Skip to content

Commit 4fdf2ca

Browse files
authored
Merge pull request #27 from shininome/aio_beta
0.1
2 parents 7913061 + 0f2323c commit 4fdf2ca

92 files changed

Lines changed: 3285 additions & 1905 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

backend/requirements-dev.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
ruff
33
black
44
pre-commit
5-
pytest
5+
pytest
6+
pytest-asyncio

backend/requirements.txt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ fastapi==0.97.0
77
h11==0.14.0
88
idna==3.4
99
pydantic~=1.10
10-
PySocks==1.7.1
11-
qbittorrent-api==2023.9.53
12-
requests==2.31.0
10+
httpx[http2,socks]==0.25.0
1311
six==1.16.0
1412
sniffio==1.3.0
1513
soupsieve==2.4.1

backend/src/main.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33

44
import uvicorn
55
from fastapi import FastAPI, Request
6-
from fastapi.responses import FileResponse, HTMLResponse, RedirectResponse
6+
from fastapi.responses import FileResponse, RedirectResponse
77
from fastapi.staticfiles import StaticFiles
88
from fastapi.templating import Jinja2Templates
9+
910
from module.api import v1
1011
from module.conf import VERSION, settings, setup_logger
12+
from module.utils import load_image
1113

12-
setup_logger(reset=True)
14+
setup_logger()
1315
logger = logging.getLogger(__name__)
1416
uvicorn_logging_config = {
1517
"version": 1,
@@ -39,8 +41,11 @@ def create_app() -> FastAPI:
3941

4042

4143
@app.get("/posters/{path:path}", tags=["posters"])
42-
def posters(path: str):
43-
return FileResponse(f"data/posters/{path}")
44+
async def posters(path: str):
45+
post_path = f"data/posters/{path}"
46+
if not os.path.exists(post_path):
47+
await load_image(path)
48+
return FileResponse(post_path)
4449

4550

4651
if VERSION != "DEV_VERSION":
@@ -57,7 +62,9 @@ def html(request: Request, path: str):
5762
else:
5863
context = {"request": request}
5964
return templates.TemplateResponse("index.html", context)
65+
6066
else:
67+
6168
@app.get("/", status_code=302, tags=["html"])
6269
def index():
6370
return RedirectResponse("/docs")

backend/src/module/api/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from .rss import router as rss_router
99
from .search import router as search_router
1010

11-
__all__ = "v1"
11+
__all__ = ["v1"]
1212

1313
# API 1.0
1414
v1 = APIRouter(prefix="/v1")

backend/src/module/api/auth.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from datetime import timedelta
22

3-
from fastapi import APIRouter, Depends, HTTPException, status
3+
from fastapi import APIRouter, Depends
44
from fastapi.responses import JSONResponse, Response
55
from fastapi.security import OAuth2PasswordRequestForm
66

backend/src/module/api/bangumi.py

Lines changed: 61 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
from fastapi import APIRouter, Depends
22
from fastapi.responses import JSONResponse
3+
from sqlalchemy.util.concurrency import asyncio
34

5+
from module.database import Database, engine
46
from module.manager import TorrentManager
5-
from module.models import APIResponse, Bangumi, BangumiUpdate
6-
from module.security.api import UNAUTHORIZED, get_current_user
7+
from module.models import APIResponse, Bangumi, BangumiUpdate, ResponseModel
8+
from module.security.api import get_current_user
79

810
from .response import u_response
911

@@ -20,8 +22,8 @@ def str_to_list(data: Bangumi):
2022
"/get/all", response_model=list[Bangumi], dependencies=[Depends(get_current_user)]
2123
)
2224
async def get_all_data():
23-
with TorrentManager() as manager:
24-
return manager.bangumi.search_all()
25+
with Database() as db:
26+
return db.bangumi.search_all()
2527

2628

2729
@router.get(
@@ -30,8 +32,7 @@ async def get_all_data():
3032
dependencies=[Depends(get_current_user)],
3133
)
3234
async def get_data(bangumi_id: str):
33-
with TorrentManager() as manager:
34-
resp = manager.search_one(bangumi_id)
35+
resp = TorrentManager().search_one(bangumi_id)
3536
return resp
3637

3738

