44import threading
55import random
66import asyncio
7+ from pathlib import Path
78
89from fastapi import FastAPI , Depends , UploadFile , Form , File
910from starlette .requests import Request
1314from sqlalchemy import or_ , select , update , delete
1415from sqlalchemy .ext .asyncio .session import AsyncSession
1516
17+ import settings
1618from database import get_session , Codes , init_models , engine
1719
18- app = FastAPI ()
19- if not os .path .exists ('./static' ):
20- os .makedirs ('./static' )
21- app .mount ("/static" , StaticFiles (directory = "static" ), name = "static" )
20+ app = FastAPI (debug = settings .DEBUG )
21+
22+ DATA_ROOT = Path (settings .DATA_ROOT )
23+ if not DATA_ROOT .exists ():
24+ DATA_ROOT .mkdir (parents = True )
25+
26+ STATIC_URL = settings .STATIC_URL
27+ app .mount (STATIC_URL , StaticFiles (directory = DATA_ROOT ), name = "static" )
2228
2329
2430@app .on_event ('startup' )
@@ -27,43 +33,22 @@ async def startup():
2733
2834 asyncio .create_task (delete_expire_files ())
2935
30-
31- ############################################
32- # 需要修改的参数
33- # 允许错误次数
34- error_count = 5
35- # 禁止分钟数
36- error_minute = 10
37- # 后台地址
38- admin_address = 'admin'
39- # 管理密码
40- admin_password = 'admin'
41- # 文件大小限制 10M
42- file_size_limit = 1024 * 1024 * 10
43- # 系统标题
44- title = '文件快递柜'
45- # 系统描述
46- description = 'FileCodeBox,文件快递柜,口令传送箱,匿名口令分享文本,文件,图片,视频,音频,压缩包等文件'
47- # 系统关键字
48- keywords = 'FileCodeBox,文件快递柜,口令传送箱,匿名口令分享文本,文件,图片,视频,音频,压缩包等文件'
49- ############################################
50-
5136index_html = open ('templates/index.html' , 'r' , encoding = 'utf-8' ).read () \
52- .replace ('{{title}}' , title ) \
53- .replace ('{{description}}' , description ) \
54- .replace ('{{keywords}}' , keywords )
37+ .replace ('{{title}}' , settings . TITLE ) \
38+ .replace ('{{description}}' , settings . DESCRIPTION ) \
39+ .replace ('{{keywords}}' , settings . KEYWORDS )
5540admin_html = open ('templates/admin.html' , 'r' , encoding = 'utf-8' ).read () \
56- .replace ('{{title}}' , title ) \
57- .replace ('{{description}}' , description ) \
58- .replace ('{{keywords}}' , keywords )
41+ .replace ('{{title}}' , settings . TITLE ) \
42+ .replace ('{{description}}' , settings . DESCRIPTION ) \
43+ .replace ('{{keywords}}' , settings . KEYWORDS )
5944
6045error_ip_count = {}
6146
6247
6348def delete_file (files ):
6449 for file in files :
6550 if file ['type' ] != 'text' :
66- os .remove ('.' + file ['text' ])
51+ os .remove (DATA_ROOT / file ['text' ]. lstrip ( STATIC_URL + '/' ) )
6752
6853
6954async def delete_expire_files ():
@@ -92,35 +77,36 @@ def get_file_name(key, ext, file):
9277 now = datetime .datetime .now ()
9378 file_bytes = file .file .read ()
9479 size = len (file_bytes )
95- if size > file_size_limit :
80+ if size > settings . FILE_SIZE_LIMIT :
9681 return size , '' , '' , ''
97- path = f'./static/ upload/{ now .year } /{ now .month } /{ now .day } /'
82+ path = DATA_ROOT / f" upload/{ now .year } /{ now .month } /{ now .day } /"
9883 name = f'{ key } .{ ext } '
99- if not os .path .exists (path ):
100- os .makedirs (path )
101- with open (f'{ os .path .join (path , name )} ' , 'wb' ) as f :
84+ if not path .exists ():
85+ path .mkdir (parents = True )
86+ filepath = path / name
87+ with open (filepath , 'wb' ) as f :
10288 f .write (file_bytes )
103- return size , path [ 1 :] + name , file .content_type , file .filename
89+ return size , f" { STATIC_URL } / { filepath . relative_to ( DATA_ROOT ) } " , file .content_type , file .filename
10490
10591
106- @app .get (f'/{ admin_address } ' )
92+ @app .get (f'/{ settings . ADMIN_ADDRESS } ' )
10793async def admin ():
10894 return HTMLResponse (admin_html )
10995
11096
111- @app .post (f'/{ admin_address } ' )
97+ @app .post (f'/{ settings . ADMIN_ADDRESS } ' )
11298async def admin_post (request : Request , s : AsyncSession = Depends (get_session )):
113- if request .headers .get ('pwd' ) == admin_password :
99+ if request .headers .get ('pwd' ) == settings . ADMIN_PASSWORD :
114100 query = select (Codes )
115101 codes = (await s .execute (query )).scalars ().all ()
116102 return {'code' : 200 , 'msg' : '查询成功' , 'data' : codes }
117103 else :
118104 return {'code' : 404 , 'msg' : '密码错误' }
119105
120106
121- @app .delete (f'/{ admin_address } ' )
107+ @app .delete (f'/{ settings . ADMIN_ADDRESS } ' )
122108async def admin_delete (request : Request , code : str , s : AsyncSession = Depends (get_session )):
123- if request .headers .get ('pwd' ) == admin_password :
109+ if request .headers .get ('pwd' ) == settings . ADMIN_PASSWORD :
124110 query = select (Codes ).where (Codes .code == code )
125111 file = (await s .execute (query )).scalars ().first ()
126112 await asyncio .to_thread (delete_file , [{'type' : file .type , 'text' : file .text }])
@@ -139,8 +125,8 @@ async def index():
139125def check_ip (ip ):
140126 # 检查ip是否被禁止
141127 if ip in error_ip_count :
142- if error_ip_count [ip ]['count' ] >= error_count :
143- if error_ip_count [ip ]['time' ] + datetime .timedelta (minutes = error_minute ) > datetime .datetime .now ():
128+ if error_ip_count [ip ]['count' ] >= settings . ERROR_COUNT :
129+ if error_ip_count [ip ]['time' ] + datetime .timedelta (minutes = settings . ERROR_MINUTE ) > datetime .datetime .now ():
144130 return False
145131 else :
146132 error_ip_count .pop (ip )
@@ -162,7 +148,7 @@ async def get_file(code: str, s: AsyncSession = Depends(get_session)):
162148 if info .type == 'text' :
163149 return {'code' : code , 'msg' : '查询成功' , 'data' : info .text }
164150 else :
165- return FileResponse ('.' + info .text , filename = info .name )
151+ return FileResponse (DATA_ROOT / info .text . lstrip ( STATIC_URL + '/' ) , filename = info .name )
166152 else :
167153 return {'code' : 404 , 'msg' : '口令不存在' }
168154
@@ -175,7 +161,7 @@ async def index(request: Request, code: str, s: AsyncSession = Depends(get_sessi
175161 query = select (Codes ).where (Codes .code == code )
176162 info = (await s .execute (query )).scalars ().first ()
177163 if not info :
178- return {'code' : 404 , 'msg' : f'取件码错误,错误{ error_count - ip_error (ip )} 次将被禁止10分钟' }
164+ return {'code' : 404 , 'msg' : f'取件码错误,错误{ settings . ERROR_COUNT - ip_error (ip )} 次将被禁止10分钟' }
179165 if info .exp_time < datetime .datetime .now () or info .count == 0 :
180166 threading .Thread (target = delete_file , args = ([{'type' : info .type , 'text' : info .text }],)).start ()
181167 await s .delete (info )
@@ -215,7 +201,7 @@ async def share(text: str = Form(default=None), style: str = Form(default='2'),
215201 key = uuid .uuid4 ().hex
216202 if file :
217203 size , _text , _type , name = get_file_name (key , file .filename .split ('.' )[- 1 ], file )
218- if size > file_size_limit :
204+ if size > settings . FILE_SIZE_LIMIT :
219205 return {'code' : 404 , 'msg' : '文件过大' }
220206 else :
221207 size , _text , _type , name = len (text ), text , 'text' , '文本分享'
0 commit comments