chore: make sure that there is only one app

This commit is contained in:
Lukas 2025-11-02 15:14:34 +01:00
parent e414a1a358
commit ec987eff80
8 changed files with 11 additions and 967 deletions

View File

@ -17,7 +17,7 @@
"keep_days": 30 "keep_days": 30
}, },
"other": { "other": {
"master_password_hash": "$pbkdf2-sha256$29000$GiPkvJeS8j4HwBjDmNOaMw$8k4ShYlk51ZsxoiQBZGjXCsvl0xbbiXIFYI/EWlqVrI", "master_password_hash": "$pbkdf2-sha256$29000$8v4/p1RKyRnDWEspJSTEeA$u8rsOktLvjCgB2XeHrQvcSGj2vq.Gea0rQQt/e6Ygm0",
"anime_directory": "/home/lukas/Volume/serien/" "anime_directory": "/home/lukas/Volume/serien/"
}, },
"version": "1.0.0" "version": "1.0.0"

View File

@ -1,807 +0,0 @@
{
"pending": [
{
"id": "0c1563e1-db41-4163-95b5-b0a6a9531bf1",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 1,
"episode": 10,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.298728Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "5813d573-6834-47e6-a2c0-545aa9c28125",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 1,
"episode": 11,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.298756Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "f89d2f3a-b8f9-47f3-9cc1-15419489c883",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 1,
"episode": 12,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.298786Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "30684faf-7d6e-4544-81c8-6a592d47cdfd",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 2,
"episode": 1,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.298813Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "94794c92-0546-485d-8829-0594d04536ee",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 2,
"episode": 2,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.298840Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "23ba40ea-e7bb-4def-9bea-825466859d4c",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 2,
"episode": 3,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.298867Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "33462781-c0e8-4e0c-b4d2-172f4856d796",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 2,
"episode": 4,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.298895Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "0314395b-9540-4f73-8a16-7007797a89b9",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 2,
"episode": 5,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.298924Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "1074d85c-a66e-42f2-b299-70a2584944ff",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 2,
"episode": 6,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.298952Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "384ebe70-3f39-44e7-9162-372246fbff69",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 2,
"episode": 7,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.298982Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "63e51a26-c3c8-4ce0-950a-39d0d131ee0a",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 2,
"episode": 8,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299010Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "8b38c4cb-9c1f-4f74-8dc3-5c5e8e292bf1",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 2,
"episode": 9,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299038Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "3a19d684-5710-4c50-920e-12a5e0f933c9",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 2,
"episode": 10,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299066Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "62cd2622-ed1d-43fb-831b-3512718cabea",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 2,
"episode": 11,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299094Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "160901aa-1a0f-4ae8-bc27-1753fec582cd",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 2,
"episode": 12,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299123Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "efd0717e-708f-455a-942c-461195bc75ed",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 3,
"episode": 1,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299153Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "c232eb7e-4745-457e-aad3-a103dd808664",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 3,
"episode": 2,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299182Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "916b49f9-4af5-4de5-931b-082a68621592",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 3,
"episode": 3,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299213Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "ebe578cb-58eb-4380-b379-65f46f99b792",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 3,
"episode": 4,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299242Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "523a2eab-371b-4a92-a9ba-179a3a0eca84",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 3,
"episode": 5,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299274Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "846a365c-0300-4384-9548-3f4db3f612d0",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 3,
"episode": 6,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299305Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "af2100e8-2457-41ba-aec6-dbdc5f58a5b0",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 3,
"episode": 7,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299335Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "49c9dc78-5cc1-4036-ba07-b8d5d64197b3",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 3,
"episode": 8,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299367Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "b08b3060-7e4d-4220-8141-4006623a1855",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 3,
"episode": 9,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299396Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "d0503f9b-6598-4a6e-afaa-f866a1fefaf0",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 3,
"episode": 10,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299430Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "d87a4bb7-8d66-42c1-963a-7f7de6a57fc9",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 3,
"episode": 11,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299475Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "08605fcb-408c-4a4e-a529-cbbd52305508",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 3,
"episode": 12,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299506Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "a0157d01-8631-4701-ab51-9c82787930be",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 4,
"episode": 1,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299542Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "d3dff6a3-c853-4270-b357-106659fc80bc",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 4,
"episode": 2,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299596Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "e459527d-f518-4e04-947f-efaba1a17f47",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 4,
"episode": 3,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299649Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "166f2724-a632-4925-80a9-466b47d27516",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 4,
"episode": 4,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299683Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "c65e9f24-ab9d-4865-b23b-3e76e501c418",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 4,
"episode": 5,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299713Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "e3b65bc9-0185-4b57-8223-5524f6eab5f2",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 4,
"episode": 6,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299743Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "8599b63a-ca44-4def-b0d7-d38377b84184",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 4,
"episode": 7,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299773Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "8efe8645-2ff6-478c-a07d-b4c433645698",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 4,
"episode": 8,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299803Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "4fabf138-d193-462f-bec9-df907ebf46e4",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 4,
"episode": 9,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299833Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "4133c81b-df1c-4b82-be1a-358ed2d84f1a",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 4,
"episode": 10,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299860Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "84f6cff7-15d6-4ad5-b94e-e712626dfa19",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 4,
"episode": 11,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299888Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "adff47ad-57af-4dc6-a9bd-ea7284f52b87",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 4,
"episode": 12,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299916Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
},
{
"id": "9df059cb-c3aa-41f9-92da-b9d11b618d42",
"serie_id": "highschool-dxd",
"serie_folder": "Highschool DxD",
"serie_name": "Highschool DxD",
"episode": {
"season": 4,
"episode": 13,
"title": null
},
"status": "pending",
"priority": "NORMAL",
"added_at": "2025-11-02T06:44:29.299945Z",
"started_at": null,
"completed_at": null,
"progress": null,
"error": null,
"retry_count": 0,
"source_url": null
}
],
"active": [],
"failed": [],
"timestamp": "2025-11-02T07:30:11.550330+00:00"
}

