kaizoku-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +0 -0
- package/README.md +105 -0
- package/dist/extractors/kwik.d.ts +6 -0
- package/dist/extractors/kwik.js +33 -0
- package/dist/extractors/megaplay.d.ts +2 -0
- package/dist/extractors/megaplay.js +32 -0
- package/dist/extractors/streamwish.d.ts +4 -0
- package/dist/extractors/streamwish.js +86 -0
- package/dist/extractors/vidtube.d.ts +2 -0
- package/dist/extractors/vidtube.js +24 -0
- package/dist/extractors/vidwish.d.ts +2 -0
- package/dist/extractors/vidwish.js +32 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +18 -0
- package/dist/lib/config.d.ts +22 -0
- package/dist/lib/config.js +21 -0
- package/dist/providers/anime/anidb.d.ts +6 -0
- package/dist/providers/anime/anidb.js +88 -0
- package/dist/providers/anime/anikoto.d.ts +41 -0
- package/dist/providers/anime/anikoto.js +259 -0
- package/dist/providers/anime/animegg.d.ts +6 -0
- package/dist/providers/anime/animegg.js +107 -0
- package/dist/providers/anime/animeonsen.d.ts +6 -0
- package/dist/providers/anime/animeonsen.js +95 -0
- package/dist/providers/anime/animepahe.d.ts +6 -0
- package/dist/providers/anime/animepahe.js +102 -0
- package/dist/providers/anime/animesaturn.d.ts +8 -0
- package/dist/providers/anime/animesaturn.js +160 -0
- package/dist/providers/anime/animeunity.d.ts +4 -0
- package/dist/providers/anime/animeunity.js +108 -0
- package/dist/providers/anime/anizone.d.ts +12 -0
- package/dist/providers/anime/anizone.js +146 -0
- package/dist/providers/anime/gojo.d.ts +6 -0
- package/dist/providers/anime/gojo.js +83 -0
- package/dist/providers/meta/anilist/anilist.d.ts +28 -0
- package/dist/providers/meta/anilist/anilist.js +263 -0
- package/dist/providers/meta/anilist/queries.d.ts +22 -0
- package/dist/providers/meta/anilist/queries.js +405 -0
- package/dist/providers/meta/anilist/types.d.ts +213 -0
- package/dist/providers/meta/anilist/types.js +21 -0
- package/dist/providers/meta/anilist.d.ts +15 -0
- package/dist/providers/meta/anilist.js +94 -0
- package/dist/types/types.d.ts +88 -0
- package/dist/types/types.js +4 -0
- package/dist/utils/http.d.ts +13 -0
- package/dist/utils/http.js +39 -0
- package/dist/utils/proxy.d.ts +9 -0
- package/dist/utils/proxy.js +43 -0
- package/dist/utils/shared.d.ts +15 -0
- package/dist/utils/shared.js +64 -0
- package/dist/utils/unpack.d.ts +9 -0
- package/dist/utils/unpack.js +59 -0
- package/package.json +34 -0
- package/vitest.config.ts +7 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
// ─── Shared Field Fragments ─────────────────────────────────────
|
|
2
|
+
// AniList doesn't support native GraphQL fragments via its endpoint
|
|
3
|
+
// so we use template strings to keep things DRY.
|
|
4
|
+
/** Fields selected for cards, carousels, and list items */
|
|
5
|
+
export const MEDIA_CARD_FIELDS = `
|
|
6
|
+
id
|
|
7
|
+
idMal
|
|
8
|
+
title {
|
|
9
|
+
romaji
|
|
10
|
+
english
|
|
11
|
+
native
|
|
12
|
+
userPreferred
|
|
13
|
+
}
|
|
14
|
+
coverImage {
|
|
15
|
+
extraLarge
|
|
16
|
+
large
|
|
17
|
+
medium
|
|
18
|
+
color
|
|
19
|
+
}
|
|
20
|
+
bannerImage
|
|
21
|
+
format
|
|
22
|
+
type
|
|
23
|
+
status
|
|
24
|
+
episodes
|
|
25
|
+
duration
|
|
26
|
+
season
|
|
27
|
+
seasonYear
|
|
28
|
+
averageScore
|
|
29
|
+
meanScore
|
|
30
|
+
popularity
|
|
31
|
+
favourites
|
|
32
|
+
trending
|
|
33
|
+
genres
|
|
34
|
+
description(asHtml: false)
|
|
35
|
+
trailer {
|
|
36
|
+
id
|
|
37
|
+
site
|
|
38
|
+
thumbnail
|
|
39
|
+
}
|
|
40
|
+
startDate {
|
|
41
|
+
year
|
|
42
|
+
month
|
|
43
|
+
day
|
|
44
|
+
}
|
|
45
|
+
endDate {
|
|
46
|
+
year
|
|
47
|
+
month
|
|
48
|
+
day
|
|
49
|
+
}
|
|
50
|
+
source
|
|
51
|
+
countryOfOrigin
|
|
52
|
+
isAdult
|
|
53
|
+
studios(isMain: true) {
|
|
54
|
+
nodes {
|
|
55
|
+
id
|
|
56
|
+
name
|
|
57
|
+
isAnimationStudio
|
|
58
|
+
siteUrl
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
nextAiringEpisode {
|
|
62
|
+
id
|
|
63
|
+
airingAt
|
|
64
|
+
timeUntilAiring
|
|
65
|
+
episode
|
|
66
|
+
}
|
|
67
|
+
`;
|
|
68
|
+
/** Extra fields only needed on the detail page */
|
|
69
|
+
const MEDIA_DETAIL_EXTRA = `
|
|
70
|
+
synonyms
|
|
71
|
+
hashtag
|
|
72
|
+
siteUrl
|
|
73
|
+
characters(sort: [ROLE, RELEVANCE, ID], perPage: 25) {
|
|
74
|
+
edges {
|
|
75
|
+
id
|
|
76
|
+
role
|
|
77
|
+
node {
|
|
78
|
+
id
|
|
79
|
+
name {
|
|
80
|
+
full
|
|
81
|
+
native
|
|
82
|
+
first
|
|
83
|
+
last
|
|
84
|
+
}
|
|
85
|
+
image {
|
|
86
|
+
large
|
|
87
|
+
medium
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
voiceActors(language: JAPANESE) {
|
|
91
|
+
id
|
|
92
|
+
name {
|
|
93
|
+
full
|
|
94
|
+
native
|
|
95
|
+
first
|
|
96
|
+
last
|
|
97
|
+
}
|
|
98
|
+
image {
|
|
99
|
+
large
|
|
100
|
+
medium
|
|
101
|
+
}
|
|
102
|
+
languageV2
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
staff(sort: RELEVANCE, perPage: 25) {
|
|
107
|
+
edges {
|
|
108
|
+
id
|
|
109
|
+
role
|
|
110
|
+
node {
|
|
111
|
+
id
|
|
112
|
+
name {
|
|
113
|
+
full
|
|
114
|
+
native
|
|
115
|
+
}
|
|
116
|
+
image {
|
|
117
|
+
large
|
|
118
|
+
medium
|
|
119
|
+
}
|
|
120
|
+
primaryOccupations
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
streamingEpisodes {
|
|
125
|
+
title
|
|
126
|
+
thumbnail
|
|
127
|
+
url
|
|
128
|
+
site
|
|
129
|
+
}
|
|
130
|
+
externalLinks {
|
|
131
|
+
id
|
|
132
|
+
url
|
|
133
|
+
site
|
|
134
|
+
type
|
|
135
|
+
icon
|
|
136
|
+
color
|
|
137
|
+
}
|
|
138
|
+
relations {
|
|
139
|
+
edges {
|
|
140
|
+
id
|
|
141
|
+
relationType(version: 2)
|
|
142
|
+
node {
|
|
143
|
+
${MEDIA_CARD_FIELDS}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
recommendations(sort: RATING_DESC, perPage: 10) {
|
|
148
|
+
nodes {
|
|
149
|
+
id
|
|
150
|
+
rating
|
|
151
|
+
mediaRecommendation {
|
|
152
|
+
${MEDIA_CARD_FIELDS}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
`;
|
|
157
|
+
// ─── Page Queries (lists) ───────────────────────────────────────
|
|
158
|
+
/** Trending right now — sorted by trending score descending */
|
|
159
|
+
export const TRENDING_QUERY = `
|
|
160
|
+
query TrendingAnime($page: Int, $perPage: Int) {
|
|
161
|
+
Page(page: $page, perPage: $perPage) {
|
|
162
|
+
pageInfo {
|
|
163
|
+
total
|
|
164
|
+
currentPage
|
|
165
|
+
lastPage
|
|
166
|
+
hasNextPage
|
|
167
|
+
perPage
|
|
168
|
+
}
|
|
169
|
+
media(sort: TRENDING_DESC, type: ANIME, isAdult: false) {
|
|
170
|
+
${MEDIA_CARD_FIELDS}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
`;
|
|
175
|
+
/** Popular this season */
|
|
176
|
+
export const POPULAR_THIS_SEASON_QUERY = `
|
|
177
|
+
query PopularThisSeason($page: Int, $perPage: Int, $season: MediaSeason, $seasonYear: Int) {
|
|
178
|
+
Page(page: $page, perPage: $perPage) {
|
|
179
|
+
pageInfo {
|
|
180
|
+
total
|
|
181
|
+
currentPage
|
|
182
|
+
lastPage
|
|
183
|
+
hasNextPage
|
|
184
|
+
perPage
|
|
185
|
+
}
|
|
186
|
+
media(
|
|
187
|
+
sort: POPULARITY_DESC
|
|
188
|
+
type: ANIME
|
|
189
|
+
season: $season
|
|
190
|
+
seasonYear: $seasonYear
|
|
191
|
+
isAdult: false
|
|
192
|
+
) {
|
|
193
|
+
${MEDIA_CARD_FIELDS}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
`;
|
|
198
|
+
/** Top upcoming — next season, sorted by popularity */
|
|
199
|
+
export const UPCOMING_QUERY = `
|
|
200
|
+
query UpcomingAnime($page: Int, $perPage: Int, $season: MediaSeason, $seasonYear: Int) {
|
|
201
|
+
Page(page: $page, perPage: $perPage) {
|
|
202
|
+
pageInfo {
|
|
203
|
+
total
|
|
204
|
+
currentPage
|
|
205
|
+
lastPage
|
|
206
|
+
hasNextPage
|
|
207
|
+
perPage
|
|
208
|
+
}
|
|
209
|
+
media(
|
|
210
|
+
sort: POPULARITY_DESC
|
|
211
|
+
type: ANIME
|
|
212
|
+
season: $season
|
|
213
|
+
seasonYear: $seasonYear
|
|
214
|
+
status: NOT_YET_RELEASED
|
|
215
|
+
isAdult: false
|
|
216
|
+
) {
|
|
217
|
+
${MEDIA_CARD_FIELDS}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
`;
|
|
222
|
+
/** All-time most popular */
|
|
223
|
+
export const ALL_TIME_POPULAR_QUERY = `
|
|
224
|
+
query AllTimePopular($page: Int, $perPage: Int) {
|
|
225
|
+
Page(page: $page, perPage: $perPage) {
|
|
226
|
+
pageInfo {
|
|
227
|
+
total
|
|
228
|
+
currentPage
|
|
229
|
+
lastPage
|
|
230
|
+
hasNextPage
|
|
231
|
+
perPage
|
|
232
|
+
}
|
|
233
|
+
media(sort: POPULARITY_DESC, type: ANIME, isAdult: false) {
|
|
234
|
+
${MEDIA_CARD_FIELDS}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
`;
|
|
239
|
+
/** All-time most favorited */
|
|
240
|
+
export const ALL_TIME_FAVORITE_QUERY = `
|
|
241
|
+
query AllTimeFavorite($page: Int, $perPage: Int) {
|
|
242
|
+
Page(page: $page, perPage: $perPage) {
|
|
243
|
+
pageInfo {
|
|
244
|
+
total
|
|
245
|
+
currentPage
|
|
246
|
+
lastPage
|
|
247
|
+
hasNextPage
|
|
248
|
+
perPage
|
|
249
|
+
}
|
|
250
|
+
media(sort: FAVOURITES_DESC, type: ANIME, isAdult: false) {
|
|
251
|
+
${MEDIA_CARD_FIELDS}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
`;
|
|
256
|
+
/** Top rated of all time */
|
|
257
|
+
export const TOP_RATED_QUERY = `
|
|
258
|
+
query TopRated($page: Int, $perPage: Int) {
|
|
259
|
+
Page(page: $page, perPage: $perPage) {
|
|
260
|
+
pageInfo {
|
|
261
|
+
total
|
|
262
|
+
currentPage
|
|
263
|
+
lastPage
|
|
264
|
+
hasNextPage
|
|
265
|
+
perPage
|
|
266
|
+
}
|
|
267
|
+
media(sort: SCORE_DESC, type: ANIME, isAdult: false) {
|
|
268
|
+
${MEDIA_CARD_FIELDS}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
`;
|
|
273
|
+
/** Currently airing — releasing right now */
|
|
274
|
+
export const CURRENTLY_AIRING_QUERY = `
|
|
275
|
+
query CurrentlyAiring($page: Int, $perPage: Int) {
|
|
276
|
+
Page(page: $page, perPage: $perPage) {
|
|
277
|
+
pageInfo {
|
|
278
|
+
total
|
|
279
|
+
currentPage
|
|
280
|
+
lastPage
|
|
281
|
+
hasNextPage
|
|
282
|
+
perPage
|
|
283
|
+
}
|
|
284
|
+
media(sort: POPULARITY_DESC, type: ANIME, status: RELEASING, isAdult: false) {
|
|
285
|
+
${MEDIA_CARD_FIELDS}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
`;
|
|
290
|
+
// ─── Search Query ───────────────────────────────────────────────
|
|
291
|
+
export const SEARCH_QUERY = `
|
|
292
|
+
query SearchAnime(
|
|
293
|
+
$page: Int
|
|
294
|
+
$perPage: Int
|
|
295
|
+
$search: String
|
|
296
|
+
$sort: [MediaSort]
|
|
297
|
+
$genre_in: [String]
|
|
298
|
+
$tag_in: [String]
|
|
299
|
+
$season: MediaSeason
|
|
300
|
+
$seasonYear: Int
|
|
301
|
+
$format: MediaFormat
|
|
302
|
+
$status: MediaStatus
|
|
303
|
+
$countryOfOrigin: CountryCode
|
|
304
|
+
$source: MediaSource
|
|
305
|
+
) {
|
|
306
|
+
Page(page: $page, perPage: $perPage) {
|
|
307
|
+
pageInfo {
|
|
308
|
+
total
|
|
309
|
+
currentPage
|
|
310
|
+
lastPage
|
|
311
|
+
hasNextPage
|
|
312
|
+
perPage
|
|
313
|
+
}
|
|
314
|
+
media(
|
|
315
|
+
search: $search
|
|
316
|
+
sort: $sort
|
|
317
|
+
type: ANIME
|
|
318
|
+
genre_in: $genre_in
|
|
319
|
+
tag_in: $tag_in
|
|
320
|
+
season: $season
|
|
321
|
+
seasonYear: $seasonYear
|
|
322
|
+
format: $format
|
|
323
|
+
status: $status
|
|
324
|
+
countryOfOrigin: $countryOfOrigin
|
|
325
|
+
source: $source
|
|
326
|
+
isAdult: false
|
|
327
|
+
) {
|
|
328
|
+
${MEDIA_CARD_FIELDS}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
`;
|
|
333
|
+
// ─── Detail Query (single anime) ───────────────────────────────
|
|
334
|
+
export const MEDIA_DETAIL_QUERY = `
|
|
335
|
+
query MediaDetail($id: Int) {
|
|
336
|
+
Media(id: $id, type: ANIME) {
|
|
337
|
+
${MEDIA_CARD_FIELDS}
|
|
338
|
+
${MEDIA_DETAIL_EXTRA}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
`;
|
|
342
|
+
// ─── Hero / Featured Query ──────────────────────────────────────
|
|
343
|
+
// Specifically for the hero carousel — we want trending anime
|
|
344
|
+
// that have trailers and banner images for a cinematic look.
|
|
345
|
+
export const HERO_QUERY = `
|
|
346
|
+
query HeroAnime($page: Int, $perPage: Int) {
|
|
347
|
+
Page(page: $page, perPage: $perPage) {
|
|
348
|
+
pageInfo {
|
|
349
|
+
total
|
|
350
|
+
currentPage
|
|
351
|
+
lastPage
|
|
352
|
+
hasNextPage
|
|
353
|
+
perPage
|
|
354
|
+
}
|
|
355
|
+
media(sort: TRENDING_DESC, type: ANIME, isAdult: false) {
|
|
356
|
+
${MEDIA_CARD_FIELDS}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
`;
|
|
361
|
+
// ─── Genre Collection Query ─────────────────────────────────────
|
|
362
|
+
export const GENRE_COLLECTION_QUERY = `
|
|
363
|
+
query GenreCollection {
|
|
364
|
+
GenreCollection
|
|
365
|
+
}
|
|
366
|
+
`;
|
|
367
|
+
export const TAG_COLLECTION_QUERY = `
|
|
368
|
+
query TagCollection {
|
|
369
|
+
MediaTagCollection {
|
|
370
|
+
name
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
`;
|
|
374
|
+
export const SETTINGS_ASSETS_QUERY = `
|
|
375
|
+
query SettingsAssets {
|
|
376
|
+
banners: Page(perPage: 20) {
|
|
377
|
+
media(sort: POPULARITY_DESC, type: ANIME, isAdult: false) {
|
|
378
|
+
id
|
|
379
|
+
bannerImage
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
avatars: Page(perPage: 10) {
|
|
383
|
+
media(sort: POPULARITY_DESC, type: ANIME, isAdult: false) {
|
|
384
|
+
id
|
|
385
|
+
title {
|
|
386
|
+
romaji
|
|
387
|
+
english
|
|
388
|
+
}
|
|
389
|
+
characters(sort: FAVOURITES_DESC, perPage: 5) {
|
|
390
|
+
edges {
|
|
391
|
+
node {
|
|
392
|
+
id
|
|
393
|
+
name {
|
|
394
|
+
full
|
|
395
|
+
}
|
|
396
|
+
image {
|
|
397
|
+
large
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
`;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
export type MediaType = "ANIME" | "MANGA";
|
|
2
|
+
export type MediaFormat = "TV" | "TV_SHORT" | "MOVIE" | "SPECIAL" | "OVA" | "ONA" | "MUSIC";
|
|
3
|
+
export type MediaStatus = "FINISHED" | "RELEASING" | "NOT_YET_RELEASED" | "CANCELLED" | "HIATUS";
|
|
4
|
+
export type MediaSeason = "WINTER" | "SPRING" | "SUMMER" | "FALL";
|
|
5
|
+
export type MediaSource = "ORIGINAL" | "MANGA" | "LIGHT_NOVEL" | "VISUAL_NOVEL" | "VIDEO_GAME" | "OTHER" | "NOVEL" | "DOUJINSHI" | "ANIME" | "WEB_NOVEL" | "LIVE_ACTION" | "GAME" | "COMIC" | "MULTIMEDIA_PROJECT" | "PICTURE_BOOK";
|
|
6
|
+
export type MediaRelation = "ADAPTATION" | "PREQUEL" | "SEQUEL" | "PARENT" | "SIDE_STORY" | "CHARACTER" | "SUMMARY" | "ALTERNATIVE" | "SPIN_OFF" | "OTHER" | "SOURCE" | "COMPILATION" | "CONTAINS";
|
|
7
|
+
export type CharacterRole = "MAIN" | "SUPPORTING" | "BACKGROUND";
|
|
8
|
+
export type MediaSort = "ID" | "TITLE_ROMAJI" | "TITLE_ENGLISH" | "TITLE_NATIVE" | "TYPE" | "FORMAT" | "START_DATE" | "END_DATE" | "SCORE" | "POPULARITY" | "TRENDING" | "EPISODES" | "DURATION" | "STATUS" | "FAVOURITES" | "ID_DESC" | "TITLE_ROMAJI_DESC" | "TITLE_ENGLISH_DESC" | "TITLE_NATIVE_DESC" | "TYPE_DESC" | "FORMAT_DESC" | "START_DATE_DESC" | "END_DATE_DESC" | "SCORE_DESC" | "POPULARITY_DESC" | "TRENDING_DESC" | "EPISODES_DESC" | "DURATION_DESC" | "STATUS_DESC" | "FAVOURITES_DESC";
|
|
9
|
+
export interface MediaTitle {
|
|
10
|
+
romaji: string | null;
|
|
11
|
+
english: string | null;
|
|
12
|
+
native: string | null;
|
|
13
|
+
userPreferred: string | null;
|
|
14
|
+
}
|
|
15
|
+
export interface MediaCoverImage {
|
|
16
|
+
extraLarge: string | null;
|
|
17
|
+
large: string | null;
|
|
18
|
+
medium: string | null;
|
|
19
|
+
color: string | null;
|
|
20
|
+
}
|
|
21
|
+
export interface FuzzyDate {
|
|
22
|
+
year: number | null;
|
|
23
|
+
month: number | null;
|
|
24
|
+
day: number | null;
|
|
25
|
+
}
|
|
26
|
+
export interface MediaTrailer {
|
|
27
|
+
/** Video ID on the platform (e.g. YouTube video ID) */
|
|
28
|
+
id: string | null;
|
|
29
|
+
/** Platform name — typically "youtube" or "dailymotion" */
|
|
30
|
+
site: string | null;
|
|
31
|
+
/** Thumbnail URL for the trailer */
|
|
32
|
+
thumbnail: string | null;
|
|
33
|
+
}
|
|
34
|
+
export interface Studio {
|
|
35
|
+
id: number;
|
|
36
|
+
name: string;
|
|
37
|
+
isAnimationStudio: boolean;
|
|
38
|
+
siteUrl: string | null;
|
|
39
|
+
}
|
|
40
|
+
export interface StudioConnection {
|
|
41
|
+
nodes: Studio[];
|
|
42
|
+
}
|
|
43
|
+
export interface CharacterName {
|
|
44
|
+
full: string | null;
|
|
45
|
+
native: string | null;
|
|
46
|
+
first: string | null;
|
|
47
|
+
last: string | null;
|
|
48
|
+
}
|
|
49
|
+
export interface CharacterImage {
|
|
50
|
+
large: string | null;
|
|
51
|
+
medium: string | null;
|
|
52
|
+
}
|
|
53
|
+
export interface Character {
|
|
54
|
+
id: number;
|
|
55
|
+
name: CharacterName;
|
|
56
|
+
image: CharacterImage;
|
|
57
|
+
}
|
|
58
|
+
export interface VoiceActor {
|
|
59
|
+
id: number;
|
|
60
|
+
name: CharacterName;
|
|
61
|
+
image: CharacterImage;
|
|
62
|
+
languageV2: string | null;
|
|
63
|
+
}
|
|
64
|
+
export interface CharacterEdge {
|
|
65
|
+
id: number;
|
|
66
|
+
role: CharacterRole;
|
|
67
|
+
node: Character;
|
|
68
|
+
voiceActors: VoiceActor[];
|
|
69
|
+
}
|
|
70
|
+
export interface CharacterConnection {
|
|
71
|
+
edges: CharacterEdge[];
|
|
72
|
+
}
|
|
73
|
+
export interface StaffName {
|
|
74
|
+
full: string | null;
|
|
75
|
+
native: string | null;
|
|
76
|
+
}
|
|
77
|
+
export interface StaffImage {
|
|
78
|
+
large: string | null;
|
|
79
|
+
medium: string | null;
|
|
80
|
+
}
|
|
81
|
+
export interface Staff {
|
|
82
|
+
id: number;
|
|
83
|
+
name: StaffName;
|
|
84
|
+
image: StaffImage;
|
|
85
|
+
primaryOccupations: string[];
|
|
86
|
+
}
|
|
87
|
+
export interface StaffEdge {
|
|
88
|
+
id: number;
|
|
89
|
+
role: string;
|
|
90
|
+
node: Staff;
|
|
91
|
+
}
|
|
92
|
+
export interface StaffConnection {
|
|
93
|
+
edges: StaffEdge[];
|
|
94
|
+
}
|
|
95
|
+
export interface StreamingEpisode {
|
|
96
|
+
title: string | null;
|
|
97
|
+
thumbnail: string | null;
|
|
98
|
+
url: string | null;
|
|
99
|
+
site: string | null;
|
|
100
|
+
}
|
|
101
|
+
export interface ExternalLink {
|
|
102
|
+
id: number;
|
|
103
|
+
url: string | null;
|
|
104
|
+
site: string;
|
|
105
|
+
type: string | null;
|
|
106
|
+
icon: string | null;
|
|
107
|
+
color: string | null;
|
|
108
|
+
}
|
|
109
|
+
export interface MediaRelationEdge {
|
|
110
|
+
id: number;
|
|
111
|
+
relationType: MediaRelation;
|
|
112
|
+
node: MediaBase;
|
|
113
|
+
}
|
|
114
|
+
export interface MediaRelationConnection {
|
|
115
|
+
edges: MediaRelationEdge[];
|
|
116
|
+
}
|
|
117
|
+
export interface RecommendationNode {
|
|
118
|
+
id: number;
|
|
119
|
+
rating: number;
|
|
120
|
+
mediaRecommendation: MediaBase | null;
|
|
121
|
+
}
|
|
122
|
+
export interface RecommendationConnection {
|
|
123
|
+
nodes: RecommendationNode[];
|
|
124
|
+
}
|
|
125
|
+
export interface AiringSchedule {
|
|
126
|
+
id: number;
|
|
127
|
+
airingAt: number;
|
|
128
|
+
timeUntilAiring: number;
|
|
129
|
+
episode: number;
|
|
130
|
+
}
|
|
131
|
+
export interface AiringScheduleConnection {
|
|
132
|
+
nodes: AiringSchedule[];
|
|
133
|
+
}
|
|
134
|
+
/** Lightweight media used in lists / cards / carousels */
|
|
135
|
+
export interface MediaBase {
|
|
136
|
+
id: number;
|
|
137
|
+
idMal: number | null;
|
|
138
|
+
title: MediaTitle;
|
|
139
|
+
coverImage: MediaCoverImage;
|
|
140
|
+
bannerImage: string | null;
|
|
141
|
+
format: MediaFormat | null;
|
|
142
|
+
type: MediaType | null;
|
|
143
|
+
status: MediaStatus | null;
|
|
144
|
+
episodes: number | null;
|
|
145
|
+
duration: number | null;
|
|
146
|
+
season: MediaSeason | null;
|
|
147
|
+
seasonYear: number | null;
|
|
148
|
+
averageScore: number | null;
|
|
149
|
+
meanScore: number | null;
|
|
150
|
+
popularity: number | null;
|
|
151
|
+
favourites: number | null;
|
|
152
|
+
trending: number | null;
|
|
153
|
+
genres: string[];
|
|
154
|
+
description: string | null;
|
|
155
|
+
trailer: MediaTrailer | null;
|
|
156
|
+
startDate: FuzzyDate | null;
|
|
157
|
+
endDate: FuzzyDate | null;
|
|
158
|
+
source: MediaSource | null;
|
|
159
|
+
countryOfOrigin: string | null;
|
|
160
|
+
isAdult: boolean;
|
|
161
|
+
studios: StudioConnection | null;
|
|
162
|
+
nextAiringEpisode: AiringSchedule | null;
|
|
163
|
+
}
|
|
164
|
+
/** Full media detail includes characters, staff, relations, etc. */
|
|
165
|
+
export interface MediaDetail extends MediaBase {
|
|
166
|
+
synonyms: string[];
|
|
167
|
+
hashtag: string | null;
|
|
168
|
+
siteUrl: string | null;
|
|
169
|
+
characters: CharacterConnection | null;
|
|
170
|
+
staff: StaffConnection | null;
|
|
171
|
+
streamingEpisodes: StreamingEpisode[];
|
|
172
|
+
externalLinks: ExternalLink[];
|
|
173
|
+
relations: MediaRelationConnection | null;
|
|
174
|
+
recommendations: RecommendationConnection | null;
|
|
175
|
+
}
|
|
176
|
+
export interface SearchFilters {
|
|
177
|
+
search?: string;
|
|
178
|
+
sort?: MediaSort[];
|
|
179
|
+
genres?: string[];
|
|
180
|
+
tags?: string[];
|
|
181
|
+
season?: MediaSeason;
|
|
182
|
+
seasonYear?: number;
|
|
183
|
+
format?: MediaFormat;
|
|
184
|
+
status?: MediaStatus;
|
|
185
|
+
countryOfOrigin?: string;
|
|
186
|
+
source?: MediaSource | string;
|
|
187
|
+
page?: number;
|
|
188
|
+
perPage?: number;
|
|
189
|
+
}
|
|
190
|
+
export interface PageInfo {
|
|
191
|
+
total: number | null;
|
|
192
|
+
currentPage: number | null;
|
|
193
|
+
lastPage: number | null;
|
|
194
|
+
hasNextPage: boolean;
|
|
195
|
+
perPage: number | null;
|
|
196
|
+
}
|
|
197
|
+
export interface PagedMedia {
|
|
198
|
+
pageInfo: PageInfo;
|
|
199
|
+
media: MediaBase[];
|
|
200
|
+
}
|
|
201
|
+
export interface PageResponse {
|
|
202
|
+
Page: PagedMedia;
|
|
203
|
+
}
|
|
204
|
+
export interface MediaResponse {
|
|
205
|
+
Media: MediaDetail;
|
|
206
|
+
}
|
|
207
|
+
/** Returns current anime season based on month */
|
|
208
|
+
export declare function getCurrentSeason(): MediaSeason;
|
|
209
|
+
/** Returns the next anime season and year */
|
|
210
|
+
export declare function getNextSeason(): {
|
|
211
|
+
season: MediaSeason;
|
|
212
|
+
year: number;
|
|
213
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Returns current anime season based on month */
|
|
2
|
+
export function getCurrentSeason() {
|
|
3
|
+
const month = new Date().getMonth() + 1; // 1-12
|
|
4
|
+
if (month >= 1 && month <= 3)
|
|
5
|
+
return "WINTER";
|
|
6
|
+
if (month >= 4 && month <= 6)
|
|
7
|
+
return "SPRING";
|
|
8
|
+
if (month >= 7 && month <= 9)
|
|
9
|
+
return "SUMMER";
|
|
10
|
+
return "FALL";
|
|
11
|
+
}
|
|
12
|
+
/** Returns the next anime season and year */
|
|
13
|
+
export function getNextSeason() {
|
|
14
|
+
const currentSeason = getCurrentSeason();
|
|
15
|
+
const currentYear = new Date().getFullYear();
|
|
16
|
+
const order = ["WINTER", "SPRING", "SUMMER", "FALL"];
|
|
17
|
+
const currentIndex = order.indexOf(currentSeason);
|
|
18
|
+
const nextIndex = (currentIndex + 1) % 4;
|
|
19
|
+
const nextYear = nextIndex === 0 ? currentYear + 1 : currentYear;
|
|
20
|
+
return { season: order[nextIndex], year: nextYear };
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AniZipData, Episode, EpisodeSources } from '../../types/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The available providers in the meta wrapper.
|
|
4
|
+
*/
|
|
5
|
+
export declare const PROVIDERS: Record<string, any>;
|
|
6
|
+
export declare function getAniZipData(anilistId: string | number): Promise<AniZipData | null>;
|
|
7
|
+
/**
|
|
8
|
+
* Tries to find the anime on a specific provider by searching its titles.
|
|
9
|
+
*/
|
|
10
|
+
export declare function mapToProvider(anilistId: string | number, providerName: string): Promise<string | null>;
|
|
11
|
+
/**
|
|
12
|
+
* Fetches episodes from a provider and enriches them with AniZip metadata (titles, images, filler).
|
|
13
|
+
*/
|
|
14
|
+
export declare function fetchEpisodes(anilistId: string | number, providerName: string): Promise<Episode[]>;
|
|
15
|
+
export declare function fetchEpisodeSources(episodeId: string, providerName: string, extraArgs?: any): Promise<EpisodeSources>;
|