diff --git a/common/modules/anilist.js b/common/modules/anilist.js index 62d20a1..e213c80 100644 --- a/common/modules/anilist.js +++ b/common/modules/anilist.js @@ -305,19 +305,19 @@ class AnilistClient { // isAdult doesn't need an extra variable, as the title is the same regardless of type, so we re-use the same variable for adult and non-adult requests /** @type {Record<`v${number}`, string>} */ const requestVariables = flattenedTitles.reduce((obj, { title, isAdult }, i) => { - if (isAdult) return obj + if (isAdult && i !== 0) return obj obj[`v${i}`] = title return obj }, {}) const queryVariables = flattenedTitles.reduce((arr, { isAdult }, i) => { - if (isAdult) return arr + if (isAdult && i !== 0) return arr arr.push(`$v${i}: String`) return arr }, []).join(', ') const fragmentQueries = flattenedTitles.map(({ year, isAdult }, i) => /* js */` v${i}: Page(perPage: 10) { - media(type: ANIME, search: $v${isAdult ? i - 1 : i}, status_in: [RELEASING, FINISHED], isAdult: ${!!isAdult} ${year ? `, seasonYear: ${year}` : ''}) { + media(type: ANIME, search: $v${(isAdult && i !== 0) ? i - 1 : i}, status_in: [RELEASING, FINISHED], isAdult: ${!!isAdult} ${year ? `, seasonYear: ${year}` : ''}) { ...med } }`) diff --git a/common/modules/animeresolver.js b/common/modules/animeresolver.js index 96c5c77..8b92bd5 100644 --- a/common/modules/animeresolver.js +++ b/common/modules/animeresolver.js @@ -25,7 +25,7 @@ export default new class AnimeResolver { * @returns {string[]} */ alternativeTitles (title) { - const titles = [] + const titles = new Set() let modified = title // preemptively change S2 into Season 2 or 2nd Season, otherwise this will have accuracy issues @@ -33,31 +33,31 @@ export default new class AnimeResolver { if (seasonMatch) { if (Number(seasonMatch[1]) === 1) { // if this is S1, remove the " S1" or " S01" modified = title.replace(/ S(\d+)/, '') - titles.push(modified) + titles.add(modified) } else { modified = title.replace(/ S(\d+)/, ` ${Number(seasonMatch[1])}${postfix[Number(seasonMatch[1])] || 'th'} Season`) - titles.push(modified) - titles.push(title.replace(/ S(\d+)/, ` Season ${Number(seasonMatch[1])}`)) + titles.add(modified) + titles.add(title.replace(/ S(\d+)/, ` Season ${Number(seasonMatch[1])}`)) } } else { - titles.push(title) + titles.add(title) } // remove - : const specialMatch = modified.match(/[-:]/g) if (specialMatch) { - modified = modified.replace(/[-:]/g, '') - titles.push(modified) + modified = modified.replace(/[-:]/g, '').replace(/[ ]{2,}/, ' ') + titles.add(modified) } // remove (TV) const tvMatch = modified.match(/\(TV\)/) if (tvMatch) { modified = modified.replace('(TV)', '') - titles.push(modified) + titles.add(modified) } - return titles + return [...titles] } /** @@ -73,8 +73,10 @@ export default new class AnimeResolver { return titleObjects }).flat() - for (const [key, media] of await anilistClient.alSearchCompound(titleObjects)) { - this.animeNameCache[key] = media + for (const chunk of chunks(titleObjects, 62)) { // single title has a complexity of 8.1, al limits complexity to 500 + for (const [key, media] of await anilistClient.alSearchCompound(chunk)) { + this.animeNameCache[key] = media + } } } @@ -97,16 +99,17 @@ export default new class AnimeResolver { if (!fileName) return [{}] const parseObjs = await anitomyscript(fileName) + const TYPE_EXCLUSIONS = ['ED', 'ENDING', 'NCED', 'NCOP', 'OP', 'OPENING', 'PREVIEW', 'PV'] + /** @type {Record} */ const uniq = {} for (const obj of parseObjs) { const key = this.getCacheKeyForTitle(obj) - if (key in this.animeNameCache) continue + if (key in this.animeNameCache) continue // skip already resolved + if (obj.anime_type && TYPE_EXCLUSIONS.includes(obj.anime_type.toUpperCase())) continue // skip non-episode media uniq[key] = obj } - for (const chunk of chunks(Object.values(uniq), 50)) { - await this.findAnimesByTitle(chunk) - } + await this.findAnimesByTitle(Object.values(uniq)) const fileAnimes = [] for (const parseObj of parseObjs) {