From e42e223f282f285edd46a5ff9819705170e040cf Mon Sep 17 00:00:00 2001 From: Lukas Date: Sun, 23 Nov 2025 11:45:34 +0100 Subject: [PATCH] refactory instructions --- data/config.json | 4 +- data/download_queue.json | 918 +---------------------------- instructions.md | 1176 +++++++++++++++++++++++++++++++++++++- 3 files changed, 1184 insertions(+), 914 deletions(-) diff --git a/data/config.json b/data/config.json index 6c2e839..cb9e2f3 100644 --- a/data/config.json +++ b/data/config.json @@ -17,8 +17,8 @@ "keep_days": 30 }, "other": { - "master_password_hash": "$pbkdf2-sha256$29000$MqZ0DsHYey8lpBSi9B5jbA$wWIxfV7Yzu.DR8RsTg2Zw5WNVH5aXDX8k7dNL0.RThU", - "anime_directory": "/home/lukas/Volume/serien/" + "master_password_hash": "$pbkdf2-sha256$29000$AsCYU2pNCYHwHoPwnlPqXQ$uHLpvUnvj9GmNFgkAAgk3Yvvp2WzLyMNUBwKMyH79CQ", + "anime_directory": "/mnt/server/serien/Serien/" }, "version": "1.0.0" } \ No newline at end of file diff --git a/data/download_queue.json b/data/download_queue.json index a339191..81445d3 100644 --- a/data/download_queue.json +++ b/data/download_queue.json @@ -1,920 +1,20 @@ { "pending": [ { - "id": "96d0ecfe-95f1-4f1d-abb8-493b88616e1b", - "serie_id": "highschool-dxd", - "serie_folder": "Highschool DxD", - "serie_name": "Highschool DxD", - "episode": { - "season": 1, - "episode": 4, - "title": null - }, - "status": "pending", - "priority": "NORMAL", - "added_at": "2025-11-20T17:12:34.485259Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "4a7d3c8e-e4f4-45ca-8c7e-c2f7ce9be201", - "serie_id": "highschool-dxd", - "serie_folder": "Highschool DxD", - "serie_name": "Highschool DxD", - "episode": { - "season": 1, - "episode": 5, - "title": null - }, - "status": "pending", - "priority": "NORMAL", - "added_at": "2025-11-20T17:12:34.485291Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "48ca2817-1ae3-4689-8463-648dcbdbaf58", - "serie_id": "highschool-dxd", - "serie_folder": "Highschool DxD", - "serie_name": "Highschool DxD", - "episode": { - "season": 1, - "episode": 6, - "title": null - }, - "status": "pending", - "priority": "NORMAL", - "added_at": "2025-11-20T17:12:34.485322Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "84c67d0c-4a8d-45e0-998d-dc6e9fe30b80", - "serie_id": "highschool-dxd", - "serie_folder": "Highschool DxD", - "serie_name": "Highschool DxD", - "episode": { - "season": 1, - "episode": 7, - "title": null - }, - "status": "pending", - "priority": "NORMAL", - "added_at": "2025-11-20T17:12:34.485352Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "35ab05bf-a868-447d-bd50-7a3f9179f3e4", - "serie_id": "highschool-dxd", - "serie_folder": "Highschool DxD", - "serie_name": "Highschool DxD", + "id": "03bfbf39-60b7-4790-ae9e-a158f654dafa", + "serie_id": "a-star-brighter-than-the-sun", + "serie_folder": "Ein Stern, heller als die Sonne (2025)", + "serie_name": "A Star Brighter Than the Sun", "episode": { "season": 1, "episode": 8, "title": null }, - "status": "pending", + "status": "cancelled", "priority": "NORMAL", - "added_at": "2025-11-20T17:12:34.485382Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "be6176db-16ab-407b-80c9-3bb5e4892e62", - "serie_id": "highschool-dxd", - "serie_folder": "Highschool DxD", - "serie_name": "Highschool DxD", - "episode": { - "season": 1, - "episode": 9, - "title": null - }, - "status": "pending", - "priority": "NORMAL", - "added_at": "2025-11-20T17:12:34.485413Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "4042e211-6622-40ee-8fb8-2872630d844b", - "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-20T17:12:34.485442Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "a68c2b0c-8bcb-4e6a-849e-a8d9f16b9072", - "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-20T17:12:34.485471Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "46e1c6a1-31d3-4342-989e-efaf8298e678", - "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-20T17:12:34.485501Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "b7107ecc-eb6d-4cc7-8365-68097993bfbf", - "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-20T17:12:34.485531Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "616640e2-33ad-426c-a5d4-de31ff35936b", - "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-20T17:12:34.485560Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "5b434516-2124-40bf-a844-9b5543a3e114", - "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-20T17:12:34.485590Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "c9b8a64f-5354-41b8-8884-0ca8a43ad44d", - "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-20T17:12:34.485619Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "3069002d-4a8e-40bd-b74b-7143cb6a32d0", - "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-20T17:12:34.485648Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "176dffae-ee80-4b0f-ac4f-8b7742645fec", - "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-20T17:12:34.485677Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "fb97418a-2185-4836-8db9-9562c2578f44", - "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-20T17:12:34.485706Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "d0b1373a-2332-42ed-acb1-1b5c1270dc29", - "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-20T17:12:34.485735Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "d1c78ecc-b52d-466b-bbec-60948b304527", - "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-20T17:12:34.485765Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "c2e6b528-bee4-4e1f-9647-70290813bedb", - "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-20T17:12:34.485793Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "84bba51b-b1dc-472e-b4fb-30c59ee37ea6", - "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-20T17:12:34.485821Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "57423a0c-26e7-4ca1-acb7-d4b119e4165a", - "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-20T17:12:34.485850Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "d6912e8c-6dab-4411-85dd-6dbfcf386938", - "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-20T17:12:34.485880Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "4a2addce-d5c7-4f92-b7e0-a9f94ac7abf1", - "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-20T17:12:34.485909Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "db5c2903-e7d1-441b-8c7b-9ac1d9ea8590", - "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-20T17:12:34.485937Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "a309484f-f71b-44a4-93e8-071084fa2146", - "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-20T17:12:34.485967Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "7f1344e4-2641-47df-866d-fb104ab3c6ec", - "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-20T17:12:34.485994Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "ee60decc-40bc-43d9-a3b8-1d47b82e0320", - "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-20T17:12:34.486023Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "ffaafc68-07cd-4bdc-81c4-1ec036a4ff25", - "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-20T17:12:34.486052Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "79b0c265-ce98-4266-8c25-63736892df9c", - "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-20T17:12:34.486080Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "13fbdec7-9cd3-47ba-8b6f-9d221c3c7681", - "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-20T17:12:34.486108Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "b55523fe-3404-47a1-bc70-07f86773abf4", - "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-20T17:12:34.486136Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "61694d69-9669-4ce4-9ea3-0548ca724b50", - "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-20T17:12:34.486177Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "cc127cff-ca74-4629-87f3-7dc7722ea83d", - "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-20T17:12:34.486207Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "7a9a36b7-a64a-4503-8f43-f8ae046a7e82", - "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-20T17:12:34.486237Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "d80412f1-bac4-4aa4-8482-2e1735a323f0", - "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-20T17:12:34.486264Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "0ad83b5b-c4ec-4a62-9e43-dfede343d38f", - "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-20T17:12:34.486293Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "8684655f-74da-4de6-9e4f-e0c588d49a09", - "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-20T17:12:34.486321Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "bac0e9b5-fe3f-4071-a637-ca738f55ceb0", - "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-20T17:12:34.486348Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "1e4be753-2b7c-4980-9ab8-f3bc05cfc996", - "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-20T17:12:34.486376Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "1ddffb36-6403-45b7-84e8-aba780d04b53", - "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-20T17:12:34.486403Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "1d872232-8dec-4839-8935-9f087a16ffbf", - "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-20T17:12:34.486432Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "cc124d9d-7bf2-4498-8d2e-a902d2cd22e5", - "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-20T17:12:34.486460Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "2f9f56ce-5145-407e-80f0-bcfd1c9ebfd6", - "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-20T17:12:34.486489Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "9266da92-26cb-46f5-a477-5dba009f84c7", - "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-20T17:12:34.486520Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "661c829a-adbe-4188-8edd-6db050f3b876", - "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-20T17:12:34.486550Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "3fc6a3dc-cbae-4bfa-bc3c-95f14486b172", - "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-20T17:12:34.486579Z", - "started_at": null, - "completed_at": null, + "added_at": "2025-11-22T16:36:10.705099Z", + "started_at": "2025-11-22T16:36:16.078860Z", + "completed_at": "2025-11-22T16:37:02.340465Z", "progress": null, "error": null, "retry_count": 0, @@ -923,5 +23,5 @@ ], "active": [], "failed": [], - "timestamp": "2025-11-20T18:27:28.516768+00:00" + "timestamp": "2025-11-22T16:37:02.340599+00:00" } \ No newline at end of file diff --git a/instructions.md b/instructions.md index 15b928e..7054948 100644 --- a/instructions.md +++ b/instructions.md @@ -128,7 +128,1177 @@ For each task completed: - No database schema changes required - WebSocket infrastructure remains unchanged -# Tasks +--- -[] check method from SeriesApp are used in a correct way. SeriesApp method changed. make sure that classes that use SeriesApp take the latest interface. -[] SeriesApp no have events make sure services and api use them +# 🎯 CRITICAL: Series Identifier Standardization + +## Overview + +**Problem:** The codebase currently uses multiple identifiers inconsistently: + +- `key` (provider identifier, e.g., "attack-on-titan") +- `folder` (filesystem folder name, e.g., "Attack on Titan (2013)") +- `serie_id` (sometimes key, sometimes folder) +- `serie_folder` (filesystem path used as identifier) + +**Solution:** Standardize on `key` as the single source of truth for all series identification. + +**Benefits:** + +- Single, consistent identifier throughout the codebase +- `key` is unique, provider-assigned, URL-safe +- `folder` becomes metadata only (not used for lookups) +- Clearer separation of concerns +- Easier to maintain and debug + +**Scope:** This affects core logic, services, API endpoints, frontend, WebSocket events, and tests. + +--- + +## Task Series: Identifier Standardization + +### Phase 1: Core Models and Data Layer + +#### Task 1.1: Update Serie Class to Enforce Key as Primary Identifier + +**File:** [`src/core/entities/series.py`](src/core/entities/series.py) + +**Objective:** Ensure `Serie` class uses `key` as the primary identifier and add validation. + +**Steps:** + +1. Open [`src/core/entities/series.py`](src/core/entities/series.py) +2. Add validation in `__init__` to ensure `key` is never empty +3. Add a docstring clarifying that `key` is the unique identifier +4. Add validation to prevent `key` from being set to empty string +5. Ensure `folder` is documented as "filesystem folder name (metadata only)" + +**Success Criteria:** + +- [ ] `key` property has validation preventing empty values +- [ ] Docstrings clearly state `key` is the unique identifier +- [ ] `folder` is documented as metadata only +- [ ] All existing tests for `Serie` still pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/test_anime_models.py -v +``` + +--- + +#### Task 1.2: Update SerieList to Use Key for Lookups + +**File:** [`src/core/entities/SerieList.py`](src/core/entities/SerieList.py) + +**Objective:** Change `SerieList` internal storage to use `key` instead of `folder` as the dictionary key. + +**Steps:** + +1. Open [`src/core/entities/SerieList.py`](src/core/entities/SerieList.py) +2. Change `self.folderDict` to `self.keyDict` (rename for clarity) +3. Update `add()` method to use `serie.key` as dictionary key +4. Update `contains()` method to check by `key` instead of `folder` +5. Update `load_series()` to store series by `key` +6. Update all internal methods that access the dictionary +7. Add helper method `get_by_key(key: str) -> Optional[Serie]` +8. Add helper method `get_by_folder(folder: str) -> Optional[Serie]` for backward compatibility + +**Success Criteria:** + +- [ ] Internal dictionary keyed by `serie.key` +- [ ] `add()`, `contains()`, `GetList()` work correctly +- [ ] Helper methods `get_by_key()` and `get_by_folder()` implemented +- [ ] All existing tests pass +- [ ] No breaking changes to public API + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/ -k "SerieList" -v +``` + +--- + +#### Task 1.3: Update SerieScanner to Use Key Consistently + +**File:** [`src/core/SerieScanner.py`](src/core/SerieScanner.py) + +**Objective:** Ensure `SerieScanner` identifies and stores series by `key`. + +**Steps:** + +1. Open [`src/core/SerieScanner.py`](src/core/SerieScanner.py) +2. Update `scan()` method to use `serie.key` for all operations +3. Update `self.folderDict` to use `key` as dictionary key (or rename to `self.keyDict`) +4. Ensure all error logging and progress callbacks reference `key` not `folder` +5. Update `__read_data_from_file()` to validate `key` exists before proceeding +6. Add debug logging showing both `key` and `folder` for clarity + +**Success Criteria:** + +- [ ] Scanner stores series by `key` +- [ ] Progress callbacks use `key` for identification +- [ ] Error messages reference `key` and `folder` appropriately +- [ ] All scanner tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/ -k "SerieScanner" -v +``` + +--- + +#### Task 1.4: Update Provider Classes to Use Key + +**Files:** + +- [`src/core/providers/aniworld_provider.py`](src/core/providers/aniworld_provider.py) +- [`src/core/providers/enhanced_provider.py`](src/core/providers/enhanced_provider.py) + +**Objective:** Update provider download methods to use `key` for identification while keeping `serieFolder` for filesystem operations. + +**Steps:** + +1. Open [`src/core/providers/aniworld_provider.py`](src/core/providers/aniworld_provider.py) +2. Update `download()` method signature: + - Add `key: str` parameter as first identifier parameter + - Keep `serie_folder: str` parameter for filesystem operations + - Update docstring to clarify: `key` is the series identifier, `serie_folder` is for file paths +3. Update all logging and error messages to reference `key` instead of folder +4. Repeat for [`src/core/providers/enhanced_provider.py`](src/core/providers/enhanced_provider.py) +5. Update the `Download()` method similarly +6. Ensure all error handling and recovery logic uses `key` for identification + +**Success Criteria:** + +- [ ] Both provider classes accept `key` as primary identifier +- [ ] `serie_folder` only used for file path construction +- [ ] Logging references `key` for identification +- [ ] All error messages use `key` +- [ ] All provider tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/ -k "provider" -v +``` + +--- + +#### Task 1.5: Update Provider Factory to Use Key + +**File:** `src/core/providers/provider_factory.py` + +**Objective:** Ensure provider factory uses `key` for provider selection and series identification. + +**Steps:** + +1. Open `src/core/providers/provider_factory.py` +2. Review `get_provider()` method and ensure it can work with `key` +3. Update any caching or provider lookup logic to use `key` +4. Ensure provider instances receive `key` for operations +5. Update docstrings + +**Success Criteria:** + +- [ ] Provider factory works with `key` identifiers +- [ ] No breaking changes to provider interface +- [ ] All provider factory tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/ -k "provider_factory" -v +``` + +--- + +### Phase 2: Core Application Layer + +#### Task 2.1: Update SeriesApp to Use Key for All Operations + +**File:** [`src/core/SeriesApp.py`](src/core/SeriesApp.py) + +**Objective:** Standardize `SeriesApp` to use `key` instead of `folder` for series identification. + +**Steps:** + +1. Open [`src/core/SeriesApp.py`](src/core/SeriesApp.py) +2. Update `download()` method signature: + - Keep `serie_folder` parameter for filesystem operations + - Add docstring clarifying `serie_folder` is for file paths only + - Ensure `key` is the primary lookup identifier +3. Update all internal lookups to use `key` +4. Update event emissions to include both `key` and `folder` +5. Add helper method `_get_serie_by_key(key: str) -> Optional[Serie]` +6. Ensure all method docstrings clarify identifier usage + +**Success Criteria:** + +- [ ] All methods use `key` for series identification +- [ ] `serie_folder` only used for filesystem operations +- [ ] Events include both `key` and `folder` +- [ ] Docstrings are clear about parameter usage +- [ ] All SeriesApp tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/test_series_app.py -v +``` + +--- + +#### Task 2.2: Update Callback Interfaces to Use Key + +**File:** [`src/core/interfaces/callbacks.py`](src/core/interfaces/callbacks.py) + +**Objective:** Ensure callback interfaces use `key` in all progress and event contexts. + +**Steps:** + +1. Open [`src/core/interfaces/callbacks.py`](src/core/interfaces/callbacks.py) +2. Review `ProgressContext` and other context classes +3. Ensure context classes include `key` field where series is referenced +4. Add `folder` field as optional metadata +5. Update docstrings to clarify `key` vs `folder` usage +6. Ensure backward compatibility where needed + +**Success Criteria:** + +- [ ] Context classes include `key` field +- [ ] `folder` included as optional metadata +- [ ] Docstrings clearly document field usage +- [ ] All callback tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/test_callbacks.py -v +``` + +--- + +### Phase 3: Service Layer + +#### Task 3.1: Update DownloadService to Use Key + +**File:** [`src/server/services/download_service.py`](src/server/services/download_service.py) + +**Objective:** Change `DownloadService` to use `key` as the series identifier instead of mixing `serie_id` and `serie_folder`. + +**Steps:** + +1. Open [`src/server/services/download_service.py`](src/server/services/download_service.py) +2. In `add_to_queue()` method: + - Rename parameter `serie_id` to `series_key` (or keep as `serie_id` but document it's the key) + - Keep `serie_folder` for filesystem operations + - Keep `serie_name` for display + - Update docstring to clarify: `serie_id` is the provider key +3. Update `DownloadItem` dataclass: + - Change `serie_id` to use `key` + - Keep `serie_folder` for file operations +4. Update all internal methods to use `key` consistently +5. Update logging to reference `key` instead of `folder` + +**Success Criteria:** + +- [ ] `add_to_queue()` uses `key` for identification +- [ ] `DownloadItem` uses `key` as identifier +- [ ] Filesystem operations still use `serie_folder` +- [ ] All download service tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/ -k "DownloadService" -v +``` + +--- + +#### Task 3.2: Update AnimeService to Use Key + +**File:** [`src/server/services/anime_service.py`](src/server/services/anime_service.py) + +**Objective:** Ensure `AnimeService` uses `key` for all series operations. + +**Steps:** + +1. Open [`src/server/services/anime_service.py`](src/server/services/anime_service.py) +2. Update `download()` method to use `key` for series lookup +3. Update `get_series_list()` to return series with `key` as identifier +4. Update all event handlers to use `key` +5. Ensure all lookups in `_app` (SeriesApp) use `key` +6. Update docstrings to clarify identifier usage + +**Success Criteria:** + +- [ ] All methods use `key` for series identification +- [ ] Event handlers use `key` +- [ ] Docstrings are clear +- [ ] All anime service tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/ -k "AnimeService" -v +``` + +--- + +#### Task 3.3: Update ProgressService to Use Key + +**File:** [`src/server/services/progress_service.py`](src/server/services/progress_service.py) + +**Objective:** Ensure `ProgressService` uses `key` for all progress tracking. + +**Steps:** + +1. Open [`src/server/services/progress_service.py`](src/server/services/progress_service.py) +2. Review all methods that handle progress events +3. Ensure progress events include `key` as identifier +4. Update any internal tracking to use `key` instead of `folder` +5. Update event payloads to include both `key` and `folder` where needed +6. Update docstrings to clarify identifier usage + +**Success Criteria:** + +- [ ] All progress events include `key` +- [ ] Internal tracking uses `key` +- [ ] Event payloads structured correctly +- [ ] All progress service tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/ -k "ProgressService" -v +``` + +--- + +#### Task 3.4: Update ScanService to Use Key + +**File:** [`src/server/services/scan_service.py`](src/server/services/scan_service.py) + +**Objective:** Ensure `ScanService` uses `key` for all scan operations. + +**Steps:** + +1. Open [`src/server/services/scan_service.py`](src/server/services/scan_service.py) +2. Review all methods that handle scan events +3. Ensure scan progress events use `key` for identification +4. Update any callbacks to use `key` +5. Update event emissions to include both `key` and `folder` +6. Update docstrings + +**Success Criteria:** + +- [ ] All scan operations use `key` +- [ ] Callbacks receive `key` as identifier +- [ ] Events include both `key` and `folder` +- [ ] All scan service tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/ -k "ScanService" -v +``` + +--- + +### Phase 4: API Layer + +#### Task 4.1: Update Anime API Endpoints to Use Key + +**File:** [`src/server/api/anime.py`](src/server/api/anime.py) + +**Objective:** Standardize all anime API endpoints to use `key` as the series identifier. + +**Steps:** + +1. Open [`src/server/api/anime.py`](src/server/api/anime.py) +2. Update `AnimeSummary` model: + - Ensure `key` is the primary identifier + - Document `folder` as metadata only +3. Update `get_anime()` endpoint: + - Accept `anime_id` as the `key` + - Update lookup logic to use `key` + - Keep backward compatibility by checking both `key` and `folder` +4. Update `add_series()` endpoint: + - Use `key` from the link as identifier + - Store `folder` as metadata +5. Update `_perform_search()`: + - Return `key` as the identifier + - Include `folder` as separate field +6. Update all docstrings to clarify identifier usage + +**Success Criteria:** + +- [ ] All endpoints use `key` as identifier +- [ ] Backward compatibility maintained +- [ ] API responses include both `key` and `folder` +- [ ] All anime API tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/api/test_anime_endpoints.py -v +``` + +--- + +#### Task 4.2: Update Download API Endpoints to Use Key + +**File:** [`src/server/api/download.py`](src/server/api/download.py) + +**Objective:** Ensure download API uses `key` for series identification. + +**Steps:** + +1. Open [`src/server/api/download.py`](src/server/api/download.py) +2. Update `DownloadRequest` model: + - Rename or document `serie_id` as `series_key` + - Keep `serie_folder` for filesystem operations + - Keep `serie_name` for display +3. Update `add_to_queue()` endpoint: + - Use `series_key` for series identification + - Pass `serie_folder` to download service +4. Update all docstrings + +**Success Criteria:** + +- [ ] Request model uses `key` as identifier +- [ ] Endpoint passes correct identifiers to service +- [ ] All download API tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/api/ -k "download" -v +``` + +--- + +#### Task 4.3: Update Queue API Endpoints to Use Key + +**File:** [`src/server/api/queue.py`](src/server/api/queue.py) + +**Objective:** Ensure queue API endpoints use `key` for series identification. + +**Steps:** + +1. Open [`src/server/api/queue.py`](src/server/api/queue.py) +2. Review all queue-related endpoints +3. Update request/response models to use `key` as identifier +4. Ensure queue status includes `key` in item data +5. Update queue manipulation endpoints to accept `key` +6. Update docstrings and OpenAPI documentation + +**Success Criteria:** + +- [ ] All queue endpoints use `key` +- [ ] Queue status responses include `key` +- [ ] Request models use `key` for identification +- [ ] All queue API tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/api/ -k "queue" -v +``` + +--- + +#### Task 4.4: Update WebSocket API Endpoints to Use Key + +**File:** `src/server/api/websocket.py` + +**Objective:** Ensure WebSocket API endpoint handlers use `key` for series identification. + +**Steps:** + +1. Open `src/server/api/websocket.py` +2. Review all WebSocket message handlers +3. Ensure messages use `key` for series identification +4. Update message schemas to include `key` field +5. Keep `folder` for display purposes +6. Update docstrings + +**Success Criteria:** + +- [ ] All WebSocket handlers use `key` +- [ ] Message schemas include `key` +- [ ] All WebSocket API tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/api/ -k "websocket" -v +``` + +--- + +#### Task 4.5: Update Pydantic Models to Use Key + +**Files:** + +- `src/server/models/anime.py` +- `src/server/models/download.py` + +**Objective:** Ensure all Pydantic models use `key` as the series identifier. + +**Steps:** + +1. Open `src/server/models/anime.py` +2. Review all models (e.g., `AnimeDetail`, `AnimeSummary`, `SearchResult`) +3. Ensure `key` is the primary identifier field +4. Add `folder` as optional metadata field +5. Update field validators to validate `key` format +6. Repeat for `src/server/models/download.py` +7. Update `DownloadRequest` and related models +8. Update all docstrings and field descriptions + +**Success Criteria:** + +- [ ] All anime models use `key` as identifier +- [ ] All download models use `key` as identifier +- [ ] Field validators ensure `key` format is correct +- [ ] `folder` is optional metadata +- [ ] All model tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/ -k "models" -v +``` + +--- + +#### Task 4.6: Update Validators to Use Key + +**File:** `src/server/utils/validators.py` + +**Objective:** Ensure validation functions validate `key` instead of `folder`. + +**Steps:** + +1. Open `src/server/utils/validators.py` +2. Review all validation functions +3. Add `validate_series_key()` function if not exists +4. Update any validators that check series identifiers +5. Ensure validators accept `key` format (URL-safe, lowercase with hyphens) +6. Add tests for key validation + +**Success Criteria:** + +- [ ] Validators validate `key` format +- [ ] No validators use `folder` for identification +- [ ] Validation functions well-documented +- [ ] All validator tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/ -k "validator" -v +``` + +--- + +#### Task 4.7: Update Template Helpers to Use Key + +**File:** `src/server/utils/template_helpers.py` + +**Objective:** Ensure template helpers pass `key` to templates for series identification. + +**Steps:** + +1. Open `src/server/utils/template_helpers.py` +2. Review all helper functions +3. Ensure functions that handle series data use `key` +4. Update any filtering or sorting to use `key` +5. Ensure `folder` is available for display purposes +6. Update docstrings + +**Success Criteria:** + +- [ ] All helpers use `key` for identification +- [ ] `folder` available for display +- [ ] No breaking changes to template interface +- [ ] All template helper tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/ -k "template" -v +``` + +--- + +### Phase 5: Frontend + +#### Task 5.1: Update Frontend JavaScript to Use Key + +**File:** [`src/server/web/static/js/app.js`](src/server/web/static/js/app.js) + +**Objective:** Update frontend to use `key` as the primary series identifier instead of `folder`. + +**Steps:** + +1. Open [`src/server/web/static/js/app.js`](src/server/web/static/js/app.js) +2. Update `seriesData` storage to index by `key` +3. Update `selectedSeries` Set to use `key` instead of `folder` +4. Update `createSerieCard()`: + - Use `data-key` attribute instead of `data-folder` + - Display `folder` as metadata only +5. Update `toggleSerieSelection()` to use `key` +6. Update `downloadSelected()`: + - Send `key` as `serie_id` + - Include `folder` for filesystem operations +7. Update all event handlers and lookups to use `key` +8. Keep `folder` visible in UI for user reference + +**Success Criteria:** + +- [ ] Frontend uses `key` for all series operations +- [ ] `folder` displayed in UI but not used for identification +- [ ] Selection tracking uses `key` +- [ ] All frontend interactions work correctly + +**Manual Test:** + +1. Start server +2. Login to web interface +3. Verify series list displays correctly +4. Test selecting series (should use key internally) +5. Test downloading episodes +6. Verify search functionality + +--- + +#### Task 5.2: Update WebSocket Events to Use Key + +**File:** [`src/server/services/websocket_service.py`](src/server/services/websocket_service.py) + +**Objective:** Ensure WebSocket events use `key` for series identification. + +**Steps:** + +1. Open [`src/server/services/websocket_service.py`](src/server/services/websocket_service.py) +2. Update `broadcast_download_progress()`: + - Include `key` in event data + - Keep `folder` for display purposes +3. Update `broadcast_scan_progress()` similarly +4. Update all event broadcasts to include `key` +5. Update event handler subscriptions to use `key` + +**Success Criteria:** + +- [ ] All WebSocket events include `key` +- [ ] Events also include `folder` for display +- [ ] All WebSocket tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/test_websocket_service.py -v +``` + +--- + +#### Task 5.3: Update Additional Frontend JavaScript Files + +**Files:** + +- `src/server/web/static/js/websocket.js` +- `src/server/web/static/js/queue.js` +- `src/server/web/static/js/download.js` +- `src/server/web/static/js/utils.js` + +**Objective:** Ensure all frontend JavaScript modules use `key` for series identification. + +**Steps:** + +1. **Update `websocket.js`:** + + - Open `src/server/web/static/js/websocket.js` + - Review all message handlers + - Ensure event payloads use `key` for identification + - Update event listeners to use `key` + - Keep `folder` for display + +2. **Update `queue.js`:** + + - Open `src/server/web/static/js/queue.js` + - Update queue item identification to use `key` + - Update queue manipulation functions + - Ensure queue display shows both `key` and `folder` + +3. **Update `download.js`:** + + - Open `src/server/web/static/js/download.js` + - Update download request building to use `key` + - Update progress tracking to use `key` + - Keep `folder` for file path operations + +4. **Update `utils.js`:** + - Open `src/server/web/static/js/utils.js` + - Review utility functions that handle series data + - Ensure utilities use `key` for identification + - Update any series-related helper functions + +**Success Criteria:** + +- [ ] All JavaScript modules use `key` for identification +- [ ] WebSocket handlers use `key` +- [ ] Queue operations use `key` +- [ ] Download operations use `key` +- [ ] Utilities handle `key` correctly +- [ ] `folder` displayed in UI where appropriate +- [ ] All frontend functionality works correctly + +**Manual Test:** + +1. Test WebSocket connectivity and events +2. Test queue management +3. Test download functionality +4. Verify all series operations use `key` + +--- + +#### Task 5.4: Update HTML Templates to Use Key + +**Files:** All templates in `src/server/web/templates/` + +**Objective:** Ensure all HTML templates use `key` for series identification in data attributes and forms. + +**Steps:** + +1. Review all template files: + + - `index.html` + - `anime_detail.html` + - `search.html` + - Any other templates using series data + +2. For each template: + + - Update data attributes to use `data-key` instead of `data-folder` + - Keep `data-folder` for display purposes if needed + - Update form inputs to submit `key` as identifier + - Update JavaScript references to use `key` + - Display `folder` for user-friendly names + +3. Update template variables: + - Ensure templates receive `key` from backend + - Verify `folder` is available for display + - Update any template logic that filters/sorts by series + +**Success Criteria:** + +- [ ] All templates use `data-key` for identification +- [ ] Forms submit `key` as identifier +- [ ] `folder` displayed for user reference +- [ ] No templates use `folder` for identification +- [ ] All template rendering works correctly + +**Manual Test:** + +1. Verify all pages render correctly +2. Test form submissions +3. Verify JavaScript interactions +4. Check data attributes in browser dev tools + +--- + +### Phase 6: Database Layer + +#### Task 6.1: Verify Database Models Use Key Correctly + +**File:** [`src/server/database/models.py`](src/server/database/models.py) + +**Objective:** Verify and document that database models correctly use `key` as unique identifier. + +**Steps:** + +1. Open [`src/server/database/models.py`](src/server/database/models.py) +2. Verify `AnimeSeries.key` is unique and indexed +3. Verify `AnimeSeries.folder` is not used for lookups +4. Update docstrings to clarify identifier usage +5. Ensure all relationships use `id` (primary key) not `key` or `folder` + +**Success Criteria:** + +- [ ] `key` is unique and indexed +- [ ] `folder` is metadata only +- [ ] Docstrings are clear +- [ ] All database model tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/test_database_models.py -v +``` + +--- + +#### Task 6.2: Update Database Services to Use Key + +**File:** [`src/server/database/service.py`](src/server/database/service.py) + +**Objective:** Ensure all database service methods use `key` for series lookup. + +**Steps:** + +1. Open [`src/server/database/service.py`](src/server/database/service.py) +2. Verify `AnimeSeriesService.get_by_key()` is used for lookups +3. Verify no methods use `folder` for identification +4. Update any methods that incorrectly use `folder` for lookups +5. Add migration helper if needed to update existing data + +**Success Criteria:** + +- [ ] All service methods use `key` for lookups +- [ ] `folder` never used as identifier +- [ ] All database service tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/unit/test_database_service.py -v +``` + +--- + +### Phase 7: Testing and Validation + +#### Task 7.1: Update All Test Fixtures to Use Key + +**Files:** All test files in [`tests/`](tests/) + +**Objective:** Ensure all test fixtures and mocks use `key` consistently. + +**Steps:** + +1. Search for all test files using `folder` as identifier +2. Update `FakeSerie` class in [`tests/api/test_anime_endpoints.py`](tests/api/test_anime_endpoints.py): + - Ensure `key` is the primary identifier +3. Update all test fixtures to use `key` +4. Update mock data to use realistic `key` values +5. Ensure tests verify both `key` and `folder` are present but only `key` is used for operations + +**Success Criteria:** + +- [ ] All test fixtures use `key` as identifier +- [ ] Tests verify `key` is used for operations +- [ ] Tests verify `folder` is present as metadata +- [ ] All tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/ -v +``` + +--- + +#### Task 7.2: Add Integration Tests for Identifier Consistency + +**File:** Create new file `tests/integration/test_identifier_consistency.py` + +**Objective:** Create integration tests to verify `key` is used consistently across all layers. + +**Steps:** + +1. Create [`tests/integration/test_identifier_consistency.py`](tests/integration/test_identifier_consistency.py) +2. Write test to verify: + - API endpoint returns `key` as identifier + - Download service uses `key` + - Database lookups use `key` + - WebSocket events include `key` +3. Write test to verify `folder` is never used for lookups +4. Write test for end-to-end flow using `key` + +**Success Criteria:** + +- [ ] Integration test file created +- [ ] Tests verify `key` usage across all layers +- [ ] Tests verify `folder` not used for identification +- [ ] All integration tests pass + +**Test Command:** + +```bash +conda run -n AniWorld python -m pytest tests/integration/test_identifier_consistency.py -v +``` + +--- + +### Phase 8: Documentation and Cleanup + +#### Task 8.1: Update Infrastructure Documentation + +**File:** [`infrastructure.md`](infrastructure.md) + +**Objective:** Document the identifier standardization in infrastructure documentation. + +**Steps:** + +1. Open [`infrastructure.md`](infrastructure.md) +2. Add section explaining identifier usage: + - `key`: Unique series identifier (provider-assigned) + - `folder`: Filesystem folder name (metadata only) + - `id`: Database primary key (internal use) +3. Update all API documentation to show `key` as identifier +4. Update data model documentation +5. Add migration notes if needed + +**Success Criteria:** + +- [ ] Documentation clearly explains identifier usage +- [ ] All API examples use `key` +- [ ] Data model section updated +- [ ] Migration notes added if applicable + +--- + +#### Task 8.2: Update README and Developer Documentation + +**Files:** [`README.md`](README.md), [`docs/`](docs/) + +**Objective:** Update all developer-facing documentation. + +**Steps:** + +1. Update main README to explain identifier usage +2. Update any developer guides to use `key` +3. Add note about backward compatibility with `folder` +4. Update code examples to use `key` + +**Success Criteria:** + +- [ ] README updated +- [ ] Developer guides updated +- [ ] Code examples use `key` +- [ ] Backward compatibility documented + +--- + +#### Task 8.3: Add Deprecation Warnings for Folder-Based Lookups + +**Files:** Various service and API files + +**Objective:** Add deprecation warnings where `folder` is still accepted for backward compatibility. + +**Steps:** + +1. Identify all methods that accept `folder` for lookups +2. Add deprecation warnings using Python's `warnings` module +3. Update docstrings to indicate deprecation +4. Plan removal timeline (e.g., next major version) + +**Success Criteria:** + +- [ ] Deprecation warnings added +- [ ] Docstrings indicate deprecation +- [ ] Removal timeline documented +- [ ] Tests updated to suppress warnings + +--- + +### Phase 9: Final Validation + +#### Task 9.1: Run Full Test Suite + +**Objective:** Verify all changes work together correctly. + +**Steps:** + +1. Run complete test suite: + ```bash + conda run -n AniWorld python -m pytest tests/ -v --tb=short + ``` +2. Fix any failing tests +3. Verify test coverage is maintained +4. Run integration tests +5. Run manual UI tests + +**Success Criteria:** + +- [ ] All unit tests pass +- [ ] All integration tests pass +- [ ] All API tests pass +- [ ] Test coverage >= 80% +- [ ] Manual UI testing successful + +--- + +#### Task 9.2: Manual End-to-End Testing + +**Objective:** Manually verify all features work with the new identifier system. + +**Steps:** + +1. Start server: `conda run -n AniWorld python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 --reload` +2. Login to web interface +3. Test search functionality (verify results show `key`) +4. Test adding new series (verify uses `key`) +5. Test downloading episodes (verify uses `key`) +6. Test WebSocket events (verify events include `key`) +7. Verify database contains correct `key` values +8. Test rescan functionality + +**Success Criteria:** + +- [ ] Search works correctly +- [ ] Adding series works +- [ ] Downloads work correctly +- [ ] WebSocket events work +- [ ] Database entries correct +- [ ] Rescan functionality works + +--- + +#### Task 9.3: Performance and Load Testing + +**Objective:** Ensure identifier changes don't impact performance. + +**Steps:** + +1. Run performance tests on key operations: + - Series lookup by `key` + - Database queries using `key` + - API response times +2. Compare with baseline if available +3. Identify any performance regressions +4. Optimize if needed + +**Success Criteria:** + +- [ ] No significant performance regression +- [ ] Lookup by `key` is fast +- [ ] Database queries optimized +- [ ] API response times acceptable + +--- + +### Phase 10: Deployment + +#### Task 10.1: Create Migration Script + +**Objective:** Create script to migrate existing data if needed. + +**Steps:** + +1. Create [`scripts/migrate_identifiers.py`](scripts/migrate_identifiers.py) +2. Script should: + - Check all series have valid `key` values + - Update any references that incorrectly use `folder` + - Validate database integrity + - Create backup before migration +3. Add rollback capability +4. Test migration on test data + +**Success Criteria:** + +- [ ] Migration script created +- [ ] Script validates data +- [ ] Backup functionality works +- [ ] Rollback capability tested +- [ ] Migration tested on test data + +--- + +#### Task 10.2: Update Deployment Documentation + +**File:** Update deployment section in [`instructions.md`](instructions.md) + +**Objective:** Document deployment steps for identifier changes. + +**Steps:** + +1. Add pre-deployment checklist +2. Document migration steps +3. Add rollback procedure +4. Document verification steps +5. Add troubleshooting guide + +**Success Criteria:** + +- [ ] Deployment steps documented +- [ ] Migration procedure clear +- [ ] Rollback procedure documented +- [ ] Verification steps listed +- [ ] Troubleshooting guide added + +--- + +#### Task 10.3: Deploy to Production + +**Objective:** Deploy changes to production environment. + +**Steps:** + +1. Create deployment tag: `v2.0.0-identifier-standardization` +2. Backup production database +3. Run migration script +4. Deploy new code +5. Monitor logs for errors +6. Verify production functionality +7. Monitor for 24 hours + +**Success Criteria:** + +- [ ] Deployment tag created +- [ ] Database backed up +- [ ] Migration successful +- [ ] Code deployed +- [ ] No errors in logs +- [ ] All features working +- [ ] 24-hour monitoring completed + +--- + +## Task Tracking + +### Completion Status + +- [ ] Phase 1: Core Models and Data Layer + - [ ] Task 1.1: Update Serie Class + - [ ] Task 1.2: Update SerieList + - [ ] Task 1.3: Update SerieScanner + - [ ] **Task 1.4: Update Provider Classes** ⭐ NEW +- [ ] Phase 2: Core Application Layer + - [ ] Task 2.1: Update SeriesApp + - [ ] **Task 2.2: Update Callback Interfaces** ⭐ NEW +- [ ] Phase 3: Service Layer + - [ ] Task 3.1: Update DownloadService + - [ ] Task 3.2: Update AnimeService + - [ ] **Task 3.3: Update ProgressService** ⭐ NEW + - [ ] **Task 3.4: Update ScanService** ⭐ NEW +- [ ] Phase 4: API Layer + - [ ] Task 4.1: Update Anime API Endpoints + - [ ] Task 4.2: Update Download API Endpoints + - [ ] **Task 4.3: Update Queue API Endpoints** ⭐ NEW + - [ ] **Task 4.4: Update WebSocket API Endpoints** ⭐ NEW + - [ ] **Task 4.5: Update Pydantic Models** ⭐ NEW + - [ ] **Task 4.6: Update Validators** ⭐ NEW + - [ ] **Task 4.7: Update Template Helpers** ⭐ NEW +- [ ] Phase 5: Frontend + - [ ] Task 5.1: Update Frontend JavaScript + - [ ] Task 5.2: Update WebSocket Events + - [ ] Task 5.3: Update Additional Frontend JavaScript Files + - [ ] Task 5.4: Update HTML Templates +- [ ] Phase 6: Database Layer + - [ ] Task 6.1: Verify Database Models + - [ ] Task 6.2: Update Database Services +- [ ] Phase 7: Testing and Validation + - [ ] Task 7.1: Update Test Fixtures + - [ ] Task 7.2: Add Integration Tests +- [ ] Phase 8: Documentation and Cleanup + - [ ] Task 8.1: Update Infrastructure Documentation + - [ ] Task 8.2: Update README + - [ ] Task 8.3: Add Deprecation Warnings +- [ ] Phase 9: Final Validation