diff --git a/src/main.py b/src/main.py index 1d9660fd..c0229948 100644 --- a/src/main.py +++ b/src/main.py @@ -17,11 +17,13 @@ uvicorn_logging_config = { "uvicorn.access": { "level": "WARNING", }, - } + }, } if __name__ == "__main__": uvicorn.run( - router, host="0.0.0.0", port=settings.program.webui_port, + router, + host="0.0.0.0", + port=settings.program.webui_port, log_config=uvicorn_logging_config, - ) \ No newline at end of file + ) diff --git a/src/module/ab_decorator/__init__.py b/src/module/ab_decorator/__init__.py index 03baebc5..f469894c 100644 --- a/src/module/ab_decorator/__init__.py +++ b/src/module/ab_decorator/__init__.py @@ -16,6 +16,7 @@ def qb_connect_failed_wait(func): logger.warning("Cannot connect to qBittorrent. Wait 5 min and retry...") time.sleep(300) times += 1 + return wrapper diff --git a/src/module/api/auth.py b/src/module/api/auth.py index aaa8db45..5e22a605 100644 --- a/src/module/api/auth.py +++ b/src/module/api/auth.py @@ -1,7 +1,12 @@ from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordRequestForm -from module.security import create_access_token, get_current_user, update_user_info, auth_user +from module.security import ( + create_access_token, + get_current_user, + update_user_info, + auth_user, +) from module.models.user import User from .program import router @@ -17,27 +22,28 @@ async def login(form_data: OAuth2PasswordRequestForm = Depends()): @router.get("/api/v1/auth/refresh_token", response_model=dict, tags=["auth"]) -async def refresh( - current_user: User = Depends(get_current_user) -): +async def refresh(current_user: User = Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) token = create_access_token({"sub": current_user.username}) return {"access_token": token, "token_type": "bearer", "expire": 86400} @router.get("/api/v1/auth/logout", response_model=dict, tags=["auth"]) -async def logout( - current_user: User = Depends(get_current_user) -): +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") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) return {"message": "logout success"} @router.post("/api/v1/auth/update", response_model=dict, tags=["auth"]) async def update_user(user_data: User, current_user: User = Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) return update_user_info(user_data, current_user) - diff --git a/src/module/api/bangumi.py b/src/module/api/bangumi.py index 85068877..6def1480 100644 --- a/src/module/api/bangumi.py +++ b/src/module/api/bangumi.py @@ -8,18 +8,26 @@ from module.manager import TorrentManager from module.security import get_current_user -@router.get("/api/v1/bangumi/getAll", tags=["bangumi"], response_model=list[BangumiData]) +@router.get( + "/api/v1/bangumi/getAll", tags=["bangumi"], response_model=list[BangumiData] +) async def get_all_data(current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) with TorrentManager() as torrent: return torrent.search_all() -@router.get("/api/v1/bangumi/getData/{bangumi_id}", tags=["bangumi"], response_model=BangumiData) +@router.get( + "/api/v1/bangumi/getData/{bangumi_id}", tags=["bangumi"], response_model=BangumiData +) async def get_data(bangumi_id: str, current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) with TorrentManager() as torrent: return torrent.search_data(bangumi_id) @@ -27,7 +35,9 @@ async def get_data(bangumi_id: str, current_user=Depends(get_current_user)): @router.post("/api/v1/bangumi/updateData", tags=["bangumi"]) async def update_data(data: BangumiData, current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) with TorrentManager() as torrent: return torrent.update_rule(data) @@ -35,15 +45,21 @@ async def update_data(data: BangumiData, current_user=Depends(get_current_user)) @router.delete("/api/v1/bangumi/deleteData/{bangumi_id}", tags=["bangumi"]) async def delete_data(bangumi_id: str, current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) with TorrentManager() as torrent: return torrent.delete_data(bangumi_id) @router.delete("/api/v1/bangumi/deleteRule/{bangumi_id}", tags=["bangumi"]) -async def delete_rule(bangumi_id: str, file: bool = False, current_user=Depends(get_current_user)): +async def delete_rule( + bangumi_id: str, file: bool = False, current_user=Depends(get_current_user) +): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) with TorrentManager() as torrent: return torrent.delete_rule(bangumi_id, file) @@ -51,7 +67,9 @@ async def delete_rule(bangumi_id: str, file: bool = False, current_user=Depends( @router.get("/api/v1/bangumi/resetAll", tags=["bangumi"]) async def reset_all(current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) with BangumiDatabase() as database: database.delete_all() return {"status": "ok"} diff --git a/src/module/api/config.py b/src/module/api/config.py index a82bca5a..b034d9d0 100644 --- a/src/module/api/config.py +++ b/src/module/api/config.py @@ -14,14 +14,18 @@ logger = logging.getLogger(__name__) @router.get("/api/v1/getConfig", tags=["config"], response_model=Config) async def get_config(current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) return settings @router.post("/api/v1/updateConfig", tags=["config"]) async def update_config(config: Config, current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) try: settings.save(config_dict=config.dict()) settings.load() diff --git a/src/module/api/download.py b/src/module/api/download.py index b8396ea5..8a540640 100644 --- a/src/module/api/download.py +++ b/src/module/api/download.py @@ -16,7 +16,9 @@ def link_process(link): @router.post("/api/v1/download/analysis", tags=["download"]) async def analysis(link: RssLink, current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) data = link_process(link.rss_link) if data: return data[0] @@ -25,9 +27,13 @@ async def analysis(link: RssLink, current_user=Depends(get_current_user)): @router.post("/api/v1/download/collection", tags=["download"]) -async def download_collection(data: BangumiData, current_user=Depends(get_current_user)): +async def download_collection( + data: BangumiData, current_user=Depends(get_current_user) +): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) if data: with SeasonCollector() as collector: collector.collect_season(data, data.rss_link[0]) @@ -39,7 +45,9 @@ async def download_collection(data: BangumiData, current_user=Depends(get_curren @router.post("/api/v1/download/subscribe", tags=["download"]) async def subscribe(data: BangumiData, current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) if data: with SeasonCollector() as collector: collector.subscribe_season(data) diff --git a/src/module/api/log.py b/src/module/api/log.py index cf26cb8c..24c04432 100644 --- a/src/module/api/log.py +++ b/src/module/api/log.py @@ -10,7 +10,9 @@ from module.security import get_current_user @router.get("/api/v1/log", tags=["log"]) async def get_log(current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) if os.path.isfile(LOG_PATH): with open(LOG_PATH, "r") as f: return Response(f.read(), media_type="text/plain") @@ -21,15 +23,12 @@ async def get_log(current_user=Depends(get_current_user)): @router.get("/api/v1/log/clear", tags=["log"]) async def clear_log(current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) if os.path.isfile(LOG_PATH): with open(LOG_PATH, "w") as f: f.write("") return {"status": "ok"} else: return Response("Log file not found", status_code=404) - - - - - diff --git a/src/module/api/program.py b/src/module/api/program.py index 73dcfa0a..b4c0f33e 100644 --- a/src/module/api/program.py +++ b/src/module/api/program.py @@ -26,7 +26,9 @@ async def shutdown(): @router.get("/api/v1/restart", tags=["program"]) async def restart(current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) try: program.restart() return {"status": "ok"} @@ -39,7 +41,9 @@ async def restart(current_user=Depends(get_current_user)): @router.get("/api/v1/start", tags=["program"]) async def start(current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) try: program.start() return {"status": "ok"} @@ -52,7 +56,9 @@ async def start(current_user=Depends(get_current_user)): @router.get("/api/v1/stop", tags=["program"]) async def stop(current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) program.stop() return {"status": "ok"} @@ -60,7 +66,9 @@ async def stop(current_user=Depends(get_current_user)): @router.get("/api/v1/status", tags=["program"]) async def status(current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) if not program.is_running: return {"status": "stop"} else: @@ -70,7 +78,9 @@ async def status(current_user=Depends(get_current_user)): @router.get("/api/v1/shutdown", tags=["program"]) async def shutdown_program(current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) program.stop() logger.info("Shutting down program...") os.kill(os.getpid(), signal.SIGINT) @@ -81,12 +91,16 @@ async def shutdown_program(current_user=Depends(get_current_user)): @router.get("/api/v1/check/downloader", tags=["check"]) async def check_downloader_status(current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) return program.check_downloader() @router.get("/api/v1/check/rss", tags=["check"]) async def check_rss_status(current_user=Depends(get_current_user)): if not current_user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) return program.check_analyser() diff --git a/src/module/api/proxy.py b/src/module/api/proxy.py index c362d348..d06052fc 100644 --- a/src/module/api/proxy.py +++ b/src/module/api/proxy.py @@ -38,7 +38,7 @@ def get_torrent(full_path): logger.warning("Failed to get torrent") raise HTTPException(status_code=500, detail="Failed to get torrent") - + @router.get("/RSS/MyBangumi", tags=["proxy"]) async def get_my_bangumi(token: str): full_path = "MyBangumi?token=" + token diff --git a/src/module/api/web.py b/src/module/api/web.py index 51942887..ebc3cb93 100644 --- a/src/module/api/web.py +++ b/src/module/api/web.py @@ -17,7 +17,9 @@ if VERSION != "DEV_VERSION": def index(request: Request): context = {"request": request} return templates.TemplateResponse("index.html", context) + else: + @router.get("/", status_code=302, tags=["html"]) def index(): return RedirectResponse("/docs") diff --git a/src/module/checker/__init__.py b/src/module/checker/__init__.py index 0c9226c5..243f0286 100644 --- a/src/module/checker/__init__.py +++ b/src/module/checker/__init__.py @@ -1 +1 @@ -from .checker import Checker \ No newline at end of file +from .checker import Checker diff --git a/src/module/checker/checker.py b/src/module/checker/checker.py index c96454bb..aba46030 100644 --- a/src/module/checker/checker.py +++ b/src/module/checker/checker.py @@ -10,15 +10,13 @@ class Checker: pass def check_renamer(self) -> bool: - if self.check_downloader() and\ - settings.bangumi_manage.enable: + if self.check_downloader() and settings.bangumi_manage.enable: return True else: return False def check_analyser(self) -> bool: - if self.check_downloader() and\ - settings.rss_parser.enable: + if self.check_downloader() and settings.rss_parser.enable: return True else: return False diff --git a/src/module/conf/log.py b/src/module/conf/log.py index 75463a6f..8ba45ce1 100644 --- a/src/module/conf/log.py +++ b/src/module/conf/log.py @@ -5,6 +5,7 @@ from .config import settings LOG_PATH = "data/log.txt" + def setup_logger(level: int = logging.INFO, reset: bool = False): level = logging.DEBUG if settings.log.debug_enable else level if not os.path.isdir("data"): diff --git a/src/module/conf/uvicorn_logging.py b/src/module/conf/uvicorn_logging.py index e3d06e82..b2e30882 100644 --- a/src/module/conf/uvicorn_logging.py +++ b/src/module/conf/uvicorn_logging.py @@ -35,4 +35,4 @@ logging_config = { "propagate": False, }, }, -} \ No newline at end of file +} diff --git a/src/module/core/__init__.py b/src/module/core/__init__.py index 82d79d10..84633ad6 100644 --- a/src/module/core/__init__.py +++ b/src/module/core/__init__.py @@ -1 +1 @@ -from .program import Program \ No newline at end of file +from .program import Program diff --git a/src/module/core/rss_feed.py b/src/module/core/rss_feed.py index 39f046bb..e1f14653 100644 --- a/src/module/core/rss_feed.py +++ b/src/module/core/rss_feed.py @@ -27,7 +27,8 @@ def add_rss_feed(): logger.info(f"Add RSS Feed: {settings.rss_link}") -if __name__ == '__main__': +if __name__ == "__main__": from module.conf import setup_logger + setup_logger() - add_rss_feed() \ No newline at end of file + add_rss_feed() diff --git a/src/module/database/bangumi.py b/src/module/database/bangumi.py index f653bc93..d826f47c 100644 --- a/src/module/database/bangumi.py +++ b/src/module/database/bangumi.py @@ -149,8 +149,7 @@ class BangumiDatabase(DataConnector): SELECT official_title, poster_link FROM bangumi WHERE INSTR(:bangumi_name, official_title) > 0 - """ - , + """, {"bangumi_name": bangumi_name}, ) data = self._cursor.fetchone() diff --git a/src/module/database/connector.py b/src/module/database/connector.py index f8cea42c..d74bb159 100644 --- a/src/module/database/connector.py +++ b/src/module/database/connector.py @@ -16,11 +16,18 @@ class DataConnector: self._cursor = self._conn.cursor() def _update_table(self, table_name: str, db_data: dict): - columns = ", ".join([f"{key} {self.__python_to_sqlite_type(value)}" for key, value in db_data.items()]) + columns = ", ".join( + [ + f"{key} {self.__python_to_sqlite_type(value)}" + for key, value in db_data.items() + ] + ) create_table_sql = f"CREATE TABLE IF NOT EXISTS {table_name} ({columns});" self._cursor.execute(create_table_sql) self._cursor.execute(f"PRAGMA table_info({table_name})") - existing_columns = {column_info[1]: column_info for column_info in self._cursor.fetchall()} + existing_columns = { + column_info[1]: column_info for column_info in self._cursor.fetchall() + } for key, value in db_data.items(): if key not in existing_columns: insert_column = self.__python_to_sqlite_type(value) @@ -31,23 +38,29 @@ class DataConnector: self._conn.commit() logger.debug(f"Create / Update table {table_name}.") - def _insert(self, table_name: str, db_data: dict): + def _insert(self, table_name: str, db_data: dict): columns = ", ".join(db_data.keys()) values = ", ".join([f":{key}" for key in db_data.keys()]) - self._cursor.execute(f"INSERT INTO {table_name} ({columns}) VALUES ({values})", db_data) + self._cursor.execute( + f"INSERT INTO {table_name} ({columns}) VALUES ({values})", db_data + ) self._conn.commit() def _insert_list(self, table_name: str, data_list: list[dict]): columns = ", ".join(data_list[0].keys()) values = ", ".join([f":{key}" for key in data_list[0].keys()]) - self._cursor.executemany(f"INSERT INTO {table_name} ({columns}) VALUES ({values})", data_list) + self._cursor.executemany( + f"INSERT INTO {table_name} ({columns}) VALUES ({values})", data_list + ) self._conn.commit() def _select(self, keys: list[str], table_name: str, condition: str = None) -> dict: if condition is None: self._cursor.execute(f"SELECT {', '.join(keys)} FROM {table_name}") else: - self._cursor.execute(f"SELECT {', '.join(keys)} FROM {table_name} WHERE {condition}") + self._cursor.execute( + f"SELECT {', '.join(keys)} FROM {table_name} WHERE {condition}" + ) return dict(zip(keys, self._cursor.fetchone())) def _update(self, table_name: str, db_data: dict): @@ -55,21 +68,29 @@ class DataConnector: if _id is None: raise ValueError("No _id in db_data.") set_sql = ", ".join([f"{key} = :{key}" for key in db_data.keys()]) - self._cursor.execute(f"UPDATE {table_name} SET {set_sql} WHERE id = {_id}", db_data) + self._cursor.execute( + f"UPDATE {table_name} SET {set_sql} WHERE id = {_id}", db_data + ) self._conn.commit() return self._cursor.rowcount == 1 def _update_list(self, table_name: str, data_list: list[dict]): if len(data_list) == 0: return - set_sql = ", ".join([f"{key} = :{key}" for key in data_list[0].keys() if key != "id"]) - self._cursor.executemany(f"UPDATE {table_name} SET {set_sql} WHERE id = :id", data_list) + set_sql = ", ".join( + [f"{key} = :{key}" for key in data_list[0].keys() if key != "id"] + ) + self._cursor.executemany( + f"UPDATE {table_name} SET {set_sql} WHERE id = :id", data_list + ) self._conn.commit() def _update_section(self, table_name: str, location: dict, update_dict: dict): set_sql = ", ".join([f"{key} = :{key}" for key in update_dict.keys()]) sql_loc = f"{location['key']} = {location['value']}" - self._cursor.execute(f"UPDATE {table_name} SET {set_sql} WHERE {sql_loc}", update_dict) + self._cursor.execute( + f"UPDATE {table_name} SET {set_sql} WHERE {sql_loc}", update_dict + ) self._conn.commit() def _delete_all(self, table_name: str): @@ -77,7 +98,10 @@ class DataConnector: self._conn.commit() def _table_exists(self, table_name: str) -> bool: - self._cursor.execute(f"SELECT name FROM sqlite_master WHERE type='table' AND name=?;", (table_name,)) + self._cursor.execute( + f"SELECT name FROM sqlite_master WHERE type='table' AND name=?;", + (table_name,), + ) return len(self._cursor.fetchall()) == 1 @staticmethod diff --git a/src/module/database/torrent.py b/src/module/database/torrent.py index 623addf3..bbdf0f8c 100644 --- a/src/module/database/torrent.py +++ b/src/module/database/torrent.py @@ -4,8 +4,8 @@ from .connector import DataConnector logger = logging.getLogger(__name__) -class TorrentDatabase(DataConnector): +class TorrentDatabase(DataConnector): def update_table(self): table_name = "torrent" db_data = self.__data_to_db() @@ -30,14 +30,18 @@ class TorrentDatabase(DataConnector): return SaveTorrent(**db_data) def if_downloaded(self, torrent_url: str, torrent_name: str) -> bool: - self._cursor.execute("SELECT * FROM torrent WHERE torrent_url = ? OR torrent_name = ?", - (torrent_url, torrent_name)) + self._cursor.execute( + "SELECT * FROM torrent WHERE torrent_url = ? OR torrent_name = ?", + (torrent_url, torrent_name), + ) return bool(self._cursor.fetchone()) def insert(self, data: SaveTorrent): db_data = self.__data_to_db(data) columns = ", ".join(db_data.keys()) values = ", ".join([f":{key}" for key in db_data.keys()]) - self._cursor.execute(f"INSERT INTO torrent ({columns}) VALUES ({values})", db_data) + self._cursor.execute( + f"INSERT INTO torrent ({columns}) VALUES ({values})", db_data + ) logger.debug(f"Add {data.torrent_name} into database.") - self._conn.commit() \ No newline at end of file + self._conn.commit() diff --git a/src/module/database/user.py b/src/module/database/user.py index 5a1ef836..22a97020 100644 --- a/src/module/database/user.py +++ b/src/module/database/user.py @@ -33,7 +33,9 @@ class AuthDB(DataConnector): return User(**db_data) def get_user(self, username): - self._cursor.execute(f"SELECT * FROM {self.__table_name} WHERE username=?", (username,)) + self._cursor.execute( + f"SELECT * FROM {self.__table_name} WHERE username=?", (username,) + ) result = self._cursor.fetchone() if not result: return None @@ -41,7 +43,10 @@ class AuthDB(DataConnector): return self.__db_to_data(db_data) def auth_user(self, username, password) -> bool: - self._cursor.execute(f"SELECT username, password FROM {self.__table_name} WHERE username=?", (username,)) + self._cursor.execute( + f"SELECT username, password FROM {self.__table_name} WHERE username=?", + (username,), + ) result = self._cursor.fetchone() if not result: raise HTTPException(status_code=404, detail="User not found") @@ -53,15 +58,17 @@ class AuthDB(DataConnector): # Update username and password new_username = update_user.username new_password = update_user.password - self._cursor.execute(f""" + self._cursor.execute( + f""" UPDATE {self.__table_name} SET username = '{new_username}', password = '{get_password_hash(new_password)}' WHERE username = '{username}' - """) + """ + ) self._conn.commit() if __name__ == "__main__": with AuthDB() as db: # db.update_user(UserLogin(username="admin", password="adminadmin"), User(username="admin", password="cica1234")) - db.update_user("admin", User(username="estrella", password="cica1234")) \ No newline at end of file + db.update_user("admin", User(username="estrella", password="cica1234")) diff --git a/src/module/downloader/__init__.py b/src/module/downloader/__init__.py index 46518611..0f5784c1 100644 --- a/src/module/downloader/__init__.py +++ b/src/module/downloader/__init__.py @@ -1,2 +1 @@ from .download_client import DownloadClient - diff --git a/src/module/downloader/client/qb_downloader.py b/src/module/downloader/client/qb_downloader.py index fadefdd7..fbd658a8 100644 --- a/src/module/downloader/client/qb_downloader.py +++ b/src/module/downloader/client/qb_downloader.py @@ -2,7 +2,11 @@ import logging import time from qbittorrentapi import Client, LoginFailed -from qbittorrentapi.exceptions import Conflict409Error, Forbidden403Error, APIConnectionError +from qbittorrentapi.exceptions import ( + Conflict409Error, + Forbidden403Error, + APIConnectionError, +) from module.ab_decorator import qb_connect_failed_wait from module.downloader.exceptions import ConflictError @@ -18,7 +22,7 @@ class QbDownloader: password=password, VERIFY_WEBUI_CERTIFICATE=ssl, DISABLE_LOGGING_DEBUG_OUTPUT=True, - REQUESTS_ARGS={'timeout': (3.1, 10)} + REQUESTS_ARGS={"timeout": (3.1, 10)}, ) self.host = host self.username = username diff --git a/src/module/downloader/download_client.py b/src/module/downloader/download_client.py index 3eeee3b2..829b7355 100644 --- a/src/module/downloader/download_client.py +++ b/src/module/downloader/download_client.py @@ -24,6 +24,7 @@ class DownloadClient(TorrentPath): ssl = settings.downloader.ssl if type == "qbittorrent": from .client.qb_downloader import QbDownloader + return QbDownloader(host, username, password, ssl) else: raise Exception(f"Unsupported downloader type: {type}") @@ -79,7 +80,9 @@ class DownloadClient(TorrentPath): } self.client.rss_set_rule(rule_name=data.rule_name, rule_def=rule) data.added = True - logger.info(f"Add {data.official_title} Season {data.season} to auto download rules.") + logger.info( + f"Add {data.official_title} Season {data.season} to auto download rules." + ) def set_rules(self, bangumi_info: list[BangumiData]): logger.debug("Start adding rules.") @@ -129,4 +132,4 @@ class DownloadClient(TorrentPath): def remove_rule(self, rule_name): self.client.remove_rule(rule_name) - logger.info(f"Delete rule: {rule_name}") \ No newline at end of file + logger.info(f"Delete rule: {rule_name}") diff --git a/src/module/downloader/path.py b/src/module/downloader/path.py index 6db55a80..b6359ecb 100644 --- a/src/module/downloader/path.py +++ b/src/module/downloader/path.py @@ -52,15 +52,19 @@ class TorrentPath: return self._file_depth(path) <= 2 def _gen_save_path(self, data: BangumiData): - folder = f"{data.official_title}({data.year})" if data.year else data.official_title + folder = ( + f"{data.official_title}({data.year})" if data.year else data.official_title + ) save_path = path.join(self.download_path, folder, f"Season {data.season}") return save_path @staticmethod def _rule_name(data: BangumiData): - rule_name = f"[{data.group_name}] {data.official_title} S{data.season}" \ - if settings.bangumi_manage.group_tag \ + rule_name = ( + f"[{data.group_name}] {data.official_title} S{data.season}" + if settings.bangumi_manage.group_tag else f"{data.official_title} S{data.season}" + ) return rule_name @staticmethod diff --git a/src/module/manager/collector.py b/src/module/manager/collector.py index bbbf9b72..dc1c2de0 100644 --- a/src/module/manager/collector.py +++ b/src/module/manager/collector.py @@ -49,7 +49,8 @@ def eps_complete(): bd.update_list(datas) -if __name__ == '__main__': +if __name__ == "__main__": from module.conf import setup_logger + setup_logger() - eps_complete() \ No newline at end of file + eps_complete() diff --git a/src/module/manager/renamer.py b/src/module/manager/renamer.py index 86e49fff..a807488e 100644 --- a/src/module/manager/renamer.py +++ b/src/module/manager/renamer.py @@ -26,9 +26,13 @@ class Renamer(DownloadClient): logger.debug(f"Checked {torrent_count} files") @staticmethod - def gen_path(file_info: EpisodeFile | SubtitleFile, bangumi_name: str, method: str) -> str: + def gen_path( + file_info: EpisodeFile | SubtitleFile, bangumi_name: str, method: str + ) -> str: season = f"0{file_info.season}" if file_info.season < 10 else file_info.season - episode = f"0{file_info.episode}" if file_info.episode < 10 else file_info.episode + episode = ( + f"0{file_info.episode}" if file_info.episode < 10 else file_info.episode + ) if method == "None": return file_info.media_path elif method == "pn": @@ -66,7 +70,7 @@ class Renamer(DownloadClient): method: str, season: int, _hash: str, - **kwargs + **kwargs, ): ep = self._parser.torrent_parser( torrent_name=torrent_name, @@ -76,7 +80,9 @@ class Renamer(DownloadClient): if ep: new_path = self.gen_path(ep, bangumi_name, method=method) if media_path != new_path: - renamed = self.rename_torrent_file(_hash=_hash, old_path=media_path, new_path=new_path) + renamed = self.rename_torrent_file( + _hash=_hash, old_path=media_path, new_path=new_path + ) if renamed: if settings.notification.enable: self.send_notification(bangumi_name, ep) @@ -92,7 +98,7 @@ class Renamer(DownloadClient): season: int, method: str, _hash: str, - **kwargs + **kwargs, ): for media_path in media_list: if self.is_ep(media_path): @@ -121,7 +127,7 @@ class Renamer(DownloadClient): season: int, method: str, _hash, - **kwargs + **kwargs, ): method = "subtitle_" + method for subtitle_path in subtitle_list: @@ -166,15 +172,16 @@ class Renamer(DownloadClient): logger.info("Start rename collection") self.rename_collection(media_list=media_list, **kwargs) if len(subtitle_list) > 0: - self.rename_subtitles(subtitle_list=subtitle_list,**kwargs) + self.rename_subtitles(subtitle_list=subtitle_list, **kwargs) self.set_category(info.hash, "BangumiCollection") else: logger.warning(f"{info.name} has no media file") logger.debug("Rename process finished.") -if __name__ == '__main__': +if __name__ == "__main__": from module.conf import setup_logger + settings.log.debug_enable = True setup_logger() with Renamer() as renamer: diff --git a/src/module/manager/torrent.py b/src/module/manager/torrent.py index ec129038..760e2bad 100644 --- a/src/module/manager/torrent.py +++ b/src/module/manager/torrent.py @@ -25,7 +25,10 @@ class TorrentManager(BangumiDatabase): hash_list = self.__match_torrents_list(data) with DownloadClient() as client: client.delete_torrent(hash_list) - return {"status": "success", "msg": f"Delete torrents for {data.official_title}"} + return { + "status": "success", + "msg": f"Delete torrents for {data.official_title}", + } else: return data @@ -48,9 +51,15 @@ class TorrentManager(BangumiDatabase): if file: self.delete_torrents(data.id) logger.info(f"Delete rule and torrents for {data.official_title}") - return {"status": "success", "msg": f"Delete rule and torrents for {data.official_title}"} + return { + "status": "success", + "msg": f"Delete rule and torrents for {data.official_title}", + } logger.info(f"Delete rule for {data.official_title}") - return {"status": "success", "msg": f"Delete rule for {data.official_title}"} + return { + "status": "success", + "msg": f"Delete rule for {data.official_title}", + } else: return data @@ -69,7 +78,10 @@ class TorrentManager(BangumiDatabase): client.remove_rule(data.rule_name) client.set_rule(data) self.update_one(data) - return {"status": "success", "msg": f"Set new path for {data.official_title}"} + return { + "status": "success", + "msg": f"Set new path for {data.official_title}", + } def search_all_bangumi(self): datas = self.search_all() diff --git a/src/module/models/__init__.py b/src/module/models/__init__.py index 96b1034e..508d68f1 100644 --- a/src/module/models/__init__.py +++ b/src/module/models/__init__.py @@ -2,3 +2,4 @@ from .bangumi import * from .config import Config from .torrent import EpisodeFile, SubtitleFile from .user import UserLogin +from .torrent import TorrentBase diff --git a/src/module/models/torrent.py b/src/module/models/torrent.py index 7498cf1b..892d66d6 100644 --- a/src/module/models/torrent.py +++ b/src/module/models/torrent.py @@ -1,12 +1,10 @@ from pydantic import BaseModel, Field -class TorrentInfo(BaseModel): +class TorrentBase(BaseModel): name: str = Field(...) - link: str = Field(...) + torrent_link: str = Field(...) homepage: str | None = Field(None) - poster_link: str = Field(...) - official_title: str = Field(...) class FileSet(BaseModel): @@ -32,4 +30,3 @@ class SubtitleFile(BaseModel): episode: int = Field(None) language: str = Field(..., regex=r"(zh|zh-tw)") suffix: str = Field(..., regex=r"\.(ass|srt|ASS|SRT)$") - diff --git a/src/module/models/user.py b/src/module/models/user.py index 12031bfd..36512642 100644 --- a/src/module/models/user.py +++ b/src/module/models/user.py @@ -2,7 +2,9 @@ from pydantic import BaseModel, Field class User(BaseModel): - username: str = Field("admin", min_length=4, max_length=20, regex=r"^[a-zA-Z0-9_]+$") + username: str = Field( + "admin", min_length=4, max_length=20, regex=r"^[a-zA-Z0-9_]+$" + ) password: str = Field("adminadmin", min_length=8) @@ -17,4 +19,4 @@ class Token(BaseModel): class TokenData(BaseModel): - username: str | None = None \ No newline at end of file + username: str | None = None diff --git a/src/module/network/__init__.py b/src/module/network/__init__.py index d4589016..2da0ea13 100644 --- a/src/module/network/__init__.py +++ b/src/module/network/__init__.py @@ -1,2 +1,2 @@ -from .request_contents import RequestContent -from .notification import PostNotification, ServerChanNotification +from .request_contents import RequestContent, TorrentInfo +from .notification import PostNotification diff --git a/src/module/network/notification.py b/src/module/network/notification.py index d390d5c8..c351fe35 100644 --- a/src/module/network/notification.py +++ b/src/module/network/notification.py @@ -31,6 +31,7 @@ class TelegramNotification(RequestContent): class ServerChanNotification(RequestContent): """Server酱推送""" + def __init__(self): super().__init__() self.notification_url = f"https://sctapi.ftqq.com/{token}.send" @@ -71,10 +72,12 @@ def getClient(): class PostNotification(getClient()): def send_msg(self, info: Notification) -> bool: - text = f"番剧名称:{info.official_title}\n" \ - f"季度: 第{info.season}季\n" \ - f"更新集数: 第{info.episode}集\n" \ - f"{info.poster_link}\n" + text = ( + f"番剧名称:{info.official_title}\n" + f"季度: 第{info.season}季\n" + f"更新集数: 第{info.episode}集\n" + f"{info.poster_link}\n" + ) try: return self.post_msg(text) except Exception as e: @@ -82,7 +85,7 @@ class PostNotification(getClient()): return False -if __name__ == '__main__': +if __name__ == "__main__": info = Notification( official_title="魔法纪录 魔法少女小圆外传", season=2, @@ -90,4 +93,4 @@ if __name__ == '__main__': poster_link="https://mikanani.me/images/Bangumi/202107/3788b33f.jpg", ) with PostNotification() as client: - client.send_msg(info) \ No newline at end of file + client.send_msg(info) diff --git a/src/module/network/request_contents.py b/src/module/network/request_contents.py index a2c7f7b1..45dfa54a 100644 --- a/src/module/network/request_contents.py +++ b/src/module/network/request_contents.py @@ -1,17 +1,14 @@ import re import xml.etree.ElementTree -from dataclasses import dataclass from bs4 import BeautifulSoup from .request_url import RequestURL +from .site import mikan_parser from module.conf import settings +from module.models import TorrentBase -@dataclass -class TorrentInfo: - name: str - torrent_link: str - homepage: str = None +class TorrentInfo(TorrentBase): _poster_link: str = None _official_title: str = None @@ -19,39 +16,38 @@ class TorrentInfo: def poster_link(self) -> str: if self._poster_link is None: with RequestContent() as req: - self._poster_link, self._official_title = req.get_mikan_info(self.homepage) + self._poster_link, self._official_title = req.get_mikan_info( + self.homepage + ) return self._poster_link @property def official_title(self) -> str: if self._official_title is None: with RequestContent() as req: - self._poster_link, self._official_title = req.get_mikan_info(self.homepage) + self._poster_link, self._official_title = req.get_mikan_info( + self.homepage + ) return self._official_title class RequestContent(RequestURL): # Mikanani RSS def get_torrents( - self, - _url: str, - _filter: str = "|".join(settings.rss_parser.filter), - retry: int = 3 + self, + _url: str, + _filter: str = "|".join(settings.rss_parser.filter), + retry: int = 3, ) -> [TorrentInfo]: soup = self.get_xml(_url, retry) - torrent_titles = [] - torrent_urls = [] - torrent_homepage = [] - - for item in soup.findall("./channel/item"): - torrent_titles.append(item.find("title").text) - torrent_urls.append(item.find("enclosure").attrib["url"]) - torrent_homepage.append(item.find("link").text) + torrent_titles, torrent_urls, torrent_homepage = mikan_parser(soup) torrents = [] - for _title, torrent_url, homepage in zip(torrent_titles, torrent_urls, torrent_homepage): + for _title, torrent_url, homepage in zip( + torrent_titles, torrent_urls, torrent_homepage + ): if re.search(_filter, _title) is None: - torrents.append(TorrentInfo(_title, torrent_url, homepage)) + torrents.append(TorrentInfo(name=_title, torrent_link=torrent_url, homepage=homepage)) return torrents def get_mikan_info(self, _url) -> tuple[str, str]: @@ -59,7 +55,9 @@ class RequestContent(RequestURL): soup = BeautifulSoup(content, "html.parser") poster_div = soup.find("div", {"class": "bangumi-poster"}) poster_style = poster_div.get("style") - official_title = soup.select_one('p.bangumi-title a[href^="/Home/Bangumi/"]').text + official_title = soup.select_one( + 'p.bangumi-title a[href^="/Home/Bangumi/"]' + ).text if poster_style: poster_path = poster_style.split("url('")[1].split("')")[0] return poster_path, official_title diff --git a/src/module/network/request_url.py b/src/module/network/request_url.py index 1bdbceaf..e9bf923f 100644 --- a/src/module/network/request_url.py +++ b/src/module/network/request_url.py @@ -39,7 +39,9 @@ class RequestURL: try_time = 0 while True: try: - req = self.session.post(url=url, headers=self.header, data=data, timeout=5) + req = self.session.post( + url=url, headers=self.header, data=data, timeout=5 + ) req.raise_for_status() return req except requests.RequestException as e: @@ -59,7 +61,6 @@ class RequestURL: if "://" not in url: url = f"http://{url}" try: - req = requests.head(url=url, headers=self.header, timeout=5) req.raise_for_status() return True diff --git a/src/module/network/site/__init__.py b/src/module/network/site/__init__.py new file mode 100644 index 00000000..04b8a615 --- /dev/null +++ b/src/module/network/site/__init__.py @@ -0,0 +1 @@ +from .mikan import mikan_parser \ No newline at end of file diff --git a/src/module/network/site/mikan.py b/src/module/network/site/mikan.py new file mode 100644 index 00000000..5a326925 --- /dev/null +++ b/src/module/network/site/mikan.py @@ -0,0 +1,9 @@ +def mikan_parser(soup): + torrent_titles = [] + torrent_urls = [] + torrent_homepage = [] + for item in soup.findall("./channel/item"): + torrent_titles.append(item.find("title").text) + torrent_urls.append(item.find("enclosure").attrib["url"]) + torrent_homepage.append(item.find("link").text) + return torrent_titles, torrent_urls, torrent_homepage \ No newline at end of file diff --git a/src/module/parser/analyser/bgm_parser.py b/src/module/parser/analyser/bgm_parser.py index 67fbf220..af345270 100644 --- a/src/module/parser/analyser/bgm_parser.py +++ b/src/module/parser/analyser/bgm_parser.py @@ -1,8 +1,7 @@ from module.network import RequestContent -search_url = lambda e: \ - f"https://api.bgm.tv/search/subject/{e}?responseGroup=large" +search_url = lambda e: f"https://api.bgm.tv/search/subject/{e}?responseGroup=large" def bgm_parser(title): @@ -13,4 +12,3 @@ def bgm_parser(title): return contents[0] else: return None - diff --git a/src/module/parser/analyser/torrent_parser.py b/src/module/parser/analyser/torrent_parser.py index b5045702..fab6e485 100644 --- a/src/module/parser/analyser/torrent_parser.py +++ b/src/module/parser/analyser/torrent_parser.py @@ -59,10 +59,10 @@ def get_subtitle_lang(subtitle_name: str) -> str: def torrent_parser( - torrent_path: str, - torrent_name: str | None = None, - season: int | None = None, - file_type: str = "media" + torrent_path: str, + torrent_name: str | None = None, + season: int | None = None, + file_type: str = "media", ) -> EpisodeFile | SubtitleFile: media_path = split_path(torrent_path) for rule in RULES: @@ -85,7 +85,7 @@ def torrent_parser( title=title, season=season, episode=episode, - suffix=suffix + suffix=suffix, ) elif file_type == "subtitle": language = get_subtitle_lang(media_path) @@ -96,5 +96,5 @@ def torrent_parser( season=season, language=language, episode=episode, - suffix=suffix + suffix=suffix, ) diff --git a/src/module/rss/__init__.py b/src/module/rss/__init__.py index 220d4319..93e69605 100644 --- a/src/module/rss/__init__.py +++ b/src/module/rss/__init__.py @@ -2,4 +2,4 @@ from .rss_analyser import RSSAnalyser from .add_rules import add_rules -analyser = RSSAnalyser() \ No newline at end of file +analyser = RSSAnalyser() diff --git a/src/module/rss/filter.py b/src/module/rss/filter.py index 9691c4b6..8255dbde 100644 --- a/src/module/rss/filter.py +++ b/src/module/rss/filter.py @@ -15,7 +15,9 @@ def matched(torrent_title: str): def save_path(data: BangumiData): - folder = f"{data.official_title}({data.year})" if data.year else f"{data.official_title}" + folder = ( + f"{data.official_title}({data.year})" if data.year else f"{data.official_title}" + ) season = f"Season {data.season}" return path.join( settings.downloader.path, @@ -52,4 +54,4 @@ def get_downloads(rss_link: str): else: logger.debug(f"{torrent.title} not matched") else: - logger.debug(f"{torrent.title} already downloaded") \ No newline at end of file + logger.debug(f"{torrent.title} already downloaded") diff --git a/src/module/rss/rss_analyser.py b/src/module/rss/rss_analyser.py index a2e59845..eee0e351 100644 --- a/src/module/rss/rss_analyser.py +++ b/src/module/rss/rss_analyser.py @@ -1,7 +1,7 @@ import re import logging -from module.network import RequestContent +from module.network import RequestContent, TorrentInfo from module.parser import TitleParser from module.models import BangumiData from module.database import BangumiDatabase @@ -21,9 +21,7 @@ class RSSAnalyser: data.official_title = mikan_title if mikan_title else data.official_title elif settings.rss_parser.parser_type == "tmdb": tmdb_title, season, year = self._title_analyser.tmdb_parser( - data.official_title, - data.season, - settings.rss_parser.language + data.official_title, data.season, settings.rss_parser.language ) data.official_title = tmdb_title data.year = year @@ -41,15 +39,18 @@ class RSSAnalyser: rss_torrents = req.get_torrents(rss_link, "\\d+-\\d+") return rss_torrents - def new_bangumi_list(self, torrents: list, rss_link: str, full_parse: bool = True) -> list: + def torrents_to_data( + self, torrents: list, rss_link: str, full_parse: bool = True + ) -> list: new_data = [] for torrent in torrents: - data = self._title_analyser.raw_parser( - raw=torrent.name, rss_link=rss_link - ) + data = self._title_analyser.raw_parser(raw=torrent.name, rss_link=rss_link) if data and data.title_raw not in [i.title_raw for i in new_data]: try: - poster_link, mikan_title = torrent.poster_link, torrent.official_title + poster_link, mikan_title = ( + torrent.poster_link, + torrent.official_title, + ) except AttributeError: poster_link, mikan_title = None, None data.poster_link = poster_link @@ -60,6 +61,20 @@ class RSSAnalyser: logger.debug(f"New title found: {data.official_title}") return new_data + def torrent_to_data(self, torrent: TorrentInfo, rss_link: str | None = None) -> BangumiData: + data = self._title_analyser.raw_parser(raw=torrent.name, rss_link=rss_link) + if data: + try: + poster_link, mikan_title = ( + torrent.poster_link, + torrent.official_title, + ) + except AttributeError: + poster_link, mikan_title = None, None + data.poster_link = poster_link + self.official_title_parser(data, mikan_title) + return data + def rss_to_data(self, rss_link: str, full_parse: bool = True) -> list[BangumiData]: rss_torrents = self.get_rss_torrents(rss_link, full_parse) with BangumiDatabase() as database: @@ -68,7 +83,7 @@ class RSSAnalyser: logger.debug("No new title found.") return [] # New List - new_data = self.new_bangumi_list(torrents_to_add, rss_link, full_parse) + new_data = self.torrents_to_data(torrents_to_add, rss_link, full_parse) if full_parse: database.insert_list(new_data) return new_data diff --git a/src/module/rss/searcher.py b/src/module/rss/searcher.py index f1d85507..0d547bd2 100644 --- a/src/module/rss/searcher.py +++ b/src/module/rss/searcher.py @@ -3,7 +3,6 @@ from module.conf import settings class RSSSearcher(RequestContent): - def __search_url(self, keywords: str) -> str: keywords.replace(" ", "+") url = f"{settings.rss_parser.custom_url}/RSS/Search?keyword={keywords}" diff --git a/src/module/searcher/plugin/mikan.py b/src/module/searcher/plugin/mikan.py index 28384501..947066c8 100644 --- a/src/module/searcher/plugin/mikan.py +++ b/src/module/searcher/plugin/mikan.py @@ -10,4 +10,3 @@ def mikan_url(keywords: list[str]): if "://" not in url: url = f"https://{url}" return url - diff --git a/src/module/searcher/searcher.py b/src/module/searcher/searcher.py index bd653425..afd2134c 100644 --- a/src/module/searcher/searcher.py +++ b/src/module/searcher/searcher.py @@ -1,6 +1,6 @@ -from .plugin import search_url +from module.searcher.plugin import search_url from module.network import RequestContent -from module.models import BangumiData +from module.models import BangumiData, TorrentBase SEARCH_KEY = [ "group_name", @@ -13,11 +13,19 @@ SEARCH_KEY = [ class SearchTorrent(RequestContent): - def search_torrents(self, keywords: list[str], site: str = "mikan") -> list: + def search_torrents(self, keywords: list[str], site: str = "mikan") -> list[TorrentBase]: url = search_url(site, keywords) - return self.get_torrents(url) + # TorrentInfo to TorrentBase + torrents = self.get_torrents(url) + return [TorrentBase(**torrent.dict()) for torrent in torrents] def search_season(self, data: BangumiData): keywords = [getattr(data, key) for key in SEARCH_KEY if getattr(data, key)] torrents = self.search_torrents(keywords) - 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] + + +if __name__ == '__main__': + with SearchTorrent() as st: + for t in st.search_torrents(["魔法科高校の劣等生"]): + print(t) \ No newline at end of file diff --git a/src/module/security/api.py b/src/module/security/api.py index 979a3642..73548fb0 100644 --- a/src/module/security/api.py +++ b/src/module/security/api.py @@ -12,22 +12,30 @@ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login") async def get_current_user(token: str = Depends(oauth2_scheme)): if not token: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) payload = decode_token(token) if not payload: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) username = payload.get("sub") with AuthDB() as user_db: user = user_db.get_user(username) if not user: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid username") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid username" + ) return user async def get_token_data(token: str = Depends(oauth2_scheme)): payload = decode_token(token) if not payload: - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token") + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid token" + ) return payload @@ -43,4 +51,7 @@ def update_user_info(user_data: User, current_user): def auth_user(username, password): with AuthDB() as db: if not db.auth_user(username, password): - raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid username or password") \ No newline at end of file + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="invalid username or password", + ) diff --git a/src/module/utils/bangumi_data.py b/src/module/utils/bangumi_data.py index 12d67963..d688be50 100644 --- a/src/module/utils/bangumi_data.py +++ b/src/module/utils/bangumi_data.py @@ -3,4 +3,3 @@ import logging from .json_config import save, load logger = logging.getLogger(__name__) - diff --git a/src/test/test_torrent_parser.py b/src/test/test_torrent_parser.py index 8b0dbdb4..54832c7f 100644 --- a/src/test/test_torrent_parser.py +++ b/src/test/test_torrent_parser.py @@ -67,5 +67,3 @@ def test_torrent_parser(): assert bf.title == "放学后失眠的你-Kimi wa Houkago Insomnia" assert bf.season == 1 assert bf.episode == 6 - -