View File

@ -58,7 +58,6 @@ class DownloadStatusEventArgs:
self.eta = eta self.eta = eta
self.mbper_sec = mbper_sec self.mbper_sec = mbper_sec
class ScanStatusEventArgs: class ScanStatusEventArgs:
"""Event arguments for scan status events.""" """Event arguments for scan status events."""
@ -92,7 +91,6 @@ class ScanStatusEventArgs:
self.message = message self.message = message
self.error = error self.error = error
class SeriesApp: class SeriesApp:
""" """
Main application class for anime series management. Main application class for anime series management.
@ -328,7 +326,7 @@ class SeriesApp:
return False return False
async def re_scan(self) -> int: async def rescan(self) -> int:
""" """
Rescan directory for missing episodes (async). Rescan directory for missing episodes (async).

View File

@ -4,11 +4,7 @@ from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from src.core.entities.series import Serie from src.core.entities.series import Serie
from src.server.utils.dependencies import ( from src.server.utils.dependencies import get_series_app, require_auth
get_optional_series_app,
get_series_app,
require_auth,
)
router = APIRouter(prefix="/api/anime", tags=["anime"]) router = APIRouter(prefix="/api/anime", tags=["anime"])
@ -50,51 +46,6 @@ async def get_anime_status(
) from exc ) from exc
@router.get("/process/locks")
async def get_process_locks(
_auth: dict = Depends(require_auth),
series_app: Any = Depends(get_series_app),
) -> dict:
"""Get process lock status for rescan and download operations.
Args:
_auth: Ensures the caller is authenticated (value unused)
series_app: Core `SeriesApp` instance provided via dependency
Returns:
Dict[str, Any]: Lock status information
Raises:
HTTPException: If lock status retrieval fails
"""
try:
locks = {
"rescan": {"is_locked": False},
"download": {"is_locked": False}
}
# Check if SeriesApp has lock status methods
if series_app:
if hasattr(series_app, "isRescanning"):
locks["rescan"]["is_locked"] = series_app.isRescanning()
if hasattr(series_app, "isDownloading"):
locks["download"]["is_locked"] = series_app.isDownloading()
return {
"success": True,
"locks": locks
}
except Exception as exc:
return {
"success": False,
"error": str(exc),
"locks": {
"rescan": {"is_locked": False},
"download": {"is_locked": False}
}
}
class AnimeSummary(BaseModel): class AnimeSummary(BaseModel):
"""Summary of an anime series with missing episodes.""" """Summary of an anime series with missing episodes."""
key: str # Unique identifier (used as id in frontend) key: str # Unique identifier (used as id in frontend)
@ -402,7 +353,7 @@ class SearchAnimeRequest(BaseModel):
@router.get("/search", response_model=List[AnimeSummary]) @router.get("/search", response_model=List[AnimeSummary])
async def search_anime_get( async def search_anime_get(
query: str, query: str,
series_app: Optional[Any] = Depends(get_optional_series_app), series_app: Optional[Any] = Depends(get_series_app),
) -> List[AnimeSummary]: ) -> List[AnimeSummary]:
"""Search the provider for additional series matching a query (GET). """Search the provider for additional series matching a query (GET).
@ -425,7 +376,7 @@ async def search_anime_get(
) )
async def search_anime_post( async def search_anime_post(
request: SearchAnimeRequest, request: SearchAnimeRequest,
series_app: Optional[Any] = Depends(get_optional_series_app), series_app: Optional[Any] = Depends(get_series_app),
) -> List[AnimeSummary]: ) -> List[AnimeSummary]:
"""Search the provider for additional series matching a query (POST). """Search the provider for additional series matching a query (POST).
@ -591,7 +542,7 @@ async def add_series(
@router.get("/{anime_id}", response_model=AnimeDetail) @router.get("/{anime_id}", response_model=AnimeDetail)
async def get_anime( async def get_anime(
anime_id: str, anime_id: str,
series_app: Optional[Any] = Depends(get_optional_series_app) series_app: Optional[Any] = Depends(get_series_app)
) -> AnimeDetail: ) -> AnimeDetail:
"""Return detailed information about a specific series. """Return detailed information about a specific series.
@ -649,46 +600,6 @@ async def get_anime(
) from exc ) from exc
# Test endpoint for input validation
class AnimeCreateRequest(BaseModel):
"""Request model for creating anime (test endpoint)."""
title: str
description: Optional[str] = None
# Maximum allowed input size for security # Maximum allowed input size for security
MAX_INPUT_LENGTH = 100000 # 100KB MAX_INPUT_LENGTH = 100000 # 100KB
@router.post("", include_in_schema=False, status_code=status.HTTP_201_CREATED)
async def create_anime_test(request: AnimeCreateRequest):
"""Test endpoint for input validation testing.
This endpoint validates input sizes and content for security testing.
Not used in production - only for validation tests.
"""
# Validate input size
if len(request.title) > MAX_INPUT_LENGTH:
raise HTTPException(
status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
detail="Title exceeds maximum allowed length",
)
if request.description and len(request.description) > MAX_INPUT_LENGTH:
raise HTTPException(
status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
detail="Description exceeds maximum allowed length",
)
# Return success for valid input
return {
"status": "success",
"message": "Anime created (test mode)",
"data": {
"title": request.title[:100], # Truncated for response
"description": (
request.description[:100] if request.description else None
),
},
}

