Skip to content

Commit 77d81fe

Browse files
authored
Merge pull request #100 from shinonomeow/shino_aio
feat: add torrent management and notification testing
2 parents 9b2099e + cd89148 commit 77d81fe

36 files changed

Lines changed: 880 additions & 215 deletions

backend/src/module/api/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from .program import router as program_router
99
from .rss import router as rss_router
1010
from .search import router as search_router
11+
from .torrent import router as torrent_router
1112

1213
__all__ = ["v1","lifespan"]
1314

@@ -20,3 +21,4 @@
2021
v1.include_router(config_router)
2122
v1.include_router(rss_router)
2223
v1.include_router(search_router)
24+
v1.include_router(torrent_router)

backend/src/module/api/bangumi.py

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from module.database import Database, engine
88
from module.manager import BangumiManager
9-
from module.models import APIResponse, Bangumi, BangumiUpdate, ResponseModel
9+
from module.models import APIResponse, Bangumi, BangumiUpdate, ResponseModel,Torrent
1010
from module.security.api import get_current_user
1111

1212
from .response import u_response
@@ -217,12 +217,37 @@ async def refresh_single_poster(bangumi_id: int):
217217
async def reset_all():
218218
with Database(engine) as db:
219219
db.bangumi.delete_all()
220-
return JSONResponse(
221-
status_code=200,
222-
content={
223-
"msg_en": "Reset all rules successfully.",
224-
"msg_zh": "重置所有规则成功。",
225-
},
226-
)
220+
return JSONResponse(
221+
status_code=200,
222+
content={
223+
"msg_en": "Reset all rules successfully.",
224+
"msg_zh": "重置所有规则成功。",
225+
},
226+
)
227+
228+
229+
# @router.get("/get_torrent", response_model=list[Torrent], dependencies=[Depends(get_current_user)])
230+
# async def manage_bangumi(_id:int):
231+
# """
232+
# 管理对应 Bangumi 的规则
233+
# """
234+
# try:
235+
# resp = await BangumiManager().fetch_all_bangumi_torrents(_id)
236+
# return resp
237+
# except Exception as e:
238+
# logger.error(f"[Bangumi] Error managing bangumi: {e}")
239+
# return []
240+
#
241+
# @router.get("/download_torrent", response_model=APIResponse, dependencies=[Depends(get_current_user)])
242+
# async def download_bangumi(_id:int, torrent:Torrent):
243+
# """
244+
# 手动下载对应 Bangumi 的种子
245+
# """
246+
# try:
247+
# resp = BangumiManager().download_torrent(_id,torrent)
248+
# return resp
249+
# except Exception as e:
250+
# logger.error(f"[Bangumi] Error downloading bangumi: {e}")
251+
# return []
227252

228253

backend/src/module/api/config.py

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

66
from module.conf import settings
77
from module.models import APIResponse, Config
8+
from module.models.config import Notification
89
from module.security.api import get_current_user
910

1011
router = APIRouter(prefix="/config", tags=["config"])
@@ -15,13 +16,43 @@
1516
async def get_config():
1617
return settings
1718

19+
# 测试通知的是否生效
20+
@router.post("/test_notify", response_model=APIResponse, dependencies=[Depends(get_current_user)])
21+
async def test_notify(config: Notification):
22+
try:
23+
from module.notification.notification import PostNotification
24+
from module.models import Message
25+
print(config)
26+
27+
title = "AB通知测试"
28+
link = "https://mikanani.me/images/Bangumi/202507/8a6beaff.jpg"
29+
nt = Message(title=title, season="1", episode="1", poster_path=link)
30+
sender = PostNotification()
31+
sender.initialize(config)
32+
await sender.send(nt)
33+
34+
logger.info("Notification test completed")
35+
return JSONResponse(
36+
status_code=200,
37+
content={
38+
"msg_en": "Test notification sent successfully.",
39+
"msg_zh": "测试通知发送成功。",
40+
},
41+
)
42+
except Exception as e:
43+
logger.warning(e)
44+
return JSONResponse(
45+
status_code=406,
46+
content={"msg_en": "Test notification failed.", "msg_zh": "测试通知失败。"},
47+
)
48+
1849

