mirror of
https://github.com/EstrellaXD/Auto_Bangumi.git
synced 2026-04-15 02:50:42 +08:00
chore: small change in api.
This commit is contained in:
@@ -6,6 +6,7 @@ from .config import router as config_router
|
||||
from .download import router as download_router
|
||||
from .log import router as log_router
|
||||
from .program import router as program_router
|
||||
from .rss import router as rss_router
|
||||
|
||||
__all__ = "v1"
|
||||
|
||||
@@ -17,3 +18,4 @@ v1.include_router(program_router)
|
||||
v1.include_router(download_router)
|
||||
v1.include_router(bangumi_router)
|
||||
v1.include_router(config_router)
|
||||
v1.include_router(rss_router)
|
||||
|
||||
@@ -3,7 +3,7 @@ from datetime import timedelta
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from fastapi.security import OAuth2PasswordRequestForm
|
||||
|
||||
from module.models.user import User
|
||||
from module.models.user import User, UserUpdate
|
||||
from module.security.api import (
|
||||
auth_user,
|
||||
get_current_user,
|
||||
@@ -16,10 +16,11 @@ router = APIRouter(prefix="/auth", tags=["auth"])
|
||||
|
||||
@router.post("/login", response_model=dict)
|
||||
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
|
||||
username = form_data.username
|
||||
password = form_data.password
|
||||
auth_user(username, password)
|
||||
token = create_access_token(data={"sub": username}, expires_delta=timedelta(days=1))
|
||||
user = User(username=form_data.username, password=form_data.password)
|
||||
auth_user(user)
|
||||
token = create_access_token(
|
||||
data={"sub": user.username}, expires_delta=timedelta(days=1)
|
||||
)
|
||||
|
||||
return {"access_token": token, "token_type": "bearer", "expire": 86400}
|
||||
|
||||
@@ -44,7 +45,9 @@ async def logout(current_user: User = Depends(get_current_user)):
|
||||
|
||||
|
||||
@router.post("/update", response_model=dict)
|
||||
async def update_user(user_data: User, current_user: User = Depends(get_current_user)):
|
||||
async def update_user(
|
||||
user_data: UserUpdate, current_user: User = Depends(get_current_user)
|
||||
):
|
||||
if not current_user:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
|
||||
|
||||
@@ -2,13 +2,13 @@ from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from module.manager import TorrentManager
|
||||
from module.models import Bangumi
|
||||
from module.models import Bangumi, BangumiUpdate
|
||||
from module.security.api import get_current_user
|
||||
|
||||
router = APIRouter(prefix="/bangumi", tags=["bangumi"])
|
||||
|
||||
|
||||
@router.get("/getAll", response_model=list[Bangumi])
|
||||
@router.get("/get/all", response_model=list[Bangumi])
|
||||
async def get_all_data(current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise HTTPException(
|
||||
@@ -18,7 +18,7 @@ async def get_all_data(current_user=Depends(get_current_user)):
|
||||
return manager.bangumi.search_all()
|
||||
|
||||
|
||||
@router.get("/getData/{bangumi_id}", response_model=Bangumi)
|
||||
@router.get("/get/{bangumi_id}", response_model=Bangumi)
|
||||
async def get_data(bangumi_id: str, current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise HTTPException(
|
||||
@@ -28,17 +28,19 @@ async def get_data(bangumi_id: str, current_user=Depends(get_current_user)):
|
||||
return manager.search_one(bangumi_id)
|
||||
|
||||
|
||||
@router.post("/updateRule")
|
||||
async def update_rule(data: Bangumi, current_user=Depends(get_current_user)):
|
||||
@router.patch("/update/{bangumi_id}")
|
||||
async def update_rule(
|
||||
bangumi_id: int, data: BangumiUpdate, current_user=Depends(get_current_user)
|
||||
):
|
||||
if not current_user:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
|
||||
)
|
||||
with TorrentManager() as manager:
|
||||
return manager.update_rule(data)
|
||||
return manager.update_rule(bangumi_id, data)
|
||||
|
||||
|
||||
@router.delete("/deleteRule/{bangumi_id}")
|
||||
@router.delete("/delete/{bangumi_id}")
|
||||
async def delete_rule(
|
||||
bangumi_id: str, file: bool = False, current_user=Depends(get_current_user)
|
||||
):
|
||||
@@ -50,7 +52,7 @@ async def delete_rule(
|
||||
return manager.delete_rule(bangumi_id, file)
|
||||
|
||||
|
||||
@router.delete("/disableRule/{bangumi_id}")
|
||||
@router.delete("/disable/{bangumi_id}")
|
||||
async def disable_rule(
|
||||
bangumi_id: str, file: bool = False, current_user=Depends(get_current_user)
|
||||
):
|
||||
@@ -62,7 +64,7 @@ async def disable_rule(
|
||||
return manager.disable_rule(bangumi_id, file)
|
||||
|
||||
|
||||
@router.get("/enableRule/{bangumi_id}")
|
||||
@router.get("/enable/{bangumi_id}")
|
||||
async def enable_rule(bangumi_id: str, current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise HTTPException(
|
||||
@@ -72,7 +74,7 @@ async def enable_rule(bangumi_id: str, current_user=Depends(get_current_user)):
|
||||
return manager.enable_rule(bangumi_id)
|
||||
|
||||
|
||||
@router.get("/resetAll")
|
||||
@router.get("/reset/all")
|
||||
async def reset_all(current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise HTTPException(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import logging
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, status
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
from module.models import RSSItem
|
||||
from module.models import RSSItem, RSSUpdate
|
||||
from module.rss import RSSEngine
|
||||
from module.security import get_current_user
|
||||
from module.security.api import get_current_user
|
||||
from module.downloader import DownloadClient
|
||||
|
||||
|
||||
@@ -20,34 +20,36 @@ async def get_rss(current_user=Depends(get_current_user)):
|
||||
return engine.rss.search_all()
|
||||
|
||||
|
||||
@router.delete("/delete/{id}")
|
||||
async def delete_rss(_id: int, current_user=Depends(get_current_user)):
|
||||
@router.delete("/delete/{rss_id}")
|
||||
async def delete_rss(rss_id: int, current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
|
||||
)
|
||||
with RSSEngine() as engine:
|
||||
result = engine.rss.delete(_id)
|
||||
result = engine.rss.delete(rss_id)
|
||||
if result:
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
content={"status": f"Success deleted {_id}"},
|
||||
content={"status": f"Success deleted {rss_id}"},
|
||||
)
|
||||
else:
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
content={"status": f"Failed to delete {_id}"},
|
||||
content={"status": f"Failed to delete {rss_id}"},
|
||||
)
|
||||
|
||||
|
||||
@router.put("/update/{id}")
|
||||
async def update_rss(data: RSSItem, current_user=Depends(get_current_user)):
|
||||
@router.patch("/update/{rss_id}")
|
||||
async def update_rss(
|
||||
rss_id: int, data: RSSUpdate, current_user=Depends(get_current_user)
|
||||
):
|
||||
if not current_user:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
|
||||
)
|
||||
with RSSEngine() as engine:
|
||||
result = engine.rss.update(data)
|
||||
result = engine.rss.update(rss_id, data)
|
||||
if result:
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
@@ -66,8 +68,8 @@ async def refresh_all(current_user=Depends(get_current_user)):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
|
||||
)
|
||||
with RSSEngine() as engine:
|
||||
response = engine.refresh_rss()
|
||||
with RSSEngine() as engine, DownloadClient() as client:
|
||||
response = engine.refresh_rss(client)
|
||||
if response:
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
@@ -80,21 +82,21 @@ async def refresh_all(current_user=Depends(get_current_user)):
|
||||
)
|
||||
|
||||
|
||||
@router.get("/refresh/{id}")
|
||||
async def refresh_rss(_id: int, current_user=Depends(get_current_user)):
|
||||
@router.get("/refresh/{rss_id}")
|
||||
async def refresh_rss(rss_id: int, current_user=Depends(get_current_user)):
|
||||
if not current_user:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token"
|
||||
)
|
||||
with RSSEngine() as engine:
|
||||
response = engine.refresh_rss(_id)
|
||||
with RSSEngine() as engine, DownloadClient() as client:
|
||||
response = engine.refresh_rss(client, rss_id)
|
||||
if response:
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_200_OK,
|
||||
content={"status": f"Success refresh {_id}"},
|
||||
content={"status": f"Success refresh {rss_id}"},
|
||||
)
|
||||
else:
|
||||
return JSONResponse(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
content={"status": f"Failed to refresh {_id}"},
|
||||
)
|
||||
content={"status": f"Failed to refresh {rss_id}"},
|
||||
)
|
||||
|
||||
@@ -2,8 +2,7 @@ import logging
|
||||
|
||||
from sqlmodel import Session, select, delete
|
||||
|
||||
from .engine import engine
|
||||
from module.models import RSSItem
|
||||
from module.models import RSSItem, RSSUpdate
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -25,12 +24,21 @@ class RSSDatabase:
|
||||
self.session.commit()
|
||||
self.session.refresh(data)
|
||||
|
||||
def update(self, data: RSSItem):
|
||||
self.session.add(data)
|
||||
def update(self, _id: int, data: RSSUpdate):
|
||||
# Check if exists
|
||||
statement = select(RSSItem).where(RSSItem.id == _id)
|
||||
db_data = self.session.exec(statement).first()
|
||||
if not db_data:
|
||||
return False
|
||||
# Update
|
||||
dict_data = data.dict(exclude_unset=True)
|
||||
for key, value in dict_data.items():
|
||||
setattr(db_data, key, value)
|
||||
self.session.add(db_data)
|
||||
self.session.commit()
|
||||
self.session.refresh(data)
|
||||
self.session.refresh(db_data)
|
||||
return True
|
||||
|
||||
# TODO: Check if this is needed
|
||||
def search_id(self, _id: int) -> RSSItem:
|
||||
return self.session.get(RSSItem, _id)
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ class UserDatabase:
|
||||
raise HTTPException(status_code=404, detail="User not found")
|
||||
return result
|
||||
|
||||
def auth_user(self, user: UserLogin) -> bool:
|
||||
def auth_user(self, user: User) -> bool:
|
||||
statement = select(User).where(User.username == user.username)
|
||||
result = self.session.exec(statement).first()
|
||||
if not result:
|
||||
|
||||
@@ -4,7 +4,7 @@ import re
|
||||
from pathlib import Path
|
||||
|
||||
from module.conf import settings
|
||||
from module.models import Bangumi
|
||||
from module.models import Bangumi, BangumiUpdate
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -49,7 +49,7 @@ class TorrentPath:
|
||||
return self._file_depth(file_path) <= 2
|
||||
|
||||
@staticmethod
|
||||
def _gen_save_path(data: Bangumi):
|
||||
def _gen_save_path(data: Bangumi | BangumiUpdate):
|
||||
folder = (
|
||||
f"{data.official_title} ({data.year})" if data.year else data.official_title
|
||||
)
|
||||
|
||||
@@ -4,14 +4,14 @@ from fastapi.responses import JSONResponse
|
||||
|
||||
from module.database import Database
|
||||
from module.downloader import DownloadClient
|
||||
from module.models import Bangumi
|
||||
from module.models import Bangumi, BangumiUpdate
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TorrentManager(Database):
|
||||
@staticmethod
|
||||
def __match_torrents_list(data: Bangumi) -> list:
|
||||
def __match_torrents_list(data: Bangumi | BangumiUpdate) -> list:
|
||||
with DownloadClient() as client:
|
||||
torrents = client.get_torrent_info(status_filter=None)
|
||||
return [
|
||||
@@ -97,16 +97,14 @@ class TorrentManager(Database):
|
||||
status_code=406, content={"msg": f"Can't find bangumi id {_id}"}
|
||||
)
|
||||
|
||||
def update_rule(self, data: Bangumi):
|
||||
old_data = self.bangumi.search_id(data.id)
|
||||
def update_rule(self, bangumi_id, data: BangumiUpdate):
|
||||
old_data = self.bangumi.search_id(bangumi_id)
|
||||
if not old_data:
|
||||
logger.error(f"[Manager] Can't find data with {data.id}")
|
||||
return JSONResponse(
|
||||
status_code=406, content={"msg": f"Can't find data with {data.id}"}
|
||||
)
|
||||
logger.error(f"[Manager] Can't find data with {bangumi_id}")
|
||||
return {"status": False, "msg": f"Can't find data with {bangumi_id}"}
|
||||
else:
|
||||
# Move torrent
|
||||
match_list = self.__match_torrents_list(data)
|
||||
match_list = self.__match_torrents_list(old_data.save_path)
|
||||
with DownloadClient() as client:
|
||||
path = client._gen_save_path(data)
|
||||
if match_list:
|
||||
|
||||
@@ -43,7 +43,7 @@ class BangumiUpdate(SQLModel):
|
||||
subtitle: Optional[str] = Field(alias="subtitle", title="字幕")
|
||||
eps_collect: bool = Field(default=False, alias="eps_collect", title="是否已收集")
|
||||
offset: int = Field(default=0, alias="offset", title="番剧偏移量")
|
||||
filter: str = Field(default="720, \\d+-\\d+", alias="filter", title="番剧过滤器")
|
||||
filter: str = Field(default="720,\\d+-\\d+", alias="filter", title="番剧过滤器")
|
||||
rss_link: str = Field(default="", alias="rss_link", title="番剧RSS链接")
|
||||
poster_link: Optional[str] = Field(alias="poster_link", title="番剧海报链接")
|
||||
added: bool = Field(default=False, alias="added", title="是否已添加")
|
||||
|
||||
8
backend/src/module/models/response.py
Normal file
8
backend/src/module/models/response.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class ResponseModel(BaseModel):
|
||||
status: bool = Field(..., example=True)
|
||||
status_code: int = Field(..., example=200)
|
||||
msg_en: str
|
||||
msg_zh: str
|
||||
@@ -58,6 +58,7 @@ class RSSEngine(Database):
|
||||
rss_item = self.rss.search_id(rss_id)
|
||||
rss_items = [rss_item] if rss_item else []
|
||||
# From RSS Items, get all torrents
|
||||
logger.debug(f"[Engine] Get {len(rss_items)} RSS items")
|
||||
for rss_item in rss_items:
|
||||
new_torrents = self.pull_rss(rss_item)
|
||||
# Get all enabled bangumi data
|
||||
@@ -65,6 +66,7 @@ class RSSEngine(Database):
|
||||
matched_data = self.match_torrent(torrent)
|
||||
if matched_data:
|
||||
if client.add_torrent(torrent, matched_data):
|
||||
logger.debug(f"[Engine] Add torrent {torrent.name} to client")
|
||||
torrent.downloaded = True
|
||||
# Add all torrents to database
|
||||
self.torrent.add_all(new_torrents)
|
||||
|
||||
@@ -2,7 +2,7 @@ from fastapi import Depends, HTTPException, status
|
||||
from fastapi.security import OAuth2PasswordBearer
|
||||
|
||||
from module.database import Database
|
||||
from module.models.user import User
|
||||
from module.models.user import User, UserUpdate
|
||||
|
||||
from .jwt import verify_token
|
||||
|
||||
@@ -38,7 +38,7 @@ async def get_token_data(token: str = Depends(oauth2_scheme)):
|
||||
return payload
|
||||
|
||||
|
||||
def update_user_info(user_data: User, current_user):
|
||||
def update_user_info(user_data: UserUpdate, current_user):
|
||||
try:
|
||||
with Database() as db:
|
||||
db.user.update_user(current_user.username, user_data)
|
||||
@@ -47,6 +47,6 @@ def update_user_info(user_data: User, current_user):
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
|
||||
|
||||
|
||||
def auth_user(username, password):
|
||||
def auth_user(user: User):
|
||||
with Database() as db:
|
||||
db.user.auth_user(username, password)
|
||||
db.user.auth_user(user)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { BangumiRule } from '#/bangumi';
|
||||
import type { BangumiRule, BangumiUpdate } from '#/bangumi';
|
||||
import type { ApiSuccess } from '#/api';
|
||||
|
||||
export const apiBangumi = {
|
||||
@@ -7,7 +7,7 @@ export const apiBangumi = {
|
||||
* @returns 所有 bangumi 数据
|
||||
*/
|
||||
async getAll() {
|
||||
const { data } = await axios.get<BangumiRule[]>('api/v1/bangumi/getAll');
|
||||
const { data } = await axios.get<BangumiRule[]>('api/v1/bangumi/get/all');
|
||||
|
||||
return data;
|
||||
},
|
||||
@@ -19,7 +19,7 @@ export const apiBangumi = {
|
||||
*/
|
||||
async getRule(bangumiId: number) {
|
||||
const { data } = await axios.get<BangumiRule>(
|
||||
`api/v1/bangumi/getRule/${bangumiId}`
|
||||
`api/v1/bangumi/get/${bangumiId}`
|
||||
);
|
||||
|
||||
return data;
|
||||
@@ -27,12 +27,13 @@ export const apiBangumi = {
|
||||
|
||||
/**
|
||||
* 更新指定 bangumiId 的规则
|
||||
* @param bangumiData - 需要更新的规则
|
||||
* @param bangumiId - 需要更新的 bangumi 的 id
|
||||
* @param bangumiRule
|
||||
* @returns axios 请求返回的数据
|
||||
*/
|
||||
async updateRule(bangumiRule: BangumiRule) {
|
||||
const { data } = await axios.post<ApiSuccess>(
|
||||
'api/v1/bangumi/updateRule',
|
||||
async updateRule(bangumiId: number, bangumiRule: BangumiUpdate) {
|
||||
const { data } = await axios.patch<ApiSuccess>(
|
||||
`api/v1/bangumi/update/${bangumiId}`,
|
||||
bangumiRule
|
||||
);
|
||||
return data;
|
||||
@@ -46,7 +47,7 @@ export const apiBangumi = {
|
||||
*/
|
||||
async deleteRule(bangumiId: number, file: boolean) {
|
||||
const { data } = await axios.delete<ApiSuccess>(
|
||||
`api/v1/bangumi/deleteRule/${bangumiId}`,
|
||||
`api/v1/bangumi/delete/${bangumiId}`,
|
||||
{
|
||||
params: {
|
||||
file,
|
||||
@@ -64,7 +65,7 @@ export const apiBangumi = {
|
||||
*/
|
||||
async disableRule(bangumiId: number, file: boolean) {
|
||||
const { data } = await axios.delete<ApiSuccess>(
|
||||
`api/v1/bangumi/disableRule/${bangumiId}`,
|
||||
`api/v1/bangumi/disable/${bangumiId}`,
|
||||
{
|
||||
params: {
|
||||
file,
|
||||
@@ -80,7 +81,7 @@ export const apiBangumi = {
|
||||
*/
|
||||
async enableRule(bangumiId: number) {
|
||||
const { data } = await axios.get<ApiSuccess>(
|
||||
`api/v1/bangumi/enableRule/${bangumiId}`
|
||||
`api/v1/bangumi/enable/${bangumiId}`
|
||||
);
|
||||
return data;
|
||||
},
|
||||
|
||||
@@ -19,3 +19,24 @@ export interface BangumiRule {
|
||||
title_raw: string;
|
||||
year: string | null;
|
||||
}
|
||||
|
||||
export interface BangumiUpdate {
|
||||
added: boolean;
|
||||
deleted: boolean;
|
||||
dpi: string;
|
||||
eps_collect: boolean;
|
||||
filter: string;
|
||||
group_name: string;
|
||||
official_title: string;
|
||||
offset: number;
|
||||
poster_link: string | null;
|
||||
rss_link: string;
|
||||
rule_name: string;
|
||||
save_path: string;
|
||||
season: number;
|
||||
season_raw: string;
|
||||
source: string | null;
|
||||
subtitle: string;
|
||||
title_raw: string;
|
||||
year: string | null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user