From 13f9a27af86e4d358cea7e7fe80322a7b9f0ecb7 Mon Sep 17 00:00:00 2001 From: MasutaYunikon Date: Sat, 21 Mar 2026 07:58:45 +0100 Subject: [PATCH] =?UTF-8?q?fix(series):=20r=C3=A9solution=20boutons=20de?= =?UTF-8?q?=20t=C3=A9l=C3=A9chargement=20saisons=20Yu-Gi-Oh=20et=20s=C3=A9?= =?UTF-8?q?ries=20similaires?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Les boutons "Saison entière" n'apparaissaient pas pour les séries dont les season_id du scraper ne correspondent pas aux season_id de l'API Fankai. - Ajouter seasonTorrentMapBySn indexé par season_number en fallback - Utiliser season_number comme clé de secours dans enrichedSeasons fix(catalogue): état "partiel" incorrect quand l'intégrale est organisée Le badge partial s'affichait même quand tous les épisodes étaient organisés via un pack_integrale, car les torrents d'épisodes séparés faisaient baisser le ratio. La logique est maintenant basée sur les episode_id uniques. feat(series-view): badge "Hors Fankai" sur les épisodes de torrents manuels Les épisodes issus de MANUAL_TORRENTS (ex: MHA Film 4) sont maintenant marqués d'un badge violet "Hors Fankai" avec tooltip explicatif. - Propager manual: true du torrent dans le TorrentRef de l'épisode - Afficher le badge dans SerieView.vue si ep.torrent?.manual feat(series-view): tooltip avec le nom du torrent sur les boutons intégrale Quand plusieurs intégrales existent pour une série, survoler le bouton affiche le raw name du torrent via :title="t.raw". feat(scraper): extraction du nom bencode pour les torrents locaux Le champ raw des LOCAL_TORRENTS est maintenant renseigné depuis info.name extrait directement du fichier .torrent via bencode, au lieu d'utiliser la clé du dictionnaire LOCAL_TORRENTS. - fetch_torrent_files_from_local retourne maintenant (files, infohash, name) - torrent["raw"] est mis à jour avec le vrai nom bencode --- server/index.ts | 44 +++++++++++++++++++++----------- src/views/SerieView.vue | 56 +++++++++++++++++++++++------------------ 2 files changed, 61 insertions(+), 39 deletions(-) diff --git a/server/index.ts b/server/index.ts index 0ca2a4c..dec5ebd 100644 --- a/server/index.ts +++ b/server/index.ts @@ -142,22 +142,28 @@ function computeSerieDownloadState( const hasActive = serieTorrents.some(t => activeTorrents.has(t.infohash?.toLowerCase())) if (hasActive) return 'downloading' - let totalFiles = 0 - let doneFiles = 0 + // Collecter tous les épisodes uniques de la série (par episode_id) + const allEpisodeIds = new Set() + const organizedEpisodeIds = new Set() + for (const t of serieTorrents) { + const hash = t.infohash?.toLowerCase() + const orgFiles = organized[hash] ?? {} const files: any[] = t.torrent_files ?? [] - if (files.length === 0) { - totalFiles++ - if (organized[t.infohash?.toLowerCase()]?.[t.raw]) doneFiles++ - } else { - totalFiles += files.length - doneFiles += files.filter((f: any) => organized[t.infohash?.toLowerCase()]?.[f.filename]).length + + for (const ep of t.resolved_episodes ?? []) { + allEpisodeIds.add(ep.episode_id) + // Cherche le fichier correspondant à cet épisode dans torrent_files + const epFile = files.find((f: any) => f.filename === ep.filename) + if (epFile ? orgFiles[epFile.filename] : Object.keys(orgFiles).length > 0) { + organizedEpisodeIds.add(ep.episode_id) + } } } - if (totalFiles === 0) return 'none' - if (doneFiles === 0) return 'none' - if (doneFiles >= totalFiles) return 'complete' + if (allEpisodeIds.size === 0) return 'none' + if (organizedEpisodeIds.size === 0) return 'none' + if (organizedEpisodeIds.size >= allEpisodeIds.size) return 'complete' return 'partial' } @@ -242,12 +248,13 @@ app.get('/api/series/:id', requireAuth, async (req, res) => { const availableBySnEn = new Set() // "sn:en" const episodeTorrentMap: Record = {} const episodeTorrentMapBySnEn: Record = {} - const seasonTorrentMap : Record = {} + const seasonTorrentMap : Record = {} // keyed by season_id (scraper) + const seasonTorrentMapBySn: Record = {} // keyed by season_number (fallback) const integraleTorrents: any[] = [] const packEpisodesTorrents: any[] = [] for (const t of torrents) { - const ref = { torrent_url: t.torrent_url, magnet: t.magnet, type: t.type, raw: t.raw } + const ref = { torrent_url: t.torrent_url, magnet: t.magnet, type: t.type, raw: t.raw, manual: t.manual ?? false } for (const ep of t.resolved_episodes ?? []) { availableEpisodeIds.add(ep.episode_id) const snEnKey = `${ep.season_number}:${ep.episode_number}` @@ -264,6 +271,8 @@ app.get('/api/series/:id', requireAuth, async (req, res) => { } else { const sids = rs.length > 0 ? rs.map((r: any) => r.season_id) : [t.season_id] for (const sid of sids) { if (sid) seasonTorrentMap[sid] = ref } + const sns = rs.length > 0 ? rs.map((r: any) => r.season_number) : [t.season_number] + for (const sn of sns) { if (sn != null) seasonTorrentMapBySn[sn] = ref } } } else if (t.type === 'pack_integrale') { integraleTorrents.push(t) @@ -272,6 +281,13 @@ app.get('/api/series/:id', requireAuth, async (req, res) => { } } + // ── DEBUG ────────────────────────────────────────────── + console.log(`[debug /api/series/${id}] serie="${serie.title}" allSeasonIds=`, [...allSeasonIds]) + console.log(`[debug /api/series/${id}] seasonTorrentMap=`, seasonTorrentMap) + console.log(`[debug /api/series/${id}] seasons from API:`, seasonsWithEpisodes.map((s: any) => ({ id: s.id, season_number: s.season_number, title: s.title }))) + console.log(`[debug /api/series/${id}] torrents matched:`, torrents.map(t => ({ raw: t.raw, type: t.type, season_id: t.season_id, resolved_seasons: t.resolved_seasons }))) + // ── END DEBUG ────────────────────────────────────────── + let promotedIntegrale: any = null if (integraleTorrents.length === 0 && allSeasonIds.size > 0) { for (const t of torrents.filter(t => t.type === 'pack_saison')) { @@ -349,7 +365,7 @@ app.get('/api/series/:id', requireAuth, async (req, res) => { orgCount >= total && total > 0 ? 'complete' : 'partial' return { ...season, - torrent : seasonTorrentMap[season.id] ?? null, + torrent : seasonTorrentMap[season.id] ?? seasonTorrentMapBySn[season.season_number] ?? null, organized_state : seasonOrganizedState, organized_count : orgCount, episodes : eps, diff --git a/src/views/SerieView.vue b/src/views/SerieView.vue index d7751e3..90a257f 100644 --- a/src/views/SerieView.vue +++ b/src/views/SerieView.vue @@ -27,7 +27,8 @@
- +
@@ -64,6 +65,7 @@