aboutsummaryrefslogtreecommitdiff
path: root/src/lib/Media/Anime/Airing/classify.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/Media/Anime/Airing/classify.ts')
-rw-r--r--src/lib/Media/Anime/Airing/classify.ts53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/lib/Media/Anime/Airing/classify.ts b/src/lib/Media/Anime/Airing/classify.ts
new file mode 100644
index 00000000..9b7487d2
--- /dev/null
+++ b/src/lib/Media/Anime/Airing/classify.ts
@@ -0,0 +1,53 @@
+import type { Media } from '$lib/Data/AniList/media';
+
+export interface AnimeEpisodeState {
+ progress: number;
+ nextEpisode: number;
+ airedEpisodes: number;
+}
+
+const hasAired = (airingAt: number | undefined, nowEpochSeconds: number) =>
+ typeof airingAt === 'number' && airingAt <= nowEpochSeconds;
+
+export const getAnimeEpisodeState = (
+ media: Media,
+ nowEpochSeconds = Date.now() / 1000
+): AnimeEpisodeState => {
+ const progress = media.mediaListEntry?.progress || 0;
+ const nextEpisode =
+ media.nextAiringEpisode?.nativeEpisode || media.nextAiringEpisode?.episode || 0;
+
+ if (nextEpisode <= 0) {
+ return {
+ progress,
+ nextEpisode,
+ airedEpisodes: 0
+ };
+ }
+
+ let airedEpisodes = Math.max(0, nextEpisode - 1);
+ const airingAt = media.nextAiringEpisode?.airingAt;
+ const nativeAiringAt = media.nextAiringEpisode?.nativeAiringAt;
+
+ // If either source says the "next" episode already aired, treat it as released.
+ if (hasAired(airingAt, nowEpochSeconds) || hasAired(nativeAiringAt, nowEpochSeconds))
+ airedEpisodes = Math.max(airedEpisodes, nextEpisode);
+
+ return {
+ progress,
+ nextEpisode,
+ airedEpisodes
+ };
+};
+
+export const hasDueEpisodes = (media: Media, nowEpochSeconds = Date.now() / 1000) => {
+ const episodeState = getAnimeEpisodeState(media, nowEpochSeconds);
+
+ return episodeState.airedEpisodes > episodeState.progress;
+};
+
+export const hasNoAiredEpisodes = (media: Media, nowEpochSeconds = Date.now() / 1000) => {
+ const episodeState = getAnimeEpisodeState(media, nowEpochSeconds);
+
+ return episodeState.airedEpisodes <= 0;
+};