The manga title to search for.
Optional
token: stringOptional authentication token.
Optional search service configuration.
Optional
abortSignal: AbortSignalOptional abort signal to cancel the search.
Optional
specificPage: numberA promise resolving to an array of MangaMatch objects.
export async function searchMangaByTitle(
title: string,
token?: string,
config: Partial<SearchServiceConfig> = {},
abortSignal?: AbortSignal,
specificPage?: number,
): Promise<MangaSearchResponse> {
const searchConfig = { ...DEFAULT_SEARCH_CONFIG, ...config };
const cacheKey = generateCacheKey(title);
// Handle cache operations
if (searchConfig.bypassCache && cacheKey) {
handleCacheBypass(title, cacheKey);
} else if (!searchConfig.bypassCache) {
const cachedResult = processCachedResults(title, cacheKey);
if (cachedResult) {
return cachedResult;
}
} else if (searchConfig.exactMatchingOnly) {
console.log(
`🔍 MANUAL SEARCH: Ensuring exact matching is correctly configured`,
);
searchConfig.exactMatchingOnly = true;
}
// Execute the search
const searchQuery = title;
await acquireRateLimit();
const { results, lastPageInfo } = await executeSearchLoop(
searchQuery,
searchConfig,
token,
abortSignal,
specificPage,
);
// Process and filter results
const rankedResults = processSearchResults(results, title, searchConfig);
let filteredResults = applyContentFiltering(
rankedResults,
title,
searchConfig,
);
filteredResults = handleNoResultsFallback(
filteredResults,
results,
searchConfig,
);
// Handle fallback sources only if no original AniList results were found
let finalResults = filteredResults;
let comickSourceMap = new Map<
number,
{ title: string; slug: string; comickId: string; foundViaComick: boolean }
>();
let mangaDexSourceMap = new Map<
number,
{
title: string;
slug: string;
mangaDexId: string;
foundViaMangaDex: boolean;
}
>();
// Only use fallback sources if no AniList results were found
if (filteredResults.length === 0) {
console.log(
`🎯 No AniList results found for "${title}", trying fallback sources...`,
);
// Try both fallback sources when enabled
const comickFallback = await executeComickFallback(
title,
token,
finalResults,
searchConfig,
);
const mangaDexFallback = await executeMangaDexFallback(
title,
token,
finalResults,
searchConfig,
);
// Merge results and handle duplicates
const mergedResults = mergeSourceResults(
finalResults,
comickFallback.results,
mangaDexFallback.results,
comickFallback.comickSourceMap,
mangaDexFallback.mangaDexSourceMap,
);
finalResults = mergedResults.mergedResults;
comickSourceMap = mergedResults.comickSourceMap;
mangaDexSourceMap = mergedResults.mangaDexSourceMap;
} else {
console.log(
`✅ Found ${filteredResults.length} AniList results for "${title}", skipping fallback sources`,
);
}
// Build and return final response
return buildFinalResponse(
finalResults,
title,
comickSourceMap,
mangaDexSourceMap,
lastPageInfo,
);
}
Search for manga by title with rate limiting and caching.