1950
@router.patch(
2051
"/update", response_model=APIResponse, dependencies=[Depends(get_current_user)]
2152
)
2253
async def update_config(config: Config):
2354
try:
24-
settings.save(config_dict=config.dict())
55+
settings.save(config_dict=config.model_dump())
2556
settings.load()
2657
# update_rss()
2758
logger.info("Config updated")

backend/src/module/api/torrent.py

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import logging
2+
3+
from fastapi import APIRouter, Depends, HTTPException
4+
from fastapi.responses import JSONResponse
5+
from sqlalchemy.util.concurrency import asyncio
6+
7+
from module.database import Database, engine
8+
from module.manager import BangumiManager, TorrentManager
9+
from module.models import APIResponse, Bangumi, BangumiUpdate, ResponseModel, Torrent
10+
from module.security.api import get_current_user
11+
12+
from .response import u_response
13+
14+
router = APIRouter(prefix="/torrent", tags=["torrent"])
15+
logger = logging.getLogger(__name__)
16+
17+
18+
@router.get(
19+
"/get_all",
20+
response_model=list[Torrent],
21+
dependencies=[Depends(get_current_user)],
22+
)
23+
async def manage_bangumi(_id: int):
24+
"""
25+
管理对应 Bangumi 的规则
26+
"""
27+
try:
28+
resp = await TorrentManager().fetch_all_bangumi_torrents(_id)
29+
return resp
30+
except Exception as e:
31+
logger.error(f"[Bangumi] Error managing bangumi: {e}")
32+
return []
33+
34+
35+
@router.post(
36+
"/delete",
37+
response_model=APIResponse,
38+
dependencies=[Depends(get_current_user)],
39+
)
40+
async def delete_torrent(url: str):
41+
"""
42+
删除对应的种子
43+
"""
44+
try:
45+
resp = await TorrentManager().delete_torrent(url)
46+
if resp:
47+
resp = ResponseModel(
48+
status_code=200,
49+
status=True,
50+
msg_en=f"Delete torrent for {url}",
51+
msg_zh=f"删除 {url} 的种子",
52+
)
53+
else:
54+
resp = ResponseModel(
55+
status_code=406,
56+
status=False,
57+
msg_en=f"Can't find torrent with url {url}",
58+
msg_zh=f"无法找到 url 为 {url} 的种子",
59+
)
60+
return resp
61+
except Exception as e:
62+
logger.error(f"[Bangumi] Error deleting torrent: {e}")
63+
return ResponseModel(
64+
status_code=500,
65+
status=False,
66+
msg_en="Internal server error",
67+
msg_zh="服务器内部错误",
68+
)
69+
70+
71+
@router.post("/disable",response_model=APIResponse,dependencies=[Depends(get_current_user)])
72+
async def disable_torrent(url:str,name,_id:int):
73+
"""
74+
禁用对应的种子
75+
"""
76+
try:
77+
await TorrentManager().disable_torrent(url,name, _id)
78+
return ResponseModel(
79+
status_code=200,
80+
status=True,
81+
msg_en=f"Successfully disabled torrent with url {url}",
82+
msg_zh=f"成功禁用 url 为 {url} 的种子",
83+
)
84+
except Exception as e:
85+
logger.error(f"[Bangumi] Error disabling torrent: {e}")
86+
return ResponseModel(
87+
status_code=500,
88+
status=False,
89+
msg_en="Internal server error",
90+
msg_zh="服务器内部错误",
91+
)
92+
93+
94+
@router.post(
95+
"/download",
96+
response_model=APIResponse,
97+
dependencies=[Depends(get_current_user)],
98+
)
99+
async def download_bangumi(_id: int, torrent: Torrent):
100+
"""
101+
手动下载对应 Bangumi 的种子
102+
"""
103+
try:
104+
resp = TorrentManager().download_torrent(_id, torrent)
105+
if resp:
106+
resp = ResponseModel(
107+
status_code=200,
108+
status=True,
109+
msg_en=f"Download torrent for {_id}",
110+
msg_zh=f"下载 {_id} 的种子",
111+
)
112+
else:
113+
resp = ResponseModel(
114+
status_code=406,
115+
status=False,
116+
msg_en=f"Can't find id {_id}",
117+
msg_zh=f"无法找到 id {_id}",
118+
)
119+
return resp
120+
except Exception as e:
121+
logger.error(f"[Bangumi] Error downloading bangumi: {e}")
122+
return ResponseModel(
123+
status_code=500,
124+
status=False,
125+
msg_en="Internal server error",
126+
msg_zh="服务器内部错误",
127+
)

