mirror of
https://github.com/EstrellaXD/Auto_Bangumi.git
synced 2026-04-05 11:39:58 +08:00
Merge branch '3.1-dev' into webui
This commit is contained in:
@@ -25,4 +25,4 @@ if [ ! -f "$VERSION_FILE" ]; then
|
||||
echo "VERSION='DEV_VERSION'" >>"$VERSION_FILE"
|
||||
fi
|
||||
|
||||
../venv/bin/python3 main.py
|
||||
../venv/bin/uvicorn main:app --reload --port 7892
|
||||
|
||||
@@ -2,8 +2,10 @@ from datetime import timedelta
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from fastapi.security import OAuth2PasswordRequestForm
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from module.models.user import User, UserUpdate
|
||||
from module.models import APIResponse
|
||||
from module.security.api import (
|
||||
auth_user,
|
||||
get_current_user,
|
||||
@@ -22,7 +24,14 @@ async def login(form_data: OAuth2PasswordRequestForm = Depends()):
|
||||
data={"sub": user.username}, expires_delta=timedelta(days=1)
|
||||
)
|
||||
|
||||
return {"access_token": token, "token_type": "bearer", "expire": 86400}
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
content={
|
||||
"access_token": token,
|
||||
"token_type": "bearer",
|
||||
"expire": 86400,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.get("/refresh_token", response_model=dict)
|
||||
@@ -32,16 +41,29 @@ async def refresh(current_user: User = Depends(get_current_user)):
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
|
||||
)
|
||||
token = create_access_token(data={"sub": current_user.username})
|
||||
return {"access_token": token, "token_type": "bearer", "expire": 86400}
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
content={
|
||||
"access_token": token,
|
||||
"token_type": "bearer",
|
||||
"expire": 86400,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.get("/logout", response_model=dict)
|
||||
@router.get("/logout", response_model=APIResponse)
|
||||
async def logout(current_user: User = Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
|
||||
)
|
||||
return {"message": "logout success"}
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
content={
|
||||
"msg_en": "Logout success",
|
||||
"msg_zh": "登出成功",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@router.post("/update", response_model=dict)
|
||||
@@ -53,9 +75,12 @@ async def update_user(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
|
||||
)
|
||||
if update_user_info(user_data, current_user):
|
||||
return {
|
||||
"message": "update success",
|
||||
"access_token": create_access_token({"sub": user_data.username}),
|
||||
"token_type": "bearer",
|
||||
"expire": 86400,
|
||||
}
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
content={
|
||||
"message": "update success",
|
||||
"access_token": create_access_token({"sub": user_data.username}),
|
||||
"token_type": "bearer",
|
||||
"expire": 86400,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -38,7 +38,7 @@ async def update_rule(
|
||||
return u_response(resp)
|
||||
|
||||
|
||||
@router.delete("/delete/{bangumi_id}", response_model=APIResponse)
|
||||
@router.delete(path="/delete/{bangumi_id}", response_model=APIResponse)
|
||||
async def delete_rule(
|
||||
bangumi_id: str, file: bool = False, current_user=Depends(get_current_user)
|
||||
):
|
||||
@@ -49,7 +49,7 @@ async def delete_rule(
|
||||
return u_response(resp)
|
||||
|
||||
|
||||
@router.delete("/delete/many/", response_model=APIResponse)
|
||||
@router.delete(path="/delete/many/", response_model=APIResponse)
|
||||
async def delete_many_rule(
|
||||
bangumi_id: list, file: bool = False, current_user=Depends(get_current_user)
|
||||
):
|
||||
@@ -57,10 +57,11 @@ async def delete_many_rule(
|
||||
raise UNAUTHORIZED
|
||||
with TorrentManager() as manager:
|
||||
for i in bangumi_id:
|
||||
manager.delete_rule(i, file)
|
||||
resp = manager.delete_rule(i, file)
|
||||
return u_response(resp)
|
||||
|
||||
|
||||
@router.delete("/disable/{bangumi_id}", response_model=APIResponse)
|
||||
@router.delete(path="/disable/{bangumi_id}", response_model=APIResponse)
|
||||
async def disable_rule(
|
||||
bangumi_id: str, file: bool = False, current_user=Depends(get_current_user)
|
||||
):
|
||||
@@ -71,7 +72,7 @@ async def disable_rule(
|
||||
return u_response(resp)
|
||||
|
||||
|
||||
@router.delete("/disable/many/")
|
||||
@router.delete(path="/disable/many/", response_model=APIResponse)
|
||||
async def disable_many_rule(
|
||||
bangumi_id: list, file: bool = False, current_user=Depends(get_current_user)
|
||||
):
|
||||
@@ -79,10 +80,11 @@ async def disable_many_rule(
|
||||
raise UNAUTHORIZED
|
||||
with TorrentManager() as manager:
|
||||
for i in bangumi_id:
|
||||
manager.disable_rule(i, file)
|
||||
resp = manager.disable_rule(i, file)
|
||||
return u_response(resp)
|
||||
|
||||
|
||||
@router.get("/enable/{bangumi_id}", response_model=APIResponse)
|
||||
@router.get(path="/enable/{bangumi_id}", response_model=APIResponse)
|
||||
async def enable_rule(bangumi_id: str, current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise UNAUTHORIZED
|
||||
|
||||
@@ -3,16 +3,17 @@ from fastapi.responses import JSONResponse
|
||||
|
||||
from .response import u_response
|
||||
|
||||
from module.models import RSSItem, RSSUpdate, Torrent, APIResponse
|
||||
from module.rss import RSSEngine
|
||||
from module.models import RSSItem, RSSUpdate, Torrent, APIResponse, Bangumi
|
||||
from module.rss import RSSEngine, RSSAnalyser
|
||||
from module.security.api import get_current_user, UNAUTHORIZED
|
||||
from module.downloader import DownloadClient
|
||||
from module.manager import SeasonCollector
|
||||
|
||||
|
||||
router = APIRouter(prefix="/rss", tags=["rss"])
|
||||
|
||||
|
||||
@router.get("", response_model=list[RSSItem])
|
||||
@router.get(path="", response_model=list[RSSItem])
|
||||
async def get_rss(current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise UNAUTHORIZED
|
||||
@@ -20,7 +21,7 @@ async def get_rss(current_user=Depends(get_current_user)):
|
||||
return engine.rss.search_all()
|
||||
|
||||
|
||||
@router.post("/add", response_model=APIResponse)
|
||||
@router.post(path="/add", response_model=APIResponse)
|
||||
async def add_rss(rss: RSSItem, current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise UNAUTHORIZED
|
||||
@@ -29,45 +30,43 @@ async def add_rss(rss: RSSItem, current_user=Depends(get_current_user)):
|
||||
return u_response(result)
|
||||
|
||||
|
||||
@router.delete("/delete/{rss_id}", response_model=APIResponse)
|
||||
@router.delete(path="/delete/{rss_id}", response_model=APIResponse)
|
||||
async def delete_rss(rss_id: int, current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise UNAUTHORIZED
|
||||
with RSSEngine() as engine:
|
||||
result = engine.rss.delete(rss_id)
|
||||
if result:
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content={"msg_en": "Delete RSS successfully.", "msg_zh": "删除 RSS 成功。"},
|
||||
)
|
||||
else:
|
||||
return JSONResponse(
|
||||
status_code=406,
|
||||
content={"msg_en": "Delete RSS failed.", "msg_zh": "删除 RSS 失败。"},
|
||||
)
|
||||
if engine.rss.delete(rss_id):
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content={"msg_en": "Delete RSS successfully.", "msg_zh": "删除 RSS 成功。"},
|
||||
)
|
||||
else:
|
||||
return JSONResponse(
|
||||
status_code=406,
|
||||
content={"msg_en": "Delete RSS failed.", "msg_zh": "删除 RSS 失败。"},
|
||||
)
|
||||
|
||||
|
||||
@router.patch("/update/{rss_id}", response_model=APIResponse)
|
||||
@router.patch(path="/update/{rss_id}", response_model=APIResponse)
|
||||
async def update_rss(
|
||||
rss_id: int, data: RSSUpdate, current_user=Depends(get_current_user)
|
||||
):
|
||||
if not current_user:
|
||||
raise UNAUTHORIZED
|
||||
with RSSEngine() as engine:
|
||||
result = engine.rss.update(rss_id, data)
|
||||
if result:
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content={"msg_en": "Update RSS successfully.", "msg_zh": "更新 RSS 成功。"},
|
||||
)
|
||||
else:
|
||||
return JSONResponse(
|
||||
status_code=406,
|
||||
content={"msg_en": "Update RSS failed.", "msg_zh": "更新 RSS 失败。"},
|
||||
)
|
||||
if engine.rss.update(rss_id, data):
|
||||
return JSONResponse(
|
||||
status_code=200,
|
||||
content={"msg_en": "Update RSS successfully.", "msg_zh": "更新 RSS 成功。"},
|
||||
)
|
||||
else:
|
||||
return JSONResponse(
|
||||
status_code=406,
|
||||
content={"msg_en": "Update RSS failed.", "msg_zh": "更新 RSS 失败。"},
|
||||
)
|
||||
|
||||
|
||||
@router.get("/refresh/all", response_model=APIResponse)
|
||||
@router.get(path="/refresh/all", response_model=APIResponse)
|
||||
async def refresh_all(current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise UNAUTHORIZED
|
||||
@@ -79,7 +78,7 @@ async def refresh_all(current_user=Depends(get_current_user)):
|
||||
)
|
||||
|
||||
|
||||
@router.get("/refresh/{rss_id}", response_model=APIResponse)
|
||||
@router.get(path="/refresh/{rss_id}", response_model=APIResponse)
|
||||
async def refresh_rss(rss_id: int, current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise UNAUTHORIZED
|
||||
@@ -91,9 +90,41 @@ async def refresh_rss(rss_id: int, current_user=Depends(get_current_user)):
|
||||
)
|
||||
|
||||
|
||||
@router.get("/torrent/{rss_id}", response_model=list[Torrent])
|
||||
@router.get(path="/torrent/{rss_id}", response_model=list[Torrent])
|
||||
async def get_torrent(rss_id: int, current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise UNAUTHORIZED
|
||||
with RSSEngine() as engine:
|
||||
return engine.get_rss_torrents(rss_id)
|
||||
|
||||
|
||||
# Old API
|
||||
analyser = RSSAnalyser()
|
||||
|
||||
|
||||
@router.post("/analysis", response_model=Bangumi)
|
||||
async def analysis(rss: RSSItem, current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise UNAUTHORIZED
|
||||
data = analyser.link_to_data(rss)
|
||||
if isinstance(data, Bangumi):
|
||||
return data
|
||||
else:
|
||||
return u_response(data)
|
||||
|
||||
|
||||
@router.post("/collect", response_model=APIResponse)
|
||||
async def download_collection(data: Bangumi, current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise UNAUTHORIZED
|
||||
with SeasonCollector() as collector:
|
||||
resp = collector.collect_season(data, data.rss_link[0])
|
||||
return u_response(resp)
|
||||
|
||||
@router.post("/subscribe", response_model=APIResponse)
|
||||
async def subscribe(data: Bangumi, current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise UNAUTHORIZED
|
||||
with SeasonCollector() as collector:
|
||||
resp = collector.subscribe_season(data)
|
||||
return u_response(resp)
|
||||
@@ -1,7 +1,7 @@
|
||||
import logging
|
||||
|
||||
from module.downloader import DownloadClient
|
||||
from module.models import Bangumi
|
||||
from module.models import Bangumi, ResponseModel
|
||||
from module.searcher import SearchTorrent
|
||||
from module.rss import RSSEngine
|
||||
|
||||
@@ -18,7 +18,25 @@ class SeasonCollector(DownloadClient):
|
||||
torrents = st.search_season(bangumi)
|
||||
else:
|
||||
torrents = st.get_torrents(link, _filter="|".join(bangumi.filter))
|
||||
return self.add_torrent(torrents, bangumi)
|
||||
if self.add_torrent(torrents, bangumi):
|
||||
logger.info(f"Collections of {bangumi.official_title} Season {bangumi.season} completed.")
|
||||
bangumi.eps_collect = True
|
||||
with RSSEngine() as engine:
|
||||
engine.bangumi.update(bangumi)
|
||||
return ResponseModel(
|
||||
status=True,
|
||||
status_code=200,
|
||||
msg_en=f"Collections of {bangumi.official_title} Season {bangumi.season} completed.",
|
||||
msg_zh=f"收集 {bangumi.official_title} 第 {bangumi.season} 季完成。",
|
||||
)
|
||||
else:
|
||||
logger.warning(f"Collection of {bangumi.official_title} Season {bangumi.season} failed.")
|
||||
return ResponseModel(
|
||||
status=False,
|
||||
status_code=406,
|
||||
msg_en=f"Collection of {bangumi.official_title} Season {bangumi.season} failed.",
|
||||
msg_zh=f"收集 {bangumi.official_title} 第 {bangumi.season} 季失败。",
|
||||
)
|
||||
|
||||
def subscribe_season(self, data: Bangumi):
|
||||
with RSSEngine() as engine:
|
||||
@@ -29,6 +47,12 @@ class SeasonCollector(DownloadClient):
|
||||
)
|
||||
engine.bangumi.add(data)
|
||||
engine.refresh_rss(self)
|
||||
return ResponseModel(
|
||||
status=True,
|
||||
status_code=200,
|
||||
msg_en=f"Subscribe {data.official_title} successfully.",
|
||||
msg_zh=f"订阅 {data.official_title} 成功。",
|
||||
)
|
||||
|
||||
|
||||
def eps_complete():
|
||||
|
||||
@@ -143,9 +143,11 @@ class TorrentManager(Database):
|
||||
data = self.bangumi.search_id(int(_id))
|
||||
if not data:
|
||||
logger.error(f"[Manager] Can't find data with {_id}")
|
||||
return JSONResponse(
|
||||
return ResponseModel(
|
||||
status_code=406,
|
||||
content={"msg_en": f"Can't find data with {_id}", "msg_zh": f"无法找到 id {_id} 的数据"},
|
||||
status=False,
|
||||
msg_en=f"Can't find data with {_id}",
|
||||
msg_zh=f"无法找到 id {_id} 的数据",
|
||||
)
|
||||
else:
|
||||
return data
|
||||
|
||||
@@ -4,7 +4,7 @@ import re
|
||||
from .engine import RSSEngine
|
||||
|
||||
from module.conf import settings
|
||||
from module.models import Bangumi, Torrent, RSSItem
|
||||
from module.models import Bangumi, Torrent, RSSItem, ResponseModel
|
||||
from module.network import RequestContent
|
||||
from module.parser import TitleParser
|
||||
|
||||
@@ -75,9 +75,16 @@ class RSSAnalyser(TitleParser):
|
||||
else:
|
||||
return []
|
||||
|
||||
def link_to_data(self, rss: RSSItem) -> Bangumi:
|
||||
def link_to_data(self, rss: RSSItem) -> Bangumi | ResponseModel:
|
||||
torrents = self.get_rss_torrents(rss.url, False)
|
||||
for torrent in torrents:
|
||||
data = self.torrent_to_data(torrent, rss)
|
||||
if data:
|
||||
return data
|
||||
else:
|
||||
return ResponseModel(
|
||||
status=False,
|
||||
status_code=406,
|
||||
msg_en="No new title has been found.",
|
||||
msg_zh="没有找到新的番剧。",
|
||||
)
|
||||
|
||||
@@ -24,7 +24,7 @@ docker run -d \
|
||||
-v AutoBangumi_data:/app/data \
|
||||
-p 7892:7892 \
|
||||
--network=bridge \
|
||||
--dns=8.8.8.8
|
||||
--dns=8.8.8.8 \
|
||||
--restart unless-stopped \
|
||||
estrellaxd/auto_bangumi:latest
|
||||
|
||||
@@ -32,7 +32,7 @@ docker run -d \
|
||||
|
||||
### 选项2: 使用 Docker-compose 部署
|
||||
|
||||
复制以下内容到 `docker-compose.yml` 文件中,然后运行 `docker-compose up -d` 即可。
|
||||
复制以下内容到 `docker-compose.yml` 文件中。
|
||||
|
||||
```yaml
|
||||
version: "3.8"
|
||||
@@ -58,6 +58,12 @@ volumes:
|
||||
name: AutoBangumi_data
|
||||
```
|
||||
|
||||
运行以下命令启动容器。
|
||||
|
||||
```shell
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## 安装 qBittorrent
|
||||
|
||||
如果你没有安装 qBittorrent,请先安装 qBittorrent。
|
||||
|
||||
Reference in New Issue
Block a user