1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
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;
};
|