diff --git a/src/main.py b/src/main.py index 1e38a0b..b3f6922 100644 --- a/src/main.py +++ b/src/main.py @@ -85,8 +85,8 @@ def check_seadex(request:Request, db=Depends(get_db)): ) anime = cursor.fetchall() - logger.debug(f"[FastAPI] Found {len(anime)} active anime to check.") - if not anime[0]: + logger.debug("[FastAPI] Found %s active anime to check.", len(anime)) + if not anime: logger.info("[FastAPI] No active Seadex entries") return results @@ -96,12 +96,15 @@ def check_seadex(request:Request, db=Depends(get_db)): try: current = check_for_update(seadex, anilist_id) if current is None: - logger.debug(f"[FastAPI] No entry yet for Anime: {anime_name} on SeaDex") + logger.debug("[FastAPI] No entry yet for Anime: %s on SeaDex", anime_name) continue if current == last_updated: continue - logger.info(f"[FastAPI] Anime: {anime_name} updated, Anilist ID: {anilist_id}") + logger.info( + "[FastAPI] Anime: %s updated, Anilist ID: %s", + anime_name,anilist_id, + ) with db.cursor() as cursor: cursor.execute( "SELECT user_id, custom_name " @@ -124,16 +127,20 @@ def check_seadex(request:Request, db=Depends(get_db)): sent += 1 except NotificationUnavailableError: failed = len(subscribers) - sent - logger.error (f"[FastAPI] Notifications backend unavailable, skipping " - f"{failed} remaining user(s) for Anime: {anime_name}") + logger.error("[FastAPI] Notifications backend unavailable, skipping " + "%s remaining user(s) for Anime: %s", + failed, anime_name, + ) break except NotificationError as e: failed += 1 - logger.error(f"[FastAPI] Failed to send notification to user_id={user_id} for Anime: {anime_name} " - f"status={getattr(e, 'status_code',None)}") + logger.error( + "[FastAPI] Failed to send notification to user_id=%s for Anime: %s, status=%s", + user_id, anime_name, getattr(e, 'status_code',None), + ) if subscribers and sent == 0: results["errors"] += 1 - logger.error(f"[FastAPI] All notifications failed for Anime: {anime_name}, will retry later") + logger.error("[FastAPI] All notifications failed for Anime: %s, will retry later", anime_name) continue with db.cursor() as cursor: @@ -142,22 +149,25 @@ def check_seadex(request:Request, db=Depends(get_db)): (current, seadex_state_id), ) db.commit() - logger.debug(f"[FastAPI] Notification sent and database updated for Anime: {anime_name}") + logger.debug("[FastAPI] Notification sent and database updated for Anime: %s", anime_name) results["new"] += 1 except Exception: db.rollback() results["errors"] += 1 - logger.exception(f"[FastAPI] Failed for id: {seadex_state_id} Anilist: {anilist_id}",) + logger.exception( + "[FastAPI] Failed for id: %s Anilist: %s", + seadex_state_id, anilist_id, + ) if results["errors"]: - logger.warning(f"[FastAPI] SeaDex check finished with errors: {results}") + logger.warning("[FastAPI] SeaDex check finished with errors: %s", results) raise HTTPException(status_code=500, detail=results) - logger.info(f"[FastAPI] SeaDex check complete: {results}") + logger.info("[FastAPI] SeaDex check complete: %s", results) return results -@user_router.post("/add/anime") +@user_router.post("/anime/add") def add_anime( anime: AnimeCreate, user_id: UserId, @@ -214,7 +224,7 @@ def add_anime( ) return {"status": "ok", "detail": f"Tracking name={anime.custom_name or anime_name}, Anilist ID={anime.anilist_id}"} -@user_router.post("/delete/anime") +@user_router.post("/anime/delete") def remove_anime( anime: AnimeRemove, user_id: UserId, @@ -273,37 +283,44 @@ def remove_anime( ) return {"status": "ok", "detail": f"Stopped tracking Anilist ID={anime.anilist_id}"} -@user_router.get("/list/anime", response_model=AnimeList) -def list_active_and_inactive_anime(user_id: UserId, db=Depends(get_db)): - logger.info(f"[FastAPI] Received request to list anime for User ID = {user_id}") - with db.cursor() as cursor: - try: +@user_router.get("/anime/list", response_model=AnimeList) +def list_active_and_inactive_anime( + user_id: UserId, + db=Depends(get_db), + ): + logger.info("[FastAPI] Received request to list anime for User ID = %s", user_id) + + try: + with db.cursor() as cursor: cursor.execute( - "SELECT anime_name, active, last_updated " \ - "FROM seadex_state WHERE user_id = %s " - "ORDER BY anime_name", + "SELECT s.custom_name AS custom_name, st.anime_name AS anime_name, " + "st.anilist_id, s.active, st.last_updated from seadex_state_subscriptions AS s " + "JOIN seadex_state AS st on s.seadex_state_id = st.id " + "WHERE s.user_id = %s ORDER BY st.anilist_id", (user_id,), ) rows = cursor.fetchall() - except Exception as e: - logger.exception("[FastAPI] Failed to list anime") - raise HTTPException(status_code=500) from e - anime_list=AnimeList () - for name, is_active, last_updated in rows: + anime_list=AnimeList() + for custom_name, anime_name, anilist_id, is_active, last_updated in rows: entry = AnimeEntry( - name=name, - last_updated=None if last_updated is None else str(last_updated), + name=custom_name or anime_name, + anilist_id=anilist_id, + last_updated=None if last_updated is None else last_updated, ) (anime_list.active if is_active else anime_list.inactive).append(entry) - return anime_list + except Exception as e: + logger.exception("[FastAPI] Failed to list anime") + raise HTTPException(status_code=500) from e + + return anime_list api.include_router(user_router) api.include_router(scheduler_router) async def start_servers(): logger.info("[Server] Starting main API (port 5000) and metrics server (port 9000)...") - logger.info(f"[Server] Build commit id={os.getenv("COMMIT_ID","unknown")}") + logger.info("[Server] Build commit id=%s", os.getenv("COMMIT_ID", "unknown")) auth.load_keys(api, Caller.GATEWAY, Caller.SCHEDULER) cleanup_secret_files(auth.key_paths(Caller.GATEWAY, Caller.SCHEDULER)) diff --git a/src/models.py b/src/models.py index 8ce5d78..4796380 100644 --- a/src/models.py +++ b/src/models.py @@ -10,6 +10,7 @@ class AnimeRemove(BaseModel): class AnimeEntry(BaseModel): name: str + anilist_id: int last_updated: str | None = None class Counts(BaseModel):