diff --git a/data/download_queue.json b/data/download_queue.json index fc92a62..cdbb2f3 100644 --- a/data/download_queue.json +++ b/data/download_queue.json @@ -1,6 +1,67 @@ { - "pending": [], + "pending": [ + { + "id": "b9598089-3874-4574-9b1f-d31669eab645", + "serie_id": "beheneko-the-elf-girls-cat-is-secretly-an-s-ranked-monster", + "serie_folder": "beheneko the elf girls cat is secretly an s ranked monster (2025) (2025)", + "serie_name": "beheneko the elf girls cat is secretly an s ranked monster (2025) (2025)", + "episode": { + "season": 1, + "episode": 2, + "title": null + }, + "status": "pending", + "priority": "NORMAL", + "added_at": "2025-11-01T17:20:49.339563Z", + "started_at": null, + "completed_at": null, + "progress": null, + "error": null, + "retry_count": 0, + "source_url": null + }, + { + "id": "b7626704-068f-4084-80b6-6f213c121412", + "serie_id": "beheneko-the-elf-girls-cat-is-secretly-an-s-ranked-monster", + "serie_folder": "beheneko the elf girls cat is secretly an s ranked monster (2025) (2025)", + "serie_name": "beheneko the elf girls cat is secretly an s ranked monster (2025) (2025)", + "episode": { + "season": 1, + "episode": 3, + "title": null + }, + "status": "pending", + "priority": "NORMAL", + "added_at": "2025-11-01T17:20:49.339620Z", + "started_at": null, + "completed_at": null, + "progress": null, + "error": null, + "retry_count": 0, + "source_url": null + }, + { + "id": "67d98e0a-ce51-4768-854d-33c565d9bf17", + "serie_id": "beheneko-the-elf-girls-cat-is-secretly-an-s-ranked-monster", + "serie_folder": "beheneko the elf girls cat is secretly an s ranked monster (2025) (2025)", + "serie_name": "beheneko the elf girls cat is secretly an s ranked monster (2025) (2025)", + "episode": { + "season": 1, + "episode": 4, + "title": null + }, + "status": "pending", + "priority": "NORMAL", + "added_at": "2025-11-01T17:20:49.339662Z", + "started_at": null, + "completed_at": null, + "progress": null, + "error": null, + "retry_count": 0, + "source_url": null + } + ], "active": [], "failed": [], - "timestamp": "2025-11-01T17:06:01.216246+00:00" + "timestamp": "2025-11-01T17:22:28.998624+00:00" } \ No newline at end of file diff --git a/src/server/models/download.py b/src/server/models/download.py index 6f09f76..0470598 100644 --- a/src/server/models/download.py +++ b/src/server/models/download.py @@ -161,7 +161,9 @@ class DownloadRequest(BaseModel): """Request to add episode(s) to the download queue.""" serie_id: str = Field(..., description="Series identifier (provider key)") - serie_folder: str = Field(..., description="Series folder name on disk") + serie_folder: Optional[str] = Field( + None, description="Series folder name on disk" + ) serie_name: str = Field( ..., min_length=1, description="Series name for display" ) diff --git a/src/server/web/static/js/app.js b/src/server/web/static/js/app.js index d335121..fe112b7 100644 --- a/src/server/web/static/js/app.js +++ b/src/server/web/static/js/app.js @@ -892,6 +892,7 @@ class AniWorldApp { } async downloadSelected() { + console.log('=== downloadSelected v1.1 - DEBUG VERSION ==='); if (this.selectedSeries.size === 0) { this.showToast('No series selected', 'warning'); return; @@ -899,6 +900,9 @@ class AniWorldApp { try { const folders = Array.from(this.selectedSeries); + console.log('=== Starting download for selected series ==='); + console.log('Selected folders:', folders); + console.log('seriesData:', this.seriesData); let totalEpisodesAdded = 0; let failedSeries = []; @@ -906,6 +910,14 @@ class AniWorldApp { for (const folder of folders) { const serie = this.seriesData.find(s => s.folder === folder); if (!serie || !serie.episodeDict) { + console.error('Serie not found or has no episodeDict:', folder, serie); + failedSeries.push(folder); + continue; + } + + // Validate required fields + if (!serie.key) { + console.error('Serie missing key:', serie); failedSeries.push(folder); continue; } @@ -924,22 +936,29 @@ class AniWorldApp { } if (episodes.length === 0) { + console.log('No episodes to add for serie:', serie.name); continue; } + // Use folder name as fallback if serie name is empty + const serieName = serie.name && serie.name.trim() ? serie.name : serie.folder; + // Add episodes to download queue + const requestBody = { + serie_id: serie.key, + serie_folder: serie.folder, + serie_name: serieName, + episodes: episodes, + priority: 'NORMAL' + }; + console.log('Sending queue add request:', requestBody); + const response = await this.makeAuthenticatedRequest('/api/queue/add', { method: 'POST', headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ - serie_id: serie.key, - serie_folder: serie.folder, - serie_name: serie.name, - episodes: episodes, - priority: 'NORMAL' - }) + body: JSON.stringify(requestBody) }); if (!response) { @@ -948,21 +967,37 @@ class AniWorldApp { } const data = await response.json(); - if (data.status === 'success') { + console.log('Queue add response:', response.status, data); + + // Log validation errors in detail + if (data.detail && Array.isArray(data.detail)) { + console.error('Validation errors:', JSON.stringify(data.detail, null, 2)); + } + + if (response.ok && data.status === 'success') { totalEpisodesAdded += episodes.length; } else { + console.error('Failed to add to queue:', data); failedSeries.push(folder); } } // Show result message + console.log('=== Download request complete ==='); + console.log('Total episodes added:', totalEpisodesAdded); + console.log('Failed series:', failedSeries); + if (totalEpisodesAdded > 0) { const message = failedSeries.length > 0 ? `Added ${totalEpisodesAdded} episode(s) to queue (${failedSeries.length} series failed)` : `Added ${totalEpisodesAdded} episode(s) to download queue`; this.showToast(message, 'success'); } else { - this.showToast('Failed to add episodes to queue', 'error'); + const errorDetails = failedSeries.length > 0 + ? `Failed series: ${failedSeries.join(', ')}` + : 'No episodes were added. Check browser console for details.'; + console.error('Failed to add episodes. Details:', errorDetails); + this.showToast('Failed to add episodes to queue. Check console for details.', 'error'); } } catch (error) { console.error('Download error:', error);