diff options
| author | Fuwn <[email protected]> | 2023-12-16 18:50:51 -0800 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2023-12-16 18:50:51 -0800 |
| commit | b018bd62213b1a72114ecf47c6676204e33bd429 (patch) | |
| tree | 8b8ece187917e99fc5591fe2f5fa271861e8b260 /src/lib/Media | |
| parent | feat(api): subsplease endpoint (diff) | |
| download | due.moe-b018bd62213b1a72114ecf47c6676204e33bd429.tar.xz due.moe-b018bd62213b1a72114ecf47c6676204e33bd429.zip | |
feat(anime): subtitle countdown
Diffstat (limited to 'src/lib/Media')
| -rw-r--r-- | src/lib/Media/anime.ts | 88 |
1 files changed, 86 insertions, 2 deletions
diff --git a/src/lib/Media/anime.ts b/src/lib/Media/anime.ts index 927da31b..b9227562 100644 --- a/src/lib/Media/anime.ts +++ b/src/lib/Media/anime.ts @@ -5,6 +5,14 @@ import lastPruneTimes from '../../stores/lastPruneTimes'; import type { AniListAuthorisation, UserIdentity } from '../AniList/identity'; import settings from '../../stores/settings'; import type { MediaPrequel } from '$lib/AniList/prequels'; +import type { SubsPlease } from '$lib/subsPlease'; +import levenshtein from 'fast-levenshtein'; + +interface Time { + title: string; + time: string; + day: string; +} export const cleanCache = (user: AniListAuthorisation, identity: UserIdentity) => mediaListCollection(user, identity, Type.Anime, get(anime), get(lastPruneTimes).anime, true); @@ -16,9 +24,85 @@ export const updateMedia = (id: number, progress: number | undefined, callback: export const totalEpisodes = (anime: Media) => anime.episodes === null ? '' : `<span style="opacity: 50%">/${anime.episodes}</span>`; -export const airingTime = (anime: Media, upcoming = false) => { +const secondsUntil = (targetTime: string, targetDay: string) => { + const now = new Date(); + const [targetHour, targetMinute] = targetTime.split(':').map(Number); + let dayDifference = + ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'].indexOf( + targetDay + ) - now.getDay(); + + if (dayDifference < 0) dayDifference += 7; + + const targetDate = new Date(now); + + targetDate.setDate(now.getDate() + dayDifference); + targetDate.setHours(targetHour, targetMinute, 0, 0); + + const secondsDifference = (Number(targetDate) - Number(now)) / 1000; + + return secondsDifference > 0 ? secondsDifference : secondsDifference + 7 * 24 * 60 * 60; +}; + +const normalizeTitle = (title: string) => + (title || '') + .toLowerCase() + .replace(/season \d+|s\d+/g, '') + .trim(); + +const findClosestMatch = (times: Time[], titles: string[]) => { + let closestMatch = null; + let smallestDistance = Infinity; + + titles.forEach((animeTitle) => { + const normalizedAnimeTitle = normalizeTitle(animeTitle); + + times.forEach((item) => { + const normalizedItemTitle = normalizeTitle(item.title); + const distance = levenshtein.get(normalizedAnimeTitle, normalizedItemTitle); + + if (distance < smallestDistance) { + smallestDistance = distance; + closestMatch = item; + } + }); + }); + + return closestMatch; +}; + +export const airingTime = (anime: Media, subsPlease: SubsPlease, upcoming = false) => { const airingAt = anime.nextAiringEpisode?.airingAt; - const untilAiring = airingAt ? Math.round((airingAt - Date.now() / 1000) * 100) / 100 : undefined; + let untilAiring; + + if (get(settings).displayNativeCountdown) { + untilAiring = airingAt ? Math.round((airingAt - Date.now() / 1000) * 100) / 100 : undefined; + } else { + const times: Time[] = []; + + for (const [key, value] of Object.entries(subsPlease.schedule)) { + const flattenedValue = Array.isArray(value) ? value.flat() : []; + + for (const time of flattenedValue) { + times.push({ + title: time.title, + time: time.time, + day: key + }); + } + } + + const time: Time | null = findClosestMatch(times, [ + anime.title.romaji, + anime.title.english, + ...anime.synonyms + ]); + + if (time) untilAiring = secondsUntil((time as Time).time, (time as Time).day); + else + untilAiring = airingAt ? Math.round((airingAt - Date.now() / 1000) * 100) / 100 : undefined; + } + let timeFrame; const time = new Date(airingAt ? airingAt * 1000 : 0).toLocaleTimeString([], { hour12: !settings.get().display24HourTime, |