fix: batch resolving media

This commit is contained in:
ThaUnknown 2024-08-05 18:05:21 +02:00
parent c07ca0f56f
commit 5a6ea08db8
2 changed files with 21 additions and 18 deletions

View file

@ -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 // 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>} */ /** @type {Record<`v${number}`, string>} */
const requestVariables = flattenedTitles.reduce((obj, { title, isAdult }, i) => { const requestVariables = flattenedTitles.reduce((obj, { title, isAdult }, i) => {
if (isAdult) return obj if (isAdult && i !== 0) return obj
obj[`v${i}`] = title obj[`v${i}`] = title
return obj return obj
}, {}) }, {})
const queryVariables = flattenedTitles.reduce((arr, { isAdult }, i) => { const queryVariables = flattenedTitles.reduce((arr, { isAdult }, i) => {
if (isAdult) return arr if (isAdult && i !== 0) return arr
arr.push(`$v${i}: String`) arr.push(`$v${i}: String`)
return arr return arr
}, []).join(', ') }, []).join(', ')
const fragmentQueries = flattenedTitles.map(({ year, isAdult }, i) => /* js */` const fragmentQueries = flattenedTitles.map(({ year, isAdult }, i) => /* js */`
v${i}: Page(perPage: 10) { 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 ...med
} }
}`) }`)

View file

@ -25,7 +25,7 @@ export default new class AnimeResolver {
* @returns {string[]} * @returns {string[]}
*/ */
alternativeTitles (title) { alternativeTitles (title) {
const titles = [] const titles = new Set()
let modified = title let modified = title
// preemptively change S2 into Season 2 or 2nd Season, otherwise this will have accuracy issues // 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 (seasonMatch) {
if (Number(seasonMatch[1]) === 1) { // if this is S1, remove the " S1" or " S01" if (Number(seasonMatch[1]) === 1) { // if this is S1, remove the " S1" or " S01"
modified = title.replace(/ S(\d+)/, '') modified = title.replace(/ S(\d+)/, '')
titles.push(modified) titles.add(modified)
} else { } else {
modified = title.replace(/ S(\d+)/, ` ${Number(seasonMatch[1])}${postfix[Number(seasonMatch[1])] || 'th'} Season`) modified = title.replace(/ S(\d+)/, ` ${Number(seasonMatch[1])}${postfix[Number(seasonMatch[1])] || 'th'} Season`)
titles.push(modified) titles.add(modified)
titles.push(title.replace(/ S(\d+)/, ` Season ${Number(seasonMatch[1])}`)) titles.add(title.replace(/ S(\d+)/, ` Season ${Number(seasonMatch[1])}`))
} }
} else { } else {
titles.push(title) titles.add(title)
} }
// remove - : // remove - :
const specialMatch = modified.match(/[-:]/g) const specialMatch = modified.match(/[-:]/g)
if (specialMatch) { if (specialMatch) {
modified = modified.replace(/[-:]/g, '') modified = modified.replace(/[-:]/g, '').replace(/[ ]{2,}/, ' ')
titles.push(modified) titles.add(modified)
} }
// remove (TV) // remove (TV)
const tvMatch = modified.match(/\(TV\)/) const tvMatch = modified.match(/\(TV\)/)
if (tvMatch) { if (tvMatch) {
modified = modified.replace('(TV)', '') 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 return titleObjects
}).flat() }).flat()
for (const [key, media] of await anilistClient.alSearchCompound(titleObjects)) { for (const chunk of chunks(titleObjects, 62)) { // single title has a complexity of 8.1, al limits complexity to 500
this.animeNameCache[key] = media 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 [{}] if (!fileName) return [{}]
const parseObjs = await anitomyscript(fileName) const parseObjs = await anitomyscript(fileName)
const TYPE_EXCLUSIONS = ['ED', 'ENDING', 'NCED', 'NCOP', 'OP', 'OPENING', 'PREVIEW', 'PV']
/** @type {Record<string, import('anitomyscript').AnitomyResult>} */ /** @type {Record<string, import('anitomyscript').AnitomyResult>} */
const uniq = {} const uniq = {}
for (const obj of parseObjs) { for (const obj of parseObjs) {
const key = this.getCacheKeyForTitle(obj) 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 uniq[key] = obj
} }
for (const chunk of chunks(Object.values(uniq), 50)) { await this.findAnimesByTitle(Object.values(uniq))
await this.findAnimesByTitle(chunk)
}
const fileAnimes = [] const fileAnimes = []
for (const parseObj of parseObjs) { for (const parseObj of parseObjs) {