feat(aniwatch): Improves title matching logic

- Enhances title matching accuracy when fetching Aniwatch IDs.
- Prioritizes user-preferred titles and falls back to English titles.
- Ensures only one fetch call is made per title if both english and userPreferred title are same.
- Adds a score threshold to filter low-quality matches.
- Fixes a bug where the episode list was not being returned.
This commit is contained in:
2025-04-23 09:32:52 -04:00
parent 00720565b4
commit b8ae211956
3 changed files with 96 additions and 21 deletions

View File

@@ -119,17 +119,43 @@ async function fetchEpisodes(
});
}
// function updateTitles(title: Partial<{ english: string; userPreferred: string }>) {
// const english = title.english?.toLowerCase();
// const userPreferred = title.userPreferred?.toLowerCase();
// if (english?.match(/my hero academia.+[0-9]$/)) {
// }
// }
function getAniwatchId(
animeTitle: Partial<{ english: string; userPreferred: string }>,
): Promise<string | undefined> {
return Promise.allSettled([
fetch(
`https://aniwatch.up.railway.app/api/v2/hianime/search?q=${encodeURIComponent(animeTitle.english!)}`,
),
fetch(
`https://aniwatch.up.railway.app/api/v2/hianime/search?q=${encodeURIComponent(animeTitle.userPreferred!)}`,
),
])
animeTitle = {
english: animeTitle?.english?.toLowerCase(),
userPreferred: animeTitle?.userPreferred?.toLowerCase(),
};
const promises = [];
if (animeTitle.userPreferred) {
promises.push(
fetch(
`https://aniwatch.up.railway.app/api/v2/hianime/search?q=${encodeURIComponent(
animeTitle.userPreferred,
)}`,
),
);
}
if (animeTitle.english && animeTitle.english !== animeTitle.userPreferred) {
promises.push(
fetch(
`https://aniwatch.up.railway.app/api/v2/hianime/search?q=${encodeURIComponent(
animeTitle.english,
)}`,
),
);
}
return Promise.allSettled(promises)
.then((responses) => {
return responses.reduce(
async (current, res) => {
@@ -164,16 +190,21 @@ function getAniwatchId(
return;
}
const bestMatchingTitle = findBestMatchingTitle(
const { title: bestMatchingTitle, score } = findBestMatchingTitle(
animeTitle,
animes.map((anime) => ({
english: anime.name,
userPreferred: anime.jname,
})),
);
if (score < 0.8) {
return;
}
return animes.find(
(anime) =>
anime.name === bestMatchingTitle || anime.jname === bestMatchingTitle,
anime.name?.toLowerCase() === bestMatchingTitle ||
anime.jname?.toLowerCase() === bestMatchingTitle,
)?.id;
});
}

View File

@@ -81,18 +81,23 @@ export function fetchEpisodes(
app.openapi(route, async (c) => {
const aniListId = Number(c.req.param("aniListId"));
const { result: episodes, errorOccurred } = await fetchEpisodes(
const { result, errorOccurred } = await fetchEpisodes(
aniListId,
env(c, "workerd"),
);
if (errorOccurred) {
if (errorOccurred || !result) {
return c.json(ErrorResponse, { status: 500 });
}
const { episodes, providerId } = result;
if (!episodes || episodes.length === 0) {
return c.json(ErrorResponse, { status: 404 });
}
return c.json({
success: true,
result: episodes ?? [],
result: { providerId, episodes },
});
});