backend/src/module/database/combine.py

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

3-
from sqlmodel import Session, SQLModel, and_, delete, false, or_, select, text
3+
from sqlmodel import Session, SQLModel, and_, false, select, text
44

55
from module.models import Bangumi, RSSItem, Torrent, User
66

backend/src/module/database/migration.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,11 @@ def check_and_upgrade_database() -> bool:
408408

409409
logger.info(f"数据库版本: {db_version}, 应用版本: {app_version}")
410410

411+
# 对 dev 版本进行特殊处理
412+
if app_version == "DEV_VERSION":
413+
logger.info("当前应用版本为开发版本,跳过数据库升级")
414+
return True
415+
411416
# 先检查应用版本是否大于数据库版本,如果不是则什么都不做
412417
version_comparison = migration._version_compare(app_version, db_version)
413418
if version_comparison <= 0:

backend/src/module/database/torrent.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ def delete_by_url(self, url: str) -> bool:
119119
)
120120
self.session.commit()
121121
return True
122+
return False
122123

123124
def delete_by_duid(self, duid: str) -> bool:
124125
stmt = select(Torrent).where(Torrent.download_uid == duid)

backend/src/module/downloader/download_client.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,6 @@ async def move_torrent(self, hashes: list[str] | str, location: str) -> bool:
249249
if not await self.wait_for_login():
250250
return False # 登录失败时返回False
251251
try:
252-
#TODO: 好像是用 | 连起来就行,但现在好像用不上了
253252
result = await self.downloader.move(hashes=hashes, new_location=location)
254253
if result:
255254
logger.info(f"[Downloader] Move torrents {hashes} to {location}")

backend/src/module/manager/bangumi.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
from module.conf import settings
55
from module.database import Database, engine
66
from module.downloader import Client as DownlondClient
7+
from module.downloader import download_queue
78
from module.manager.torrent import TorrentManager
89
from module.models import Bangumi, BangumiUpdate, Torrent
10+
from module.network import RequestContent
911
from module.parser import MikanParser, TmdbParser
1012
from module.utils import gen_save_path
1113
from module.utils.events import Event, EventType, event_bus
@@ -158,6 +160,10 @@ def search_one(self, _id: int | str):
158160
return data
159161

160162

163+
164+
165+
161166
if __name__ == "__main__":
162167
manager = TorrentManager()
163-
asyncio.run(manager.refresh_poster())
168+
manager = BangumiManager()
169+
asyncio.run(manager.fetch_all_bangumi_torrents(1))

backend/src/module/manager/renamer.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from module.conf import settings
55
from module.database import Database
66
from module.downloader import Client as download_client
7-
from module.models import EpisodeFile, Notification, SubtitleFile
7+
from module.models import EpisodeFile, Message, SubtitleFile
88
from module.models.bangumi import Bangumi
99
from module.models.torrent import Torrent
1010
from module.parser import TitleParser, TmdbParser
@@ -173,17 +173,17 @@ async def rename_file(
173173
logger.debug(f"[Renamer] {ep=} ")
174174
if result and file_type == "media":
175175
# 重命名成功, 发送通知
176-
notify_info = Notification(
176+
notify_info = Message(
177177
title=bangumi_name,
178-
season=season,
179-
episode=ep.episode,
178+
season=str(season),
179+
episode=str(ep.episode),
180180
poster_path=bangumi.poster_link if bangumi else "",
181181
)
182182
await self._publish_notification_request(notify_info)
183183

184184
return result
185185

186-
async def _publish_notification_request(self, notify_info: Notification) -> None:
186+
async def _publish_notification_request(self, notify_info: Message) -> None:
187187
"""发布下载开始事件
188188
189189
Args:
@@ -248,6 +248,8 @@ async def rename_torrent(self, torrent: Torrent, bangumi: Bangumi | None = None)
248248
return
249249
if bangumi is None:
250250
with Database() as db:
251+
#NOTE: 这里会更新一下 season 和 official_title
252+
# 可能是因为更新了番剧信息导致的
251253
bangumi = db.torrent_to_bangumi(torrent)
252254
if not bangumi:
253255
bangumi = Bangumi(

0 commit comments

Comments
 (0)