From 3ead13f4b0846c494849b9144a1105ee882781d9 Mon Sep 17 00:00:00 2001 From: 100gle Date: Mon, 2 Oct 2023 13:16:31 +0800 Subject: [PATCH] chore(format): fix the ruff checking issue --- backend/.pre-commit-config.yaml | 7 +- backend/src/main.py | 5 +- backend/src/module/api/auth.py | 33 ++++--- backend/src/module/api/bangumi.py | 67 ++++++++++--- backend/src/module/api/config.py | 12 ++- backend/src/module/api/log.py | 6 +- backend/src/module/api/program.py | 35 ++++--- backend/src/module/api/response.py | 4 +- backend/src/module/api/rss.py | 96 ++++++++++++++----- backend/src/module/api/search.py | 20 ++-- backend/src/module/checker/checker.py | 12 ++- backend/src/module/conf/search_provider.py | 9 +- backend/src/module/core/program.py | 2 +- backend/src/module/database/bangumi.py | 14 ++- backend/src/module/database/combine.py | 10 +- backend/src/module/database/engine.py | 4 +- backend/src/module/database/rss.py | 5 +- backend/src/module/database/user.py | 22 ++--- backend/src/module/downloader/path.py | 5 +- backend/src/module/manager/collector.py | 10 +- backend/src/module/manager/torrent.py | 8 +- backend/src/module/models/__init__.py | 6 +- backend/src/module/models/bangumi.py | 4 +- backend/src/module/models/config.py | 1 + backend/src/module/models/rss.py | 3 +- backend/src/module/models/torrent.py | 5 +- backend/src/module/models/user.py | 5 +- .../src/module/network/request_contents.py | 2 +- .../src/module/parser/analyser/__init__.py | 4 +- .../src/module/parser/analyser/tmdb_parser.py | 9 +- .../module/parser/analyser/torrent_parser.py | 2 +- backend/src/module/rss/analyser.py | 6 +- backend/src/module/rss/engine.py | 22 +++-- backend/src/module/searcher/__init__.py | 2 +- backend/src/module/searcher/provider.py | 4 +- backend/src/module/searcher/searcher.py | 14 +-- backend/src/module/security/api.py | 2 +- backend/src/module/update/__init__.py | 6 +- backend/src/module/update/cross_version.py | 5 +- backend/src/module/update/data_migration.py | 2 +- backend/src/test/test_database.py | 12 +-- 41 files changed, 316 insertions(+), 186 deletions(-) diff --git a/backend/.pre-commit-config.yaml b/backend/.pre-commit-config.yaml index c51713af..c467be28 100644 --- a/backend/.pre-commit-config.yaml +++ b/backend/.pre-commit-config.yaml @@ -4,5 +4,8 @@ repos: hooks: - id: black language: python - -# TODO: add ruff lint check before committing. \ No newline at end of file +- repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.0.291 + hooks: + - id: ruff diff --git a/backend/src/main.py b/backend/src/main.py index 581d2173..d4df1c47 100644 --- a/backend/src/main.py +++ b/backend/src/main.py @@ -1,5 +1,5 @@ -import os import logging +import os import uvicorn from fastapi import FastAPI, Request @@ -8,8 +8,7 @@ from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates from module.api import v1 from module.api.proxy import router as proxy_router -from module.conf import settings, setup_logger, VERSION -from starlette.types import ASGIApp +from module.conf import VERSION, settings, setup_logger setup_logger(reset=True) logger = logging.getLogger(__name__) diff --git a/backend/src/module/api/auth.py b/backend/src/module/api/auth.py index 410ab036..8c6667c6 100644 --- a/backend/src/module/api/auth.py +++ b/backend/src/module/api/auth.py @@ -1,21 +1,21 @@ from datetime import timedelta from fastapi import APIRouter, Depends, HTTPException, status -from fastapi.security import OAuth2PasswordRequestForm from fastapi.responses import JSONResponse, Response +from fastapi.security import OAuth2PasswordRequestForm -from .response import u_response - -from module.models.user import User, UserUpdate from module.models import APIResponse +from module.models.user import User, UserUpdate from module.security.api import ( + active_user, auth_user, get_current_user, update_user_info, - active_user ) from module.security.jwt import create_access_token +from .response import u_response + router = APIRouter(prefix="/auth", tags=["auth"]) @@ -31,7 +31,10 @@ async def login(response: Response, form_data=Depends(OAuth2PasswordRequestForm) return {"access_token": token, "token_type": "bearer"} return u_response(resp) -@router.get("/refresh_token", response_model=dict, dependencies=[Depends(get_current_user)]) + +@router.get( + "/refresh_token", response_model=dict, dependencies=[Depends(get_current_user)] +) async def refresh(response: Response): token = create_access_token( data={"sub": active_user[0]}, expires_delta=timedelta(days=1) @@ -40,7 +43,9 @@ async def refresh(response: Response): return {"access_token": token, "token_type": "bearer"} -@router.get("/logout", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.get( + "/logout", response_model=APIResponse, dependencies=[Depends(get_current_user)] +) async def logout(response: Response): active_user.clear() response.delete_cookie(key="token") @@ -51,16 +56,20 @@ async def logout(response: Response): @router.post("/update", response_model=dict, dependencies=[Depends(get_current_user)]) -async def update_user( - user_data: UserUpdate, response: Response -): +async def update_user(user_data: UserUpdate, response: Response): old_user = active_user[0] if update_user_info(user_data, old_user): - token = create_access_token(data={"sub": old_user}, expires_delta=timedelta(days=1)) + token = create_access_token( + data={"sub": old_user}, expires_delta=timedelta(days=1) + ) response.set_cookie( key="token", value=token, httponly=True, max_age=86400, ) - return {"access_token": token, "token_type": "bearer", "message": "update success"} + return { + "access_token": token, + "token_type": "bearer", + "message": "update success", + } diff --git a/backend/src/module/api/bangumi.py b/backend/src/module/api/bangumi.py index c912f978..b0e1deb5 100644 --- a/backend/src/module/api/bangumi.py +++ b/backend/src/module/api/bangumi.py @@ -1,11 +1,11 @@ from fastapi import APIRouter, Depends from fastapi.responses import JSONResponse -from .response import u_response - from module.manager import TorrentManager -from module.models import Bangumi, BangumiUpdate, APIResponse -from module.security.api import get_current_user, UNAUTHORIZED +from module.models import APIResponse, Bangumi, BangumiUpdate +from module.security.api import UNAUTHORIZED, get_current_user + +from .response import u_response router = APIRouter(prefix="/bangumi", tags=["bangumi"]) @@ -16,36 +16,55 @@ def str_to_list(data: Bangumi): return data -@router.get("/get/all", response_model=list[Bangumi], dependencies=[Depends(get_current_user)]) +@router.get( + "/get/all", response_model=list[Bangumi], dependencies=[Depends(get_current_user)] +) async def get_all_data(): with TorrentManager() as manager: return manager.bangumi.search_all() -@router.get("/get/{bangumi_id}", response_model=Bangumi, dependencies=[Depends(get_current_user)]) +@router.get( + "/get/{bangumi_id}", + response_model=Bangumi, + dependencies=[Depends(get_current_user)], +) async def get_data(bangumi_id: str): with TorrentManager() as manager: resp = manager.search_one(bangumi_id) return resp -@router.patch("/update/{bangumi_id}", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.patch( + "/update/{bangumi_id}", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) async def update_rule( - bangumi_id: int, data: BangumiUpdate, + bangumi_id: int, + data: BangumiUpdate, ): with TorrentManager() as manager: resp = manager.update_rule(bangumi_id, data) return u_response(resp) -@router.delete(path="/delete/{bangumi_id}", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.delete( + path="/delete/{bangumi_id}", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) async def delete_rule(bangumi_id: str, file: bool = False): with TorrentManager() as manager: resp = manager.delete_rule(bangumi_id, file) return u_response(resp) -@router.delete(path="/delete/many/", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.delete( + path="/delete/many/", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) async def delete_many_rule(bangumi_id: list, file: bool = False): with TorrentManager() as manager: for i in bangumi_id: @@ -53,14 +72,22 @@ async def delete_many_rule(bangumi_id: list, file: bool = False): return u_response(resp) -@router.delete(path="/disable/{bangumi_id}", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.delete( + path="/disable/{bangumi_id}", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) async def disable_rule(bangumi_id: str, file: bool = False): with TorrentManager() as manager: resp = manager.disable_rule(bangumi_id, file) return u_response(resp) -@router.delete(path="/disable/many/", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.delete( + path="/disable/many/", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) async def disable_many_rule(bangumi_id: list, file: bool = False): with TorrentManager() as manager: for i in bangumi_id: @@ -68,21 +95,31 @@ async def disable_many_rule(bangumi_id: list, file: bool = False): return u_response(resp) -@router.get(path="/enable/{bangumi_id}", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.get( + path="/enable/{bangumi_id}", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) async def enable_rule(bangumi_id: str): with TorrentManager() as manager: resp = manager.enable_rule(bangumi_id) return u_response(resp) -@router.get(path="/refresh/poster/all", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.get( + path="/refresh/poster/all", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) async def refresh_poster(): with TorrentManager() as manager: resp = manager.refresh_poster() return u_response(resp) -@router.get("/reset/all", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.get( + "/reset/all", response_model=APIResponse, dependencies=[Depends(get_current_user)] +) async def reset_all(): with TorrentManager() as manager: manager.bangumi.delete_all() diff --git a/backend/src/module/api/config.py b/backend/src/module/api/config.py index 3b307599..1f798243 100644 --- a/backend/src/module/api/config.py +++ b/backend/src/module/api/config.py @@ -4,8 +4,8 @@ from fastapi import APIRouter, Depends from fastapi.responses import JSONResponse from module.conf import settings -from module.models import Config, APIResponse -from module.security.api import get_current_user, UNAUTHORIZED +from module.models import APIResponse, Config +from module.security.api import UNAUTHORIZED, get_current_user router = APIRouter(prefix="/config", tags=["config"]) logger = logging.getLogger(__name__) @@ -16,7 +16,9 @@ async def get_config(): return settings -@router.patch("/update", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.patch( + "/update", response_model=APIResponse, dependencies=[Depends(get_current_user)] +) async def update_config(config: Config): try: settings.save(config_dict=config.dict()) @@ -25,11 +27,11 @@ async def update_config(config: Config): logger.info("Config updated") return JSONResponse( status_code=200, - content={"msg_en": "Update config successfully.", "msg_zh": "更新配置成功。"} + content={"msg_en": "Update config successfully.", "msg_zh": "更新配置成功。"}, ) except Exception as e: logger.warning(e) return JSONResponse( status_code=406, - content={"msg_en": "Update config failed.", "msg_zh": "更新配置失败。"} + content={"msg_en": "Update config failed.", "msg_zh": "更新配置失败。"}, ) diff --git a/backend/src/module/api/log.py b/backend/src/module/api/log.py index 04d1434d..57b7e104 100644 --- a/backend/src/module/api/log.py +++ b/backend/src/module/api/log.py @@ -2,8 +2,8 @@ from fastapi import APIRouter, Depends, HTTPException, Response, status from fastapi.responses import JSONResponse from module.conf import LOG_PATH -from module.security.api import get_current_user, UNAUTHORIZED from module.models import APIResponse +from module.security.api import UNAUTHORIZED, get_current_user router = APIRouter(prefix="/log", tags=["log"]) @@ -17,7 +17,9 @@ async def get_log(): return Response("Log file not found", status_code=404) -@router.get("/clear", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.get( + "/clear", response_model=APIResponse, dependencies=[Depends(get_current_user)] +) async def clear_log(): if LOG_PATH.exists(): LOG_PATH.write_text("") diff --git a/backend/src/module/api/program.py b/backend/src/module/api/program.py index 691bd149..e750f3d2 100644 --- a/backend/src/module/api/program.py +++ b/backend/src/module/api/program.py @@ -5,12 +5,12 @@ import signal from fastapi import APIRouter, Depends, HTTPException from fastapi.responses import JSONResponse -from .response import u_response - +from module.conf import VERSION from module.core import Program from module.models import APIResponse -from module.conf import VERSION -from module.security.api import get_current_user, UNAUTHORIZED +from module.security.api import UNAUTHORIZED, get_current_user + +from .response import u_response logger = logging.getLogger(__name__) program = Program() @@ -27,7 +27,9 @@ async def shutdown(): program.stop() -@router.get("/restart", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.get( + "/restart", response_model=APIResponse, dependencies=[Depends(get_current_user)] +) async def restart(): try: resp = program.restart() @@ -40,11 +42,13 @@ async def restart(): detail={ "msg_en": "Failed to restart program.", "msg_zh": "重启程序失败。", - } + }, ) -@router.get("/start", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.get( + "/start", response_model=APIResponse, dependencies=[Depends(get_current_user)] +) async def start(): try: resp = program.start() @@ -57,11 +61,13 @@ async def start(): detail={ "msg_en": "Failed to start program.", "msg_zh": "启动程序失败。", - } + }, ) -@router.get("/stop", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.get( + "/stop", response_model=APIResponse, dependencies=[Depends(get_current_user)] +) async def stop(): return u_response(program.stop()) @@ -82,7 +88,9 @@ async def program_status(): } -@router.get("/shutdown", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.get( + "/shutdown", response_model=APIResponse, dependencies=[Depends(get_current_user)] +) async def shutdown_program(): program.stop() logger.info("Shutting down program...") @@ -94,6 +102,11 @@ async def shutdown_program(): # Check status -@router.get("/check/downloader", tags=["check"], response_model=bool, dependencies=[Depends(get_current_user)]) +@router.get( + "/check/downloader", + tags=["check"], + response_model=bool, + dependencies=[Depends(get_current_user)], +) async def check_downloader_status(): return program.check_downloader() diff --git a/backend/src/module/api/response.py b/backend/src/module/api/response.py index b0a2dc26..a44581c5 100644 --- a/backend/src/module/api/response.py +++ b/backend/src/module/api/response.py @@ -1,5 +1,5 @@ -from fastapi.responses import JSONResponse from fastapi.exceptions import HTTPException +from fastapi.responses import JSONResponse from module.models.response import ResponseModel @@ -11,4 +11,4 @@ def u_response(response_model: ResponseModel): "msg_en": response_model.msg_en, "msg_zh": response_model.msg_zh, }, - ) \ No newline at end of file + ) diff --git a/backend/src/module/api/rss.py b/backend/src/module/api/rss.py index 2244c67d..d2de16fe 100644 --- a/backend/src/module/api/rss.py +++ b/backend/src/module/api/rss.py @@ -1,39 +1,52 @@ from fastapi import APIRouter, Depends from fastapi.responses import JSONResponse -from .response import u_response - -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 +from module.models import APIResponse, Bangumi, RSSItem, RSSUpdate, Torrent +from module.rss import RSSAnalyser, RSSEngine +from module.security.api import UNAUTHORIZED, get_current_user +from .response import u_response router = APIRouter(prefix="/rss", tags=["rss"]) -@router.get(path="", response_model=list[RSSItem], dependencies=[Depends(get_current_user)]) +@router.get( + path="", response_model=list[RSSItem], dependencies=[Depends(get_current_user)] +) async def get_rss(): with RSSEngine() as engine: return engine.rss.search_all() -@router.post(path="/add", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.post( + path="/add", response_model=APIResponse, dependencies=[Depends(get_current_user)] +) async def add_rss(rss: RSSItem): with RSSEngine() as engine: result = engine.add_rss(rss.url, rss.name, rss.aggregate, rss.parser) return u_response(result) -@router.post(path="/enable/many", response_model=APIResponse, dependencies=[Depends(get_current_user)]) -async def enable_many_rss(rss_ids: list[int], ): +@router.post( + path="/enable/many", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) +async def enable_many_rss( + rss_ids: list[int], +): with RSSEngine() as engine: result = engine.enable_list(rss_ids) return u_response(result) -@router.delete(path="/delete/{rss_id}", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.delete( + path="/delete/{rss_id}", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) async def delete_rss(rss_id: int): with RSSEngine() as engine: if engine.rss.delete(rss_id): @@ -48,14 +61,24 @@ async def delete_rss(rss_id: int): ) -@router.post(path="/delete/many", response_model=APIResponse, dependencies=[Depends(get_current_user)]) -async def delete_many_rss(rss_ids: list[int], ): +@router.post( + path="/delete/many", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) +async def delete_many_rss( + rss_ids: list[int], +): with RSSEngine() as engine: result = engine.delete_list(rss_ids) return u_response(result) -@router.patch(path="/disable/{rss_id}", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.patch( + path="/disable/{rss_id}", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) async def disable_rss(rss_id: int): with RSSEngine() as engine: if engine.rss.disable(rss_id): @@ -70,14 +93,22 @@ async def disable_rss(rss_id: int): ) -@router.post(path="/disable/many", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.post( + path="/disable/many", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) async def disable_many_rss(rss_ids: list[int]): with RSSEngine() as engine: result = engine.disable_list(rss_ids) return u_response(result) -@router.patch(path="/update/{rss_id}", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.patch( + path="/update/{rss_id}", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) async def update_rss( rss_id: int, data: RSSUpdate, current_user=Depends(get_current_user) ): @@ -96,7 +127,11 @@ async def update_rss( ) -@router.get(path="/refresh/all", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.get( + path="/refresh/all", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) async def refresh_all(): with RSSEngine() as engine, DownloadClient() as client: engine.refresh_rss(client) @@ -106,7 +141,11 @@ async def refresh_all(): ) -@router.get(path="/refresh/{rss_id}", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.get( + path="/refresh/{rss_id}", + response_model=APIResponse, + dependencies=[Depends(get_current_user)], +) async def refresh_rss(rss_id: int): with RSSEngine() as engine, DownloadClient() as client: engine.refresh_rss(client, rss_id) @@ -116,8 +155,14 @@ async def refresh_rss(rss_id: int): ) -@router.get(path="/torrent/{rss_id}", response_model=list[Torrent], dependencies=[Depends(get_current_user)]) -async def get_torrent(rss_id: int, ): +@router.get( + path="/torrent/{rss_id}", + response_model=list[Torrent], + dependencies=[Depends(get_current_user)], +) +async def get_torrent( + rss_id: int, +): with RSSEngine() as engine: return engine.get_rss_torrents(rss_id) @@ -126,7 +171,9 @@ async def get_torrent(rss_id: int, ): analyser = RSSAnalyser() -@router.post("/analysis", response_model=Bangumi, dependencies=[Depends(get_current_user)]) +@router.post( + "/analysis", response_model=Bangumi, dependencies=[Depends(get_current_user)] +) async def analysis(rss: RSSItem): data = analyser.link_to_data(rss) if isinstance(data, Bangumi): @@ -135,16 +182,19 @@ async def analysis(rss: RSSItem): return u_response(data) -@router.post("/collect", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.post( + "/collect", response_model=APIResponse, dependencies=[Depends(get_current_user)] +) async def download_collection(data: Bangumi): with SeasonCollector() as collector: resp = collector.collect_season(data, data.rss_link) return u_response(resp) -@router.post("/subscribe", response_model=APIResponse, dependencies=[Depends(get_current_user)]) +@router.post( + "/subscribe", response_model=APIResponse, dependencies=[Depends(get_current_user)] +) async def subscribe(data: Bangumi): with SeasonCollector() as collector: resp = collector.subscribe_season(data) return u_response(resp) - diff --git a/backend/src/module/api/search.py b/backend/src/module/api/search.py index 3ad90984..220a5c91 100644 --- a/backend/src/module/api/search.py +++ b/backend/src/module/api/search.py @@ -1,19 +1,17 @@ -from fastapi import APIRouter, Query, Depends +from fastapi import APIRouter, Depends, Query from sse_starlette.sse import EventSourceResponse -from module.searcher import SearchTorrent, SEARCH_CONFIG -from module.security.api import get_current_user, UNAUTHORIZED from module.models import Bangumi - +from module.searcher import SEARCH_CONFIG, SearchTorrent +from module.security.api import UNAUTHORIZED, get_current_user router = APIRouter(prefix="/search", tags=["search"]) -@router.get("/bangumi", response_model=list[Bangumi], dependencies=[Depends(get_current_user)]) -async def search_torrents( - site: str = "mikan", - keywords: str = Query(None) -): +@router.get( + "/bangumi", response_model=list[Bangumi], dependencies=[Depends(get_current_user)] +) +async def search_torrents(site: str = "mikan", keywords: str = Query(None)): """ Server Send Event for per Bangumi item """ @@ -26,6 +24,8 @@ async def search_torrents( ) -@router.get("/provider", response_model=list[str], dependencies=[Depends(get_current_user)]) +@router.get( + "/provider", response_model=list[str], dependencies=[Depends(get_current_user)] +) async def search_provider(): return list(SEARCH_CONFIG.keys()) diff --git a/backend/src/module/checker/checker.py b/backend/src/module/checker/checker.py index 09fc222c..b39e312d 100644 --- a/backend/src/module/checker/checker.py +++ b/backend/src/module/checker/checker.py @@ -1,8 +1,9 @@ import logging -import requests from pathlib import Path -from module.conf import settings, VERSION +import requests + +from module.conf import VERSION, settings from module.downloader import DownloadClient from module.models import Config from module.update import version_check @@ -50,7 +51,11 @@ class Checker: @staticmethod def check_downloader() -> bool: try: - url = f"http://{settings.downloader.host}" if "://" not in settings.downloader.host else f"{settings.downloader.host}" + url = ( + f"http://{settings.downloader.host}" + if "://" not in settings.downloader.host + else f"{settings.downloader.host}" + ) response = requests.get(url, timeout=2) if settings.downloader.type in response.text.lower(): with DownloadClient() as client: @@ -74,4 +79,3 @@ class Checker: if __name__ == "__main__": # print(Checker().check_downloader()) requests.get("http://162.200.20.1", timeout=2) - diff --git a/backend/src/module/conf/search_provider.py b/backend/src/module/conf/search_provider.py index 610c7f55..b372b324 100644 --- a/backend/src/module/conf/search_provider.py +++ b/backend/src/module/conf/search_provider.py @@ -1,10 +1,11 @@ from pathlib import Path + from module.utils import json_config DEFAULT_PROVIDER = { - "mikan": "https://mikanani.me/RSS/Search?searchstr=%s", - "nyaa": "https://nyaa.si/?page=rss&q=%s&c=0_0&f=0", - "dmhy": "http://dmhy.org/topics/rss/rss.xml?keyword=%s" + "mikan": "https://mikanani.me/RSS/Search?searchstr=%s", + "nyaa": "https://nyaa.si/?page=rss&q=%s&c=0_0&f=0", + "dmhy": "http://dmhy.org/topics/rss/rss.xml?keyword=%s", } PROVIDER_PATH = Path("config/search_provider.json") @@ -19,5 +20,3 @@ def load_provider(): SEARCH_CONFIG = load_provider() - - diff --git a/backend/src/module/core/program.py b/backend/src/module/core/program.py index fa7ee3ec..0a50da47 100644 --- a/backend/src/module/core/program.py +++ b/backend/src/module/core/program.py @@ -1,8 +1,8 @@ import logging from module.conf import VERSION, settings -from module.update import data_migration, from_30_to_31, start_up, first_run from module.models import ResponseModel +from module.update import data_migration, first_run, from_30_to_31, start_up from .sub_thread import RenameThread, RSSThread diff --git a/backend/src/module/database/bangumi.py b/backend/src/module/database/bangumi.py index d9d3db09..05a7409b 100644 --- a/backend/src/module/database/bangumi.py +++ b/backend/src/module/database/bangumi.py @@ -1,9 +1,9 @@ import logging - -from sqlmodel import Session, select, delete, or_, and_ -from sqlalchemy.sql import func from typing import Optional +from sqlalchemy.sql import func +from sqlmodel import Session, and_, delete, false, or_, select + from module.models import Bangumi, BangumiUpdate logger = logging.getLogger(__name__) @@ -128,14 +128,18 @@ class BangumiDatabase: statement = select(Bangumi).where( and_( func.instr(torrent_name, Bangumi.title_raw) > 0, - Bangumi.deleted == False, + # use `false()` to avoid E712 checking + # see: https://docs.astral.sh/ruff/rules/true-false-comparison/ + Bangumi.deleted == false(), ) ) return self.session.exec(statement).first() def not_complete(self) -> list[Bangumi]: # Find eps_complete = False - condition = select(Bangumi).where(Bangumi.eps_collect == False) + # use `false()` to avoid E712 checking + # see: https://docs.astral.sh/ruff/rules/true-false-comparison/ + condition = select(Bangumi).where(Bangumi.eps_collect == false()) datas = self.session.exec(condition).all() return datas diff --git a/backend/src/module/database/combine.py b/backend/src/module/database/combine.py index 41550134..a809b748 100644 --- a/backend/src/module/database/combine.py +++ b/backend/src/module/database/combine.py @@ -1,12 +1,12 @@ from sqlmodel import Session, SQLModel +from module.models import Bangumi, User + +from .bangumi import BangumiDatabase +from .engine import engine as e from .rss import RSSDatabase from .torrent import TorrentDatabase -from .bangumi import BangumiDatabase from .user import UserDatabase -from .engine import engine as e - -from module.models import User, Bangumi class Database(Session): @@ -40,5 +40,3 @@ class Database(Session): self.bangumi.add_all(readd_bangumi) self.add(User(**user_data[0])) self.commit() - - diff --git a/backend/src/module/database/engine.py b/backend/src/module/database/engine.py index 94fa37b0..c94e792c 100644 --- a/backend/src/module/database/engine.py +++ b/backend/src/module/database/engine.py @@ -1,6 +1,6 @@ -from sqlmodel import create_engine, Session -from module.conf import DATA_PATH +from sqlmodel import Session, create_engine +from module.conf import DATA_PATH engine = create_engine(DATA_PATH) diff --git a/backend/src/module/database/rss.py b/backend/src/module/database/rss.py index cfc229b2..99a00abe 100644 --- a/backend/src/module/database/rss.py +++ b/backend/src/module/database/rss.py @@ -1,6 +1,6 @@ import logging -from sqlmodel import Session, select, delete, and_ +from sqlmodel import Session, and_, delete, select from module.models import RSSItem, RSSUpdate @@ -66,7 +66,6 @@ class RSSDatabase: self.session.refresh(db_data) return True - def search_id(self, _id: int) -> RSSItem: return self.session.get(RSSItem, _id) @@ -88,7 +87,7 @@ class RSSDatabase: self.session.commit() return True except Exception as e: - logger.error("Delete RSS Item failed.") + logger.error(f"Delete RSS Item failed. Because: {e}") return False def delete_all(self): diff --git a/backend/src/module/database/user.py b/backend/src/module/database/user.py index fdfa6464..dc01a9b0 100644 --- a/backend/src/module/database/user.py +++ b/backend/src/module/database/user.py @@ -1,12 +1,12 @@ import logging from fastapi import HTTPException - -from module.models.user import User, UserUpdate, UserLogin -from module.models import ResponseModel -from module.security.jwt import get_password_hash, verify_password from sqlmodel import Session, select +from module.models import ResponseModel +from module.models.user import User, UserLogin, UserUpdate +from module.security.jwt import get_password_hash, verify_password + logger = logging.getLogger(__name__) @@ -26,23 +26,17 @@ class UserDatabase: result = self.session.exec(statement).first() if not result: return ResponseModel( - status_code=401, - status=False, - msg_en="User not found", - msg_zh="用户不存在" + status_code=401, status=False, msg_en="User not found", msg_zh="用户不存在" ) if not verify_password(user.password, result.password): return ResponseModel( status_code=401, status=False, msg_en="Incorrect password", - msg_zh="密码错误" + msg_zh="密码错误", ) return ResponseModel( - status_code=200, - status=True, - msg_en="Login successfully", - msg_zh="登录成功" + status_code=200, status=True, msg_en="Login successfully", msg_zh="登录成功" ) def update_user(self, username, update_user: UserUpdate): @@ -91,7 +85,7 @@ class UserDatabase: statement = select(User) try: result = self.session.exec(statement).all() - except Exception as e: + except Exception: self.merge_old_user() result = self.session.exec(statement).all() if len(result) != 0: diff --git a/backend/src/module/downloader/path.py b/backend/src/module/downloader/path.py index af582feb..07b7d7dc 100644 --- a/backend/src/module/downloader/path.py +++ b/backend/src/module/downloader/path.py @@ -1,8 +1,8 @@ import logging -from os import PathLike import re +from os import PathLike -from module.conf import settings, PLATFORM +from module.conf import PLATFORM, settings from module.models import Bangumi, BangumiUpdate logger = logging.getLogger(__name__) @@ -72,4 +72,3 @@ class TorrentPath: @staticmethod def _join_path(*args): return str(Path(*args)) - diff --git a/backend/src/module/manager/collector.py b/backend/src/module/manager/collector.py index 9ee93a67..f447649d 100644 --- a/backend/src/module/manager/collector.py +++ b/backend/src/module/manager/collector.py @@ -2,8 +2,8 @@ import logging from module.downloader import DownloadClient from module.models import Bangumi, ResponseModel -from module.searcher import SearchTorrent from module.rss import RSSEngine +from module.searcher import SearchTorrent logger = logging.getLogger(__name__) @@ -19,7 +19,9 @@ class SeasonCollector(DownloadClient): else: torrents = st.get_torrents(link, bangumi.filter.replace(",", "|")) if self.add_torrent(torrents, bangumi): - logger.info(f"Collections of {bangumi.official_title} Season {bangumi.season} completed.") + logger.info( + f"Collections of {bangumi.official_title} Season {bangumi.season} completed." + ) bangumi.eps_collect = True with RSSEngine() as engine: engine.bangumi.update(bangumi) @@ -31,7 +33,9 @@ class SeasonCollector(DownloadClient): msg_zh=f"收集 {bangumi.official_title} 第 {bangumi.season} 季完成。", ) else: - logger.warning(f"Collection of {bangumi.official_title} Season {bangumi.season} failed.") + logger.warning( + f"Collection of {bangumi.official_title} Season {bangumi.season} failed." + ) return ResponseModel( status=False, status_code=406, diff --git a/backend/src/module/manager/torrent.py b/backend/src/module/manager/torrent.py index 58cbed69..9c7cc181 100644 --- a/backend/src/module/manager/torrent.py +++ b/backend/src/module/manager/torrent.py @@ -1,6 +1,5 @@ import logging - from module.database import Database from module.downloader import DownloadClient from module.models import Bangumi, BangumiUpdate, ResponseModel @@ -142,8 +141,8 @@ class TorrentManager(Database): return ResponseModel( status_code=200, status=True, - msg_en=f"Refresh poster link successfully.", - msg_zh=f"刷新海报链接成功。", + msg_en="Refresh poster link successfully.", + msg_zh="刷新海报链接成功。", ) def search_all_bangumi(self): @@ -165,6 +164,7 @@ class TorrentManager(Database): else: return data -if __name__ == '__main__': + +if __name__ == "__main__": with TorrentManager() as manager: manager.refresh_poster() diff --git a/backend/src/module/models/__init__.py b/backend/src/module/models/__init__.py index 7a00b90d..bd50c0ec 100644 --- a/backend/src/module/models/__init__.py +++ b/backend/src/module/models/__init__.py @@ -1,6 +1,6 @@ -from .bangumi import Bangumi, Episode, BangumiUpdate, Notification +from .bangumi import Bangumi, BangumiUpdate, Episode, Notification from .config import Config +from .response import APIResponse, ResponseModel from .rss import RSSItem, RSSUpdate from .torrent import EpisodeFile, SubtitleFile, Torrent, TorrentUpdate -from .user import UserLogin, User, UserUpdate -from .response import ResponseModel, APIResponse +from .user import User, UserLogin, UserUpdate diff --git a/backend/src/module/models/bangumi.py b/backend/src/module/models/bangumi.py index 82ee9747..ebdaa5ee 100644 --- a/backend/src/module/models/bangumi.py +++ b/backend/src/module/models/bangumi.py @@ -1,8 +1,8 @@ from dataclasses import dataclass +from typing import Optional from pydantic import BaseModel -from sqlmodel import SQLModel, Field -from typing import Optional +from sqlmodel import Field, SQLModel class Bangumi(SQLModel, table=True): diff --git a/backend/src/module/models/config.py b/backend/src/module/models/config.py index ddbdef14..22d1c6eb 100644 --- a/backend/src/module/models/config.py +++ b/backend/src/module/models/config.py @@ -1,4 +1,5 @@ from os.path import expandvars + from pydantic import BaseModel, Field diff --git a/backend/src/module/models/rss.py b/backend/src/module/models/rss.py index 7275bb12..a2d9d58f 100644 --- a/backend/src/module/models/rss.py +++ b/backend/src/module/models/rss.py @@ -1,6 +1,7 @@ -from sqlmodel import SQLModel, Field from typing import Optional +from sqlmodel import Field, SQLModel + class RSSItem(SQLModel, table=True): id: int = Field(default=None, primary_key=True, alias="id") diff --git a/backend/src/module/models/torrent.py b/backend/src/module/models/torrent.py index 57e818a3..e4727202 100644 --- a/backend/src/module/models/torrent.py +++ b/backend/src/module/models/torrent.py @@ -1,7 +1,8 @@ -from pydantic import BaseModel -from sqlmodel import SQLModel, Field from typing import Optional +from pydantic import BaseModel +from sqlmodel import Field, SQLModel + class Torrent(SQLModel, table=True): id: int = Field(default=None, primary_key=True, alias="id") diff --git a/backend/src/module/models/user.py b/backend/src/module/models/user.py index 3e5cef29..ba78e827 100644 --- a/backend/src/module/models/user.py +++ b/backend/src/module/models/user.py @@ -1,6 +1,7 @@ -from pydantic import BaseModel from typing import Optional -from sqlmodel import SQLModel, Field + +from pydantic import BaseModel +from sqlmodel import Field, SQLModel class User(SQLModel, table=True): diff --git a/backend/src/module/network/request_contents.py b/backend/src/module/network/request_contents.py index c355d56a..9ab927bb 100644 --- a/backend/src/module/network/request_contents.py +++ b/backend/src/module/network/request_contents.py @@ -1,5 +1,5 @@ -import re import logging +import re import xml.etree.ElementTree from module.conf import settings diff --git a/backend/src/module/parser/analyser/__init__.py b/backend/src/module/parser/analyser/__init__.py index de25942b..6e949f10 100644 --- a/backend/src/module/parser/analyser/__init__.py +++ b/backend/src/module/parser/analyser/__init__.py @@ -1,5 +1,5 @@ +from .mikan_parser import mikan_parser +from .openai import OpenAIParser from .raw_parser import raw_parser from .tmdb_parser import tmdb_parser from .torrent_parser import torrent_parser -from .mikan_parser import mikan_parser -from .openai import OpenAIParser diff --git a/backend/src/module/parser/analyser/tmdb_parser.py b/backend/src/module/parser/analyser/tmdb_parser.py index b98ff262..cbab5dcd 100644 --- a/backend/src/module/parser/analyser/tmdb_parser.py +++ b/backend/src/module/parser/analyser/tmdb_parser.py @@ -5,7 +5,6 @@ from dataclasses import dataclass from module.conf import TMDB_API from module.network import RequestContent - TMDB_URL = "https://api.themoviedb.org" @@ -50,7 +49,9 @@ def get_season(seasons: list) -> tuple[int, str]: [year, _, _] = date now_year = time.localtime().tm_year if int(year) <= now_year: - return int(re.findall(r"\d", season.get("season"))[0]), season.get("poster_path") + return int(re.findall(r"\d", season.get("season"))[0]), season.get( + "poster_path" + ) return len(ss), ss[-1].get("poster_path") @@ -100,5 +101,5 @@ def tmdb_parser(title, language) -> TMDBInfo | None: return None -if __name__ == '__main__': - print(tmdb_parser("魔法禁书目录", "zh")) \ No newline at end of file +if __name__ == "__main__": + print(tmdb_parser("魔法禁书目录", "zh")) diff --git a/backend/src/module/parser/analyser/torrent_parser.py b/backend/src/module/parser/analyser/torrent_parser.py index d4063526..b4c594cb 100644 --- a/backend/src/module/parser/analyser/torrent_parser.py +++ b/backend/src/module/parser/analyser/torrent_parser.py @@ -1,6 +1,6 @@ import logging -from pathlib import Path import re +from pathlib import Path from module.models import EpisodeFile, SubtitleFile diff --git a/backend/src/module/rss/analyser.py b/backend/src/module/rss/analyser.py index 549fdc0a..2d76f5a9 100644 --- a/backend/src/module/rss/analyser.py +++ b/backend/src/module/rss/analyser.py @@ -1,13 +1,13 @@ import logging import re -from .engine import RSSEngine - from module.conf import settings -from module.models import Bangumi, Torrent, RSSItem, ResponseModel +from module.models import Bangumi, ResponseModel, RSSItem, Torrent from module.network import RequestContent from module.parser import TitleParser +from .engine import RSSEngine + logger = logging.getLogger(__name__) diff --git a/backend/src/module/rss/engine.py b/backend/src/module/rss/engine.py index 60f9e397..920d6130 100644 --- a/backend/src/module/rss/engine.py +++ b/backend/src/module/rss/engine.py @@ -1,13 +1,11 @@ -import re import logging - +import re from typing import Optional -from module.models import Bangumi, RSSItem, Torrent, ResponseModel -from module.network import RequestContent -from module.downloader import DownloadClient - from module.database import Database, engine +from module.downloader import DownloadClient +from module.models import Bangumi, ResponseModel, RSSItem, Torrent +from module.network import RequestContent logger = logging.getLogger(__name__) @@ -33,7 +31,13 @@ class RSSEngine(Database): else: return [] - def add_rss(self, rss_link: str, name: str | None = None, aggregate: bool = True, parser: str = "mikan"): + def add_rss( + self, + rss_link: str, + name: str | None = None, + aggregate: bool = True, + parser: str = "mikan", + ): if not name: with RequestContent() as req: name = req.get_rss_title(rss_link) @@ -127,7 +131,9 @@ class RSSEngine(Database): def download_bangumi(self, bangumi: Bangumi): with RequestContent() as req: - torrents = req.get_torrents(bangumi.rss_link, bangumi.filter.replace(",", "|")) + torrents = req.get_torrents( + bangumi.rss_link, bangumi.filter.replace(",", "|") + ) if torrents: with DownloadClient() as client: client.add_torrent(torrents, bangumi) diff --git a/backend/src/module/searcher/__init__.py b/backend/src/module/searcher/__init__.py index 9630e420..65b403e3 100644 --- a/backend/src/module/searcher/__init__.py +++ b/backend/src/module/searcher/__init__.py @@ -1,2 +1,2 @@ -from .searcher import SearchTorrent from .provider import SEARCH_CONFIG +from .searcher import SearchTorrent diff --git a/backend/src/module/searcher/provider.py b/backend/src/module/searcher/provider.py index 318a22ea..2fffccbf 100644 --- a/backend/src/module/searcher/provider.py +++ b/backend/src/module/searcher/provider.py @@ -1,7 +1,7 @@ import re -from module.models import RSSItem from module.conf import SEARCH_CONFIG +from module.models import RSSItem def search_url(site: str, keywords: list[str]) -> RSSItem: @@ -17,4 +17,4 @@ def search_url(site: str, keywords: list[str]) -> RSSItem: ) return rss_item else: - raise ValueError(f"Site {site} is not supported") \ No newline at end of file + raise ValueError(f"Site {site} is not supported") diff --git a/backend/src/module/searcher/searcher.py b/backend/src/module/searcher/searcher.py index 533329c6..be9c0077 100644 --- a/backend/src/module/searcher/searcher.py +++ b/backend/src/module/searcher/searcher.py @@ -1,7 +1,7 @@ import json from typing import TypeAlias -from module.models import Bangumi, Torrent, RSSItem +from module.models import Bangumi, RSSItem, Torrent from module.network import RequestContent from module.rss import RSSAnalyser @@ -20,13 +20,13 @@ BangumiJSON: TypeAlias = str class SearchTorrent(RequestContent, RSSAnalyser): - def search_torrents( - self, rss_item: RSSItem - ) -> list[Torrent]: + def search_torrents(self, rss_item: RSSItem) -> list[Torrent]: torrents = self.get_torrents(rss_item.url) return torrents - def analyse_keyword(self, keywords: list[str], site: str = "mikan", limit: int = 5) -> BangumiJSON: + def analyse_keyword( + self, keywords: list[str], site: str = "mikan", limit: int = 5 + ) -> BangumiJSON: rss_item = search_url(site, keywords) torrents = self.search_torrents(rss_item) # yield for EventSourceResponse (Server Send) @@ -39,7 +39,7 @@ class SearchTorrent(RequestContent, RSSAnalyser): if bangumi and special_link not in exist_list: bangumi.rss_link = special_link exist_list.append(special_link) - yield json.dumps(bangumi.dict(), separators=(',', ':')) + yield json.dumps(bangumi.dict(), separators=(",", ":")) @staticmethod def special_url(data: Bangumi, site: str) -> RSSItem: @@ -50,4 +50,4 @@ class SearchTorrent(RequestContent, RSSAnalyser): def search_season(self, data: Bangumi, site: str = "mikan") -> list[Torrent]: rss_item = self.special_url(data, site) torrents = self.search_torrents(rss_item) - return [torrent for torrent in torrents if data.title_raw in torrent.name] \ No newline at end of file + return [torrent for torrent in torrents if data.title_raw in torrent.name] diff --git a/backend/src/module/security/api.py b/backend/src/module/security/api.py index 3b8cc510..e0150e68 100644 --- a/backend/src/module/security/api.py +++ b/backend/src/module/security/api.py @@ -1,4 +1,4 @@ -from fastapi import Depends, HTTPException, status, Cookie +from fastapi import Cookie, Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer from module.database import Database diff --git a/backend/src/module/update/__init__.py b/backend/src/module/update/__init__.py index ca1f94c5..dffc9cce 100644 --- a/backend/src/module/update/__init__.py +++ b/backend/src/module/update/__init__.py @@ -1,4 +1,4 @@ -from .data_migration import data_migration -from .startup import start_up, first_run -from .version_check import version_check from .cross_version import from_30_to_31 +from .data_migration import data_migration +from .startup import first_run, start_up +from .version_check import version_check diff --git a/backend/src/module/update/cross_version.py b/backend/src/module/update/cross_version.py index 6d9386c5..047e7ae0 100644 --- a/backend/src/module/update/cross_version.py +++ b/backend/src/module/update/cross_version.py @@ -1,4 +1,5 @@ import re + from urllib3.util import parse_url from module.rss import RSSEngine @@ -13,7 +14,9 @@ def from_30_to_31(): for bangumi in bangumis: if bangumi.poster_link: rss_link = bangumi.rss_link.split(",")[-1] - if rss_link not in rss_pool and not re.search(r"\d+.\d+.\d+.\d+", rss_link): + if rss_link not in rss_pool and not re.search( + r"\d+.\d+.\d+.\d+", rss_link + ): rss_pool.append(rss_link) root_path = parse_url(rss_link).host if "://" not in bangumi.poster_link: diff --git a/backend/src/module/update/data_migration.py b/backend/src/module/update/data_migration.py index f9775579..3492704c 100644 --- a/backend/src/module/update/data_migration.py +++ b/backend/src/module/update/data_migration.py @@ -1,6 +1,6 @@ from module.conf import LEGACY_DATA_PATH -from module.rss import RSSEngine from module.models import Bangumi +from module.rss import RSSEngine from module.utils import json_config diff --git a/backend/src/test/test_database.py b/backend/src/test/test_database.py index bb2babf7..5ee7ad93 100644 --- a/backend/src/test/test_database.py +++ b/backend/src/test/test_database.py @@ -1,9 +1,7 @@ -from sqlmodel import create_engine, SQLModel -from sqlmodel.pool import StaticPool - from module.database.combine import Database -from module.models import Bangumi, Torrent, RSSItem - +from module.models import Bangumi, RSSItem, Torrent +from sqlmodel import SQLModel, create_engine +from sqlmodel.pool import StaticPool # sqlite mock engine engine = create_engine( @@ -47,7 +45,9 @@ def test_bangumi_database(): assert db.bangumi.match_poster("无职转生,到了异世界就拿出真本事II (2021)") == "/test/test.jpg" # match torrent - result = db.bangumi.match_torrent("[Lilith-Raws] 无职转生,到了异世界就拿出真本事 / Mushoku Tensei - 11 [Baha][WEB-DL][1080p][AVC AAC][CHT][MP4]") + result = db.bangumi.match_torrent( + "[Lilith-Raws] 无职转生,到了异世界就拿出真本事 / Mushoku Tensei - 11 [Baha][WEB-DL][1080p][AVC AAC][CHT][MP4]" + ) assert result.official_title == "无职转生,到了异世界就拿出真本事II" # delete