@@ -44,8 +45,22 @@ async def update_rule(
4445
bangumi_id: int,
4546
data: BangumiUpdate,
4647
):
47-
with TorrentManager() as manager:
48-
resp = manager.update_rule(bangumi_id, data)
48+
resp = await TorrentManager().update_rule(bangumi_id, data)
49+
if resp:
50+
resp = ResponseModel(
51+
status_code=200,
52+
status=True,
53+
msg_en=f"Update rule for {data.official_title}",
54+
msg_zh=f"更新 {data.official_title} 规则",
55+
)
56+
57+
else:
58+
resp = ResponseModel(
59+
status_code=406,
60+
status=False,
61+
msg_en=f"Can't find data with {bangumi_id}",
62+
msg_zh=f"无法找到 id {bangumi_id} 的数据",
63+
)
4964
return u_response(resp)
5065

5166

@@ -55,8 +70,21 @@ async def update_rule(
5570
dependencies=[Depends(get_current_user)],
5671
)
5772
async def delete_rule(bangumi_id: str, file: bool = False):
58-
with TorrentManager() as manager:
59-
resp = manager.delete_rule(bangumi_id, file)
73+
data,torrent_message = await TorrentManager().delete_rule(bangumi_id, file)
74+
if data:
75+
resp = ResponseModel(
76+
status_code=200,
77+
status=True,
78+
msg_en=f"Delete rule for {data.official_title}. {torrent_message.msg_en if file else ''}",
79+
msg_zh=f"删除 {data.official_title} 规则。{torrent_message.msg_zh if file else ''}",
80+
)
81+
else:
82+
resp = ResponseModel(
83+
status_code=406,
84+
status=False,
85+
msg_en=f"Can't find id {bangumi_id}",
86+
msg_zh=f"无法找到 id {bangumi_id}",
87+
)
6088
return u_response(resp)
6189

6290

@@ -66,9 +94,12 @@ async def delete_rule(bangumi_id: str, file: bool = False):
6694
dependencies=[Depends(get_current_user)],
6795
)
6896
async def delete_many_rule(bangumi_id: list, file: bool = False):
69-
with TorrentManager() as manager:
70-
for i in bangumi_id:
71-
resp = manager.delete_rule(i, file)
97+
tasks = []
98+
for i in bangumi_id:
99+
tasks.append(TorrentManager().delete_rule(i, file))
100+
101+
resp = await asyncio.gather(*tasks)
102+
resp = resp[0]
72103
return u_response(resp)
73104

74105

@@ -78,8 +109,7 @@ async def delete_many_rule(bangumi_id: list, file: bool = False):
78109
dependencies=[Depends(get_current_user)],
79110
)
80111
async def disable_rule(bangumi_id: str, file: bool = False):
81-
with TorrentManager() as manager:
82-
resp = manager.disable_rule(bangumi_id, file)
112+
resp = await TorrentManager().disable_rule(bangumi_id, file)
83113
return u_response(resp)
84114

85115

@@ -89,9 +119,11 @@ async def disable_rule(bangumi_id: str, file: bool = False):
89119
dependencies=[Depends(get_current_user)],
90120
)
91121
async def disable_many_rule(bangumi_id: list, file: bool = False):
92-
with TorrentManager() as manager:
93-
for i in bangumi_id:
94-
resp = manager.disable_rule(i, file)
122+
tasks = []
123+
for i in bangumi_id:
124+
tasks.append(TorrentManager().disable_rule(i, file))
125+
resp = await asyncio.gather(*tasks)
126+
resp = resp[-1]
95127
return u_response(resp)
96128

97129

@@ -101,8 +133,7 @@ async def disable_many_rule(bangumi_id: list, file: bool = False):
101133
dependencies=[Depends(get_current_user)],
102134
)
103135
async def enable_rule(bangumi_id: str):
104-
with TorrentManager() as manager:
105-
resp = manager.enable_rule(bangumi_id)
136+
resp = await TorrentManager().enable_rule(bangumi_id)
106137
return u_response(resp)
107138

108139

@@ -112,28 +143,30 @@ async def enable_rule(bangumi_id: str):
112143
dependencies=[Depends(get_current_user)],
113144
)
114145
async def refresh_poster():
115-
with TorrentManager() as manager:
116-
resp = manager.refresh_poster()
146+
resp = await TorrentManager().refresh_poster()
117147
return u_response(resp)
118148

