diff --git a/packages/core/src/streams/fetcher.ts b/packages/core/src/streams/fetcher.ts index 62271411..db30dbfe 100644 --- a/packages/core/src/streams/fetcher.ts +++ b/packages/core/src/streams/fetcher.ts @@ -60,21 +60,25 @@ class StreamFetcher { const start = Date.now(); let queryType = type; if (AnimeDatabase.getInstance().isAnime(id)) { - queryType = 'anime'; + queryType = `anime.${type}`; } addons = addons.filter((addon) => { if ( addon.mediaTypes && addon.mediaTypes.length > 0 && - ['movie', 'series', 'anime'].includes(queryType) + ['movie', 'series', 'anime.series', 'anime.movie'].includes(queryType) ) { + let mappedType = queryType; + if (queryType === 'anime.series' || queryType === 'anime.movie') { + mappedType = 'anime'; + } const result = addon.mediaTypes.includes( - queryType as 'movie' | 'series' | 'anime' + mappedType as 'movie' | 'series' | 'anime' ); if (!result) { logger.debug( - `Skipping ${getAddonName(addon)} because its specified media types do not include ${queryType}` + `Skipping ${getAddonName(addon)} because its specified media types do not include ${mappedType}` ); } return result; diff --git a/packages/core/src/streams/filterer.ts b/packages/core/src/streams/filterer.ts index b90303b9..f2c09d2d 100644 --- a/packages/core/src/streams/filterer.ts +++ b/packages/core/src/streams/filterer.ts @@ -1566,7 +1566,7 @@ class StreamFilterer { let queryType = type; if (AnimeDatabase.getInstance().isAnime(id)) { - queryType = 'anime'; + queryType = `anime.${queryType}`; } const selector = new StreamSelector(queryType); const streamsToKeep = new Set(); @@ -1596,7 +1596,7 @@ class StreamFilterer { let queryType = type; if (AnimeDatabase.getInstance().isAnime(id)) { - queryType = 'anime'; + queryType = `anime.${queryType}`; } const passthroughStreams = streams diff --git a/packages/core/src/streams/precomputer.ts b/packages/core/src/streams/precomputer.ts index d0516854..cee5fc54 100644 --- a/packages/core/src/streams/precomputer.ts +++ b/packages/core/src/streams/precomputer.ts @@ -23,7 +23,7 @@ class StreamPrecomputer { public async precompute(streams: ParsedStream[], type: string, id: string) { let queryType = type; if (AnimeDatabase.getInstance().isAnime(id)) { - queryType = 'anime'; + queryType = `anime.${type}`; } const preferredRegexPatterns = (await FeatureControl.isRegexAllowed( diff --git a/packages/core/src/utils/config.ts b/packages/core/src/utils/config.ts index 2652d1de..ffbabff7 100644 --- a/packages/core/src/utils/config.ts +++ b/packages/core/src/utils/config.ts @@ -584,6 +584,60 @@ export function applyMigrations(config: any): UserData { migrateHOSBS('excluded'); migrateHOSBS('included'); + // migrate comparisons of queryType to 'anime' to 'anime.series' or 'anime.movie' + const migrateAnimeQueryTypeInExpression = (expr?: string) => { + if (typeof expr !== 'string') return expr as any; + // Replace equality comparisons + let updated = expr.replace( + /queryType\s*==\s*(["'])anime\1/g, + "(queryType == 'anime.series' or queryType == 'anime.movie')" + ); + updated = updated.replace( + /(["'])anime\1\s*==\s*queryType/g, + "(queryType == 'anime.series' or queryType == 'anime.movie')" + ); + // Replace inequality comparisons + updated = updated.replace( + /queryType\s*!=\s*(["'])anime\1/g, + "(queryType != 'anime.series' and queryType != 'anime.movie')" + ); + updated = updated.replace( + /(["'])anime\1\s*!=\s*queryType/g, + "(queryType != 'anime.series' and queryType != 'anime.movie')" + ); + return updated; + }; + + const expressionLists = [ + 'excludedStreamExpressions', + 'requiredStreamExpressions', + 'includedStreamExpressions', + 'preferredStreamExpressions', + ] as const; + + for (const key of expressionLists) { + if (Array.isArray((config as any)[key])) { + (config as any)[key] = (config as any)[key].map((expr: unknown) => + typeof expr === 'string' + ? migrateAnimeQueryTypeInExpression(expr) + : expr + ); + } + } + + if (config.dynamicAddonFetching?.condition) { + config.dynamicAddonFetching.condition = migrateAnimeQueryTypeInExpression( + config.dynamicAddonFetching.condition + ); + } + + if (config.groups?.groupings) { + config.groups.groupings = config.groups.groupings.map((group: any) => ({ + ...group, + condition: migrateAnimeQueryTypeInExpression(group.condition), + })); + } + return config; } diff --git a/packages/frontend/src/context/userData.tsx b/packages/frontend/src/context/userData.tsx index 392541dc..c79446e5 100644 --- a/packages/frontend/src/context/userData.tsx +++ b/packages/frontend/src/context/userData.tsx @@ -81,6 +81,58 @@ export function applyMigrations(config: any): UserData { migrateHOSBS('excluded'); migrateHOSBS('included'); + // migrate comparisons of queryType to 'anime' to 'anime.series' or 'anime.movie' + const migrateAnimeQueryTypeInExpression = (expr?: string) => { + if (typeof expr !== 'string') return expr as any; + let updated = expr.replace( + /queryType\s*==\s*(["'])anime\1/g, + "(queryType == 'anime.series' or queryType == 'anime.movie')" + ); + updated = updated.replace( + /(["'])anime\1\s*==\s*queryType/g, + "(queryType == 'anime.series' or queryType == 'anime.movie')" + ); + updated = updated.replace( + /queryType\s*!=\s*(["'])anime\1/g, + "(queryType != 'anime.series' and queryType != 'anime.movie')" + ); + updated = updated.replace( + /(["'])anime\1\s*!=\s*queryType/g, + "(queryType != 'anime.series' and queryType != 'anime.movie')" + ); + return updated; + }; + + const expressionLists = [ + 'excludedStreamExpressions', + 'requiredStreamExpressions', + 'includedStreamExpressions', + 'preferredStreamExpressions', + ] as const; + + for (const key of expressionLists) { + if (Array.isArray((config as any)[key])) { + (config as any)[key] = (config as any)[key].map((expr: unknown) => + typeof expr === 'string' + ? migrateAnimeQueryTypeInExpression(expr) + : expr + ); + } + } + + if (config.dynamicAddonFetching?.condition) { + config.dynamicAddonFetching.condition = migrateAnimeQueryTypeInExpression( + config.dynamicAddonFetching.condition + ); + } + + if (config.groups?.groupings) { + config.groups.groupings = config.groups.groupings.map((group: any) => ({ + ...group, + condition: migrateAnimeQueryTypeInExpression(group.condition), + })); + } + return config; } const DefaultUserData: UserData = {