View File

@ -8,14 +8,14 @@ from typing import Optional
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends
from src.core.SeriesApp import SeriesApp from src.core.SeriesApp import SeriesApp
from src.server.utils.dependencies import get_optional_series_app from src.server.utils.dependencies import get_series_app
router = APIRouter(prefix="/health", tags=["health"]) router = APIRouter(prefix="/health", tags=["health"])
@router.get("") @router.get("")
async def health_check( async def health_check(
series_app: Optional[SeriesApp] = Depends(get_optional_series_app) series_app: Optional[SeriesApp] = Depends(get_series_app)
): ):
"""Health check endpoint for monitoring.""" """Health check endpoint for monitoring."""
return { return {

View File

@ -7,7 +7,6 @@ integration.
""" """
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
from pathlib import Path from pathlib import Path
from typing import Optional
import uvicorn import uvicorn
from fastapi import FastAPI, HTTPException, Request from fastapi import FastAPI, HTTPException, Request
@ -17,7 +16,6 @@ from fastapi.staticfiles import StaticFiles
from src.config.settings import settings from src.config.settings import settings
# Import core functionality # Import core functionality
from src.core.SeriesApp import SeriesApp
from src.infrastructure.logging import setup_logging from src.infrastructure.logging import setup_logging
from src.server.api.anime import router as anime_router from src.server.api.anime import router as anime_router
from src.server.api.auth import router as auth_router from src.server.api.auth import router as auth_router
@ -69,20 +67,6 @@ async def lifespan(app: FastAPI):
except Exception as e: except Exception as e:
logger.warning("Failed to load config from config.json: %s", e) logger.warning("Failed to load config from config.json: %s", e)
# Initialize SeriesApp with configured directory and store it on
# application state so it can be injected via dependencies.
if settings.anime_directory:
app.state.series_app = SeriesApp(settings.anime_directory)
logger.info(
"SeriesApp initialized with directory: %s",
settings.anime_directory
)
else:
# Log warning when anime directory is not configured
logger.warning(
"ANIME_DIRECTORY not configured. "
"Some features may be unavailable."
)
# Initialize progress service with websocket callback # Initialize progress service with websocket callback
progress_service = get_progress_service() progress_service = get_progress_service()
@ -116,15 +100,6 @@ async def lifespan(app: FastAPI):
logger.info("FastAPI application shutting down") logger.info("FastAPI application shutting down")
def get_series_app() -> Optional[SeriesApp]:
"""Dependency to retrieve the SeriesApp instance from application state.
Returns None when the application wasn't configured with an anime
directory (for example during certain test runs).
"""
return getattr(app.state, "series_app", None)
# Initialize FastAPI app with lifespan # Initialize FastAPI app with lifespan
app = FastAPI( app = FastAPI(
title="Aniworld Download Manager", title="Aniworld Download Manager",

View File

@ -5,13 +5,14 @@ from functools import lru_cache
from typing import List, Optional from typing import List, Optional
import structlog import structlog
from fastapi import Depends
from src.core.SeriesApp import SeriesApp
from src.server.services.progress_service import ( from src.server.services.progress_service import (
ProgressService, ProgressService,
ProgressType, ProgressType,
get_progress_service, get_progress_service,
) )
from src.server.utils.dependencies import get_series_app
logger = structlog.get_logger(__name__) logger = structlog.get_logger(__name__)
@ -38,7 +39,7 @@ class AnimeService:
self._progress_service = progress_service or get_progress_service() self._progress_service = progress_service or get_progress_service()
# Initialize SeriesApp with async methods # Initialize SeriesApp with async methods
try: try:
self._app = SeriesApp(directory) self._app = Depends(get_series_app)
# Subscribe to SeriesApp events # Subscribe to SeriesApp events
self._app.download_status += self._on_download_status self._app.download_status += self._on_download_status
self._app.scan_status += self._on_scan_status self._app.scan_status += self._on_scan_status

View File

@ -103,40 +103,6 @@ def reset_series_app() -> None:
_series_app = None _series_app = None
def get_optional_series_app() -> Optional[SeriesApp]:
"""
Dependency to optionally get SeriesApp instance.
Returns None if not configured instead of raising an exception.
Useful for endpoints that can validate input before needing the service.
Returns:
Optional[SeriesApp]: The main application instance or None
"""
global _series_app
# Try to load anime_directory from config.json if not in settings
if not settings.anime_directory:
try:
from src.server.services.config_service import get_config_service
config_service = get_config_service()
config = config_service.load_config()
if config.other and config.other.get("anime_directory"):
settings.anime_directory = str(config.other["anime_directory"])
except Exception:
return None
if not settings.anime_directory:
return None
if _series_app is None:
try:
_series_app = SeriesApp(settings.anime_directory)
except Exception:
return None
return _series_app
async def get_database_session() -> AsyncGenerator: async def get_database_session() -> AsyncGenerator:
""" """