149+
119150
@router.get(
120151
path="/refresh/poster/{bangumi_id}",
121152
response_model=APIResponse,
122153
dependencies=[Depends(get_current_user)],
123154
)
124-
async def refresh_poster(bangumi_id: int):
125-
with TorrentManager() as manager:
126-
resp = manager.refind_poster(bangumi_id)
155+
async def refresh_single_poster(bangumi_id: int):
156+
resp = await TorrentManager().refind_poster(bangumi_id)
127157
return u_response(resp)
128158

129159

130160
@router.get(
131161
"/reset/all", response_model=APIResponse, dependencies=[Depends(get_current_user)]
132162
)
133163
async def reset_all():
134-
with TorrentManager() as manager:
135-
manager.bangumi.delete_all()
164+
with Database(engine) as db:
165+
db.bangumi.delete_all()
136166
return JSONResponse(
137167
status_code=200,
138-
content={"msg_en": "Reset all rules successfully.", "msg_zh": "重置所有规则成功。"},
168+
content={
169+
"msg_en": "Reset all rules successfully.",
170+
"msg_zh": "重置所有规则成功。",
171+
},
139172
)

backend/src/module/api/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from module.conf import settings
77
from module.models import APIResponse, Config
8-
from module.security.api import UNAUTHORIZED, get_current_user
8+
from module.security.api import get_current_user
99

1010
router = APIRouter(prefix="/config", tags=["config"])
1111
logger = logging.getLogger(__name__)

backend/src/module/api/log.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
from module.conf import LOG_PATH
55
from module.models import APIResponse
6-
from module.security.api import UNAUTHORIZED, get_current_user
6+
from module.security.api import get_current_user
77

88
router = APIRouter(prefix="/log", tags=["log"])
99

backend/src/module/api/program.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,21 @@
1919

2020
@router.on_event("startup")
2121
async def startup():
22-
program.startup()
22+
await program.startup()
2323

2424

2525
@router.on_event("shutdown")
2626
async def shutdown():
27-
program.stop()
27+
await program.stop()
2828

2929

3030
@router.get(
3131
"/restart", response_model=APIResponse, dependencies=[Depends(get_current_user)]
3232
)
3333
async def restart():
3434
try:
35-
resp = program.restart()
35+
# resp = await program.restart()
36+
resp = await program.restart()
3637
return u_response(resp)
3738
except Exception as e:
3839
logger.debug(e)
@@ -51,7 +52,7 @@ async def restart():
5152
)
5253
async def start():
5354
try:
54-
resp = program.start()
55+
resp = await program.start()
5556
return u_response(resp)
5657
except Exception as e:
5758
logger.debug(e)
@@ -69,30 +70,30 @@ async def start():
6970
"/stop", response_model=APIResponse, dependencies=[Depends(get_current_user)]
7071
)
7172
async def stop():
72-
return u_response(program.stop())
73+
return u_response(await program.stop())
7374

7475

7576
@router.get("/status", response_model=dict, dependencies=[Depends(get_current_user)])
7677
async def program_status():
77-
if not program.is_running:
78+
if not program.program_status.is_running:
7879
return {
7980
"status": False,
8081
"version": VERSION,
81-
"first_run": program.first_run,
82+
"first_run": program.program_status.first_run,
8283
}
8384
else:
8485
return {
8586
"status": True,
8687
"version": VERSION,
87-
"first_run": program.first_run,
88+
"first_run": program.program_status.first_run,
8889
}
8990

9091

9192
@router.get(
9293
"/shutdown", response_model=APIResponse, dependencies=[Depends(get_current_user)]
9394
)
9495
async def shutdown_program():
95-
program.stop()
96+
await program.stop()
9697
logger.info("Shutting down program...")
9798
os.kill(os.getpid(), signal.SIGINT)
9899
return JSONResponse(
@@ -109,4 +110,4 @@ async def shutdown_program():
109110
dependencies=[Depends(get_current_user)],
110111
)
111112
async def check_downloader_status():
112-
return program.check_downloader()
113+
return await program.program_status.check_downloader()

backend/src/module/api/response.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
from fastapi.exceptions import HTTPException
21
from fastapi.responses import JSONResponse
32

43
from module.models.response import ResponseModel

0 commit comments

Comments
 (0)