-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
137 lines (107 loc) · 3.59 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
from modules import html_deliver
from modules import transfers
from modules import ratelimit
from modules import timestamp
from modules.logs import Log
from modules import cleaner
from modules import errors
from fastapi.responses import HTMLResponse, JSONResponse, FileResponse
from fastapi import FastAPI, Request, Form, File, UploadFile
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
import uvicorn
import dotenv
import os
MainLimiter = ratelimit.ClientRateLimiter("(root)", 500, 3, 180)
ApiLimiter = ratelimit.ClientRateLimiter("api/", 100, 5, 360)
api = FastAPI(
docs_url=None,
redoc_url=None,
openapi_url=None,
)
api.mount('/web/static', StaticFiles(directory="./web/static", html=True), name="static")
api.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
def build_error_response(message: str) -> JSONResponse:
return JSONResponse({
"status": False,
"error": message
}, 400)
@api.get("/")
@api.get("/{code}")
@MainLimiter.gate
async def home(request: Request, code: str = None) -> HTMLResponse:
page = html_deliver.PageContent("main")
return HTMLResponse(content=page.get())
@api.post("/api/transfer")
@ApiLimiter.gate
async def transfer(request: Request, file: UploadFile = File(...), expire: int = Form(...)) -> JSONResponse:
result = transfers.SharedFile.create_shared_file(file, expire, request.client.host)
if isinstance(result, errors.T_Error):
Log.error(f"failed to transfer file: {result}")
return build_error_response(result)
return JSONResponse({
"status": True,
"code": result.code,
"expire": timestamp.convert_to_readable(result.date_expire)
}, 200)
@api.get("/api/receive/{code}")
@ApiLimiter.gate
async def receive(code: int, request: Request) -> FileResponse:
file = transfers.get_shared_file(code)
if isinstance(file, errors.T_Error):
return build_error_response(file)
Log.info(f"Sharing file: {code}")
return FileResponse(
transfers.get_file_path(file),
filename=file.name
)
@api.delete("/api/delete/{code}")
@ApiLimiter.gate
async def delete(code: int, request: Request) -> JSONResponse:
file = transfers.get_shared_file(code)
if isinstance(file, errors.T_Error):
return build_error_response(file)
del_status = file.request_delete(request.client.host)
if isinstance(del_status, errors.T_Error):
return build_error_response(del_status)
return JSONResponse({
"status": True,
}, 200)
@api.get("/api/owned-codes")
@ApiLimiter.gate
async def fetch_owned_codes(request: Request) -> JSONResponse:
"""
response: {
code1: {
'file': str,
'expire': str
},
code2: {...}
}
"""
codes = {}
ip_addr = transfers.hash_ip(request.client.host)
for model in transfers.transfers_db.get_all_models():
if model.owner_ip == ip_addr:
codes[model.code] = {
"file": model.name,
"expire": timestamp.convert_to_readable(model.date_expire)
}
return JSONResponse({
"status": True,
"response": codes
}, 200)
if __name__ == "__main__":
env_status = dotenv.load_dotenv(".env")
if not env_status:
raise EnvironmentError("No .env file found.")
host = os.getenv("HOST") or "localhost"
port = int(os.getenv("PORT")) or 80
cleaner.Cleaner()
uvicorn.run(api, host=host, port=port)