Merge branch '3.1-dev' into webui

This commit is contained in:
EstrellaXD
2023-08-22 15:28:14 +08:00
8 changed files with 154 additions and 57 deletions

View File

@@ -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

View File

@@ -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,
},
)

View File

@@ -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

View File

@@ -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)

View File

@@ -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():

View File

@@ -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

View File

@@ -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="没有找到新的番剧。",
)

View File

@@ -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。