@irfanshadikrishad/anilist 1.3.0-forbidden.1 → 1.3.1
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.md → LICENSE} +115 -124
- package/README.md +79 -53
- package/bin/helpers/auth.d.ts +13 -7
- package/bin/helpers/auth.js +282 -385
- package/bin/helpers/lists.d.ts +5 -1
- package/bin/helpers/lists.js +274 -126
- package/bin/helpers/mutations.d.ts +1 -2
- package/bin/helpers/mutations.js +1 -6
- package/bin/helpers/queries.d.ts +10 -9
- package/bin/helpers/queries.js +27 -30
- package/bin/helpers/types.d.ts +206 -36
- package/bin/helpers/validation.d.ts +29 -0
- package/bin/helpers/validation.js +117 -0
- package/bin/helpers/workers.d.ts +19 -10
- package/bin/helpers/workers.js +92 -28
- package/bin/index.js +30 -6
- package/package.json +20 -16
package/bin/helpers/queries.js
CHANGED
|
@@ -26,13 +26,13 @@ const userQuery = `query ($username: String) {
|
|
|
26
26
|
}`;
|
|
27
27
|
const currentUserAnimeList = `query ($id: Int) {
|
|
28
28
|
MediaListCollection(userId: $id, type: ANIME) {
|
|
29
|
-
lists { name entries { id progress hiddenFromStatusLists status media { id idMal title { romaji english } status episodes siteUrl } } }
|
|
29
|
+
lists { name entries { id progress hiddenFromStatusLists status media { id idMal title { romaji english native userPreferred } status episodes siteUrl format } } }
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
`;
|
|
33
33
|
const currentUserMangaList = `query ($id: Int) {
|
|
34
34
|
MediaListCollection(userId: $id, type: MANGA) {
|
|
35
|
-
lists { name entries { id progress hiddenFromStatusLists private status media { id idMal title { romaji english } status chapters } } }
|
|
35
|
+
lists { name entries { id progress hiddenFromStatusLists private status media { id idMal title { romaji english native userPreferred } status chapters } } }
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
`;
|
|
@@ -66,7 +66,7 @@ const userActivityQuery = `query ($id: Int, $page: Int, $perPage: Int) {
|
|
|
66
66
|
}`;
|
|
67
67
|
const animeSearchQuery = `query ($search: String, $perPage: Int) {
|
|
68
68
|
Page(perPage: $perPage) {
|
|
69
|
-
media(search: $search, type: ANIME) { id title { romaji english native userPreferred } episodes status description }
|
|
69
|
+
media(search: $search, type: ANIME) { id title { romaji english native userPreferred } startDate { day month year } episodes status description }
|
|
70
70
|
}
|
|
71
71
|
}`;
|
|
72
72
|
const mangaSearchQuery = `query ($search: String, $perPage: Int) {
|
|
@@ -120,42 +120,39 @@ const activityMediaList = `query ($userId: Int, $page: Int, $perPage: Int, $type
|
|
|
120
120
|
}
|
|
121
121
|
}`;
|
|
122
122
|
const malIdToAnilistAnimeId = `query ($malId: Int) {
|
|
123
|
-
Media(idMal: $malId, type: ANIME) {
|
|
123
|
+
Media(idMal: $malId, type: ANIME) {
|
|
124
|
+
id title { romaji english } }
|
|
125
|
+
}
|
|
124
126
|
`;
|
|
125
127
|
const malIdToAnilistMangaId = `query ($malId: Int) {
|
|
126
|
-
Media(idMal: $malId, type: MANGA) {
|
|
128
|
+
Media(idMal: $malId, type: MANGA) {
|
|
129
|
+
id title { romaji english } }
|
|
130
|
+
}
|
|
127
131
|
`;
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
... on TextActivity { id type isLiked createdAt user { id name } }
|
|
133
|
-
... on ListActivity { id type isLiked status progress media { title { userPreferred } } createdAt user { id name } }
|
|
134
|
-
... on MessageActivity { id type isLiked message createdAt recipient { id name } }
|
|
135
|
-
}
|
|
132
|
+
const userFollowingQuery = `query ($userId: Int!, $page: Int) {
|
|
133
|
+
Page (page: $page) {
|
|
134
|
+
pageInfo { total perPage currentPage lastPage hasNextPage }
|
|
135
|
+
following(userId: $userId, sort: [USERNAME]) { id name avatar { large medium } bannerImage isFollowing isFollower }
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
`;
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
... on TextActivity { id type isLiked createdAt user { id name } }
|
|
144
|
-
... on ListActivity { id type isLiked status progress media { title { userPreferred } } createdAt user { id name } }
|
|
145
|
-
... on MessageActivity { id type isLiked message createdAt recipient { id name } }
|
|
146
|
-
}
|
|
139
|
+
const userFollowersQuery = `query ($userId: Int!, $page: Int) {
|
|
140
|
+
Page (page: $page) {
|
|
141
|
+
pageInfo { total perPage currentPage lastPage hasNextPage }
|
|
142
|
+
followers(userId: $userId, sort: [USERNAME]) { id name avatar { large medium } bannerImage isFollowing isFollower }
|
|
147
143
|
}
|
|
148
144
|
}
|
|
149
145
|
`;
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
146
|
+
const toggleFollowMutation = `mutation ($userId: Int!) {
|
|
147
|
+
ToggleFollow(userId: $userId) { id name isFollower isFollowing }
|
|
148
|
+
}
|
|
149
|
+
`;
|
|
150
|
+
const mangaDetailsQuery = `query ($id: Int) {
|
|
151
|
+
Media(id: $id, type: MANGA) {
|
|
152
|
+
id title { romaji english native userPreferred } coverImage { color medium large extraLarge }
|
|
153
|
+
bannerImage description chapters volumes status genres
|
|
154
|
+
startDate { year month day } endDate { year month day }
|
|
158
155
|
}
|
|
159
156
|
}
|
|
160
157
|
`;
|
|
161
|
-
export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation,
|
|
158
|
+
export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaDetailsQuery, mangaSearchQuery, popularQuery, toggleFollowMutation, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, };
|
package/bin/helpers/types.d.ts
CHANGED
|
@@ -45,10 +45,7 @@ interface MalIdToAnilistIdResponse {
|
|
|
45
45
|
data?: {
|
|
46
46
|
Media: {
|
|
47
47
|
id: number;
|
|
48
|
-
title:
|
|
49
|
-
english?: string;
|
|
50
|
-
romaji?: string;
|
|
51
|
-
};
|
|
48
|
+
title: MediaTitle;
|
|
52
49
|
};
|
|
53
50
|
};
|
|
54
51
|
errors?: {
|
|
@@ -92,15 +89,13 @@ interface AnimeList {
|
|
|
92
89
|
}[];
|
|
93
90
|
}
|
|
94
91
|
interface MediaWithProgress {
|
|
95
|
-
malId
|
|
92
|
+
malId?: number;
|
|
96
93
|
progress: number;
|
|
97
94
|
status: string;
|
|
98
95
|
episodes?: number;
|
|
99
96
|
chapters?: number;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
romaji?: string;
|
|
103
|
-
};
|
|
97
|
+
format?: string;
|
|
98
|
+
title: MediaTitle;
|
|
104
99
|
}
|
|
105
100
|
interface MediaTitle {
|
|
106
101
|
english?: string;
|
|
@@ -121,16 +116,36 @@ interface MediaEntry {
|
|
|
121
116
|
status: string;
|
|
122
117
|
hiddenFromStatusLists: boolean;
|
|
123
118
|
}
|
|
119
|
+
interface SaveTextActivityResponse {
|
|
120
|
+
data?: {
|
|
121
|
+
SaveTextActivity: {
|
|
122
|
+
id: number;
|
|
123
|
+
userId: number;
|
|
124
|
+
text: string;
|
|
125
|
+
createdAt: number;
|
|
126
|
+
};
|
|
127
|
+
};
|
|
128
|
+
errors?: {
|
|
129
|
+
message: string;
|
|
130
|
+
}[];
|
|
131
|
+
}
|
|
132
|
+
interface MediaListCollectionResponse {
|
|
133
|
+
data?: {
|
|
134
|
+
MediaListCollection: {
|
|
135
|
+
lists: MediaList[];
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
errors?: {
|
|
139
|
+
message: string;
|
|
140
|
+
}[];
|
|
141
|
+
}
|
|
124
142
|
interface List {
|
|
125
143
|
name: string;
|
|
126
144
|
entries: MediaEntry[];
|
|
127
145
|
}
|
|
128
146
|
interface MediaList {
|
|
129
147
|
id(id: number | string): string;
|
|
130
|
-
title:
|
|
131
|
-
english?: string;
|
|
132
|
-
romaji?: string;
|
|
133
|
-
};
|
|
148
|
+
title: MediaTitle;
|
|
134
149
|
name: string;
|
|
135
150
|
entries: MediaListEntry[];
|
|
136
151
|
}
|
|
@@ -171,9 +186,9 @@ interface Myself {
|
|
|
171
186
|
}[];
|
|
172
187
|
}
|
|
173
188
|
interface DateMonthYear {
|
|
174
|
-
day?:
|
|
175
|
-
month?:
|
|
176
|
-
year?:
|
|
189
|
+
day?: number | null;
|
|
190
|
+
month?: number | null;
|
|
191
|
+
year?: number | null;
|
|
177
192
|
}
|
|
178
193
|
interface AnimeDetails {
|
|
179
194
|
data?: {
|
|
@@ -197,6 +212,17 @@ interface AnimeDetails {
|
|
|
197
212
|
message: string;
|
|
198
213
|
}[];
|
|
199
214
|
}
|
|
215
|
+
interface SaveMediaListEntryResponse {
|
|
216
|
+
data?: {
|
|
217
|
+
SaveMediaListEntry: {
|
|
218
|
+
id: number;
|
|
219
|
+
status: string;
|
|
220
|
+
};
|
|
221
|
+
};
|
|
222
|
+
errors?: {
|
|
223
|
+
message: string;
|
|
224
|
+
}[];
|
|
225
|
+
}
|
|
200
226
|
interface MediaListEntry {
|
|
201
227
|
id?: number;
|
|
202
228
|
media: {
|
|
@@ -206,35 +232,179 @@ interface MediaListEntry {
|
|
|
206
232
|
episodes?: number;
|
|
207
233
|
siteUrl?: string;
|
|
208
234
|
chapters?: number;
|
|
235
|
+
format?: string;
|
|
209
236
|
};
|
|
210
237
|
progress?: number;
|
|
211
238
|
status?: string;
|
|
212
239
|
hiddenFromStatusLists?: boolean;
|
|
213
240
|
private?: boolean;
|
|
214
241
|
}
|
|
215
|
-
|
|
216
|
-
|
|
242
|
+
type UserActivitiesResponse = {
|
|
243
|
+
data?: {
|
|
244
|
+
Page: {
|
|
245
|
+
activities: Activity[];
|
|
246
|
+
};
|
|
247
|
+
};
|
|
248
|
+
errors?: {
|
|
249
|
+
message: string;
|
|
250
|
+
}[];
|
|
251
|
+
};
|
|
252
|
+
type UserResponse = {
|
|
253
|
+
data?: {
|
|
254
|
+
User: {
|
|
255
|
+
id: number;
|
|
256
|
+
name: string;
|
|
257
|
+
siteUrl: string;
|
|
258
|
+
donatorTier: string;
|
|
259
|
+
donatorBadge: string;
|
|
260
|
+
createdAt: number;
|
|
261
|
+
updatedAt: number;
|
|
262
|
+
isBlocked: boolean;
|
|
263
|
+
isFollower: boolean;
|
|
264
|
+
isFollowing: boolean;
|
|
265
|
+
options: {
|
|
266
|
+
profileColor: string;
|
|
267
|
+
timezone: string;
|
|
268
|
+
};
|
|
269
|
+
statistics: {
|
|
270
|
+
anime: {
|
|
271
|
+
count: number;
|
|
272
|
+
episodesWatched: number;
|
|
273
|
+
minutesWatched: number;
|
|
274
|
+
};
|
|
275
|
+
manga: {
|
|
276
|
+
count: number;
|
|
277
|
+
chaptersRead: number;
|
|
278
|
+
volumesRead: number;
|
|
279
|
+
};
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
};
|
|
283
|
+
errors?: {
|
|
284
|
+
message: string;
|
|
285
|
+
}[];
|
|
286
|
+
};
|
|
287
|
+
type User = {
|
|
217
288
|
id: number;
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
name: string;
|
|
289
|
+
name: string;
|
|
290
|
+
avatar: {
|
|
291
|
+
large: string;
|
|
292
|
+
medium: string;
|
|
223
293
|
};
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
294
|
+
bannerImage: string;
|
|
295
|
+
isFollower: boolean;
|
|
296
|
+
isFollowing: boolean;
|
|
297
|
+
};
|
|
298
|
+
type UserFollower = {
|
|
299
|
+
data?: {
|
|
300
|
+
Page: {
|
|
301
|
+
pageInfo: {
|
|
302
|
+
total: number;
|
|
303
|
+
perPage: number;
|
|
304
|
+
currentPage: number;
|
|
305
|
+
lastPage: number;
|
|
306
|
+
hasNextPage: boolean;
|
|
307
|
+
};
|
|
308
|
+
followers: User[];
|
|
309
|
+
};
|
|
228
310
|
};
|
|
229
|
-
|
|
230
|
-
|
|
311
|
+
errors?: {
|
|
312
|
+
message: string;
|
|
313
|
+
}[];
|
|
314
|
+
};
|
|
315
|
+
type UserFollowing = {
|
|
316
|
+
data?: {
|
|
317
|
+
Page: {
|
|
318
|
+
pageInfo: {
|
|
319
|
+
total: number;
|
|
320
|
+
perPage: number;
|
|
321
|
+
currentPage: number;
|
|
322
|
+
lastPage: number;
|
|
323
|
+
hasNextPage: boolean;
|
|
324
|
+
};
|
|
325
|
+
following: User[];
|
|
326
|
+
};
|
|
231
327
|
};
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
328
|
+
errors?: {
|
|
329
|
+
message: string;
|
|
330
|
+
}[];
|
|
331
|
+
};
|
|
332
|
+
type AnimeSearchResponse = {
|
|
333
|
+
data?: {
|
|
334
|
+
Page: {
|
|
335
|
+
media: {
|
|
336
|
+
id: number;
|
|
337
|
+
title: MediaTitle;
|
|
338
|
+
startDate: DateMonthYear;
|
|
339
|
+
episodes: number;
|
|
340
|
+
status: string;
|
|
341
|
+
description: string;
|
|
342
|
+
}[];
|
|
235
343
|
};
|
|
236
344
|
};
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
}
|
|
240
|
-
|
|
345
|
+
errors?: {
|
|
346
|
+
message: string;
|
|
347
|
+
}[];
|
|
348
|
+
};
|
|
349
|
+
type ToggleFollowResponse = {
|
|
350
|
+
data?: {
|
|
351
|
+
ToggleFollow: {
|
|
352
|
+
id: number;
|
|
353
|
+
name: string;
|
|
354
|
+
isFollower: boolean;
|
|
355
|
+
isFollowing: boolean;
|
|
356
|
+
};
|
|
357
|
+
};
|
|
358
|
+
errors?: {
|
|
359
|
+
message: string;
|
|
360
|
+
}[];
|
|
361
|
+
};
|
|
362
|
+
type DeleteMediaListResponse = {
|
|
363
|
+
data?: {
|
|
364
|
+
DeleteMediaListEntry: {
|
|
365
|
+
deleted: boolean;
|
|
366
|
+
};
|
|
367
|
+
};
|
|
368
|
+
errors?: {
|
|
369
|
+
message: string;
|
|
370
|
+
}[];
|
|
371
|
+
};
|
|
372
|
+
type Activity = {
|
|
373
|
+
id: number;
|
|
374
|
+
type: string;
|
|
375
|
+
status: string;
|
|
376
|
+
progress: number | null;
|
|
377
|
+
media: {
|
|
378
|
+
id?: number;
|
|
379
|
+
title: MediaTitle;
|
|
380
|
+
};
|
|
381
|
+
createdAt: number;
|
|
382
|
+
};
|
|
383
|
+
type Error = {
|
|
384
|
+
message: string;
|
|
385
|
+
}[];
|
|
386
|
+
type CoverImage = {
|
|
387
|
+
color: string;
|
|
388
|
+
medium: string;
|
|
389
|
+
large: string;
|
|
390
|
+
extraLarge: string;
|
|
391
|
+
};
|
|
392
|
+
type MangaDetails = {
|
|
393
|
+
data?: {
|
|
394
|
+
Media: {
|
|
395
|
+
id: number;
|
|
396
|
+
title: MediaTitle;
|
|
397
|
+
coverImage: CoverImage;
|
|
398
|
+
bannerImage: string;
|
|
399
|
+
description: string;
|
|
400
|
+
chapters: number | null;
|
|
401
|
+
volumes: number | null;
|
|
402
|
+
status: string;
|
|
403
|
+
genres: [string];
|
|
404
|
+
startDate: DateMonthYear;
|
|
405
|
+
endDate: DateMonthYear;
|
|
406
|
+
};
|
|
407
|
+
};
|
|
408
|
+
errors?: Error;
|
|
409
|
+
};
|
|
410
|
+
export { Activity, AniListMediaStatus, AnimeDetails, AnimeList, AnimeSearchResponse, DateMonthYear, DeleteMangaResponse, DeleteMediaListResponse, List, MALAnimeStatus, MALAnimeXML, MALMangaStatus, MalIdToAnilistIdResponse, MangaDetails, MediaEntry, MediaList, MediaListCollectionResponse, MediaListEntry, MediaTitle, MediaWithProgress, Myself, SaveMediaListEntryResponse, SaveTextActivityResponse, ToggleFollowResponse, User, UserActivitiesResponse, UserFollower, UserFollowing, UserResponse, saveAnimeWithProgressResponse, };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
declare class Validate {
|
|
2
|
+
/**
|
|
3
|
+
* Validate importable JSON file
|
|
4
|
+
* @param data string
|
|
5
|
+
* @returns boolean
|
|
6
|
+
*/
|
|
7
|
+
static Import_JSON(data: {
|
|
8
|
+
id: number;
|
|
9
|
+
}[]): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Validate if MyAnimeList Anime XML file is valid or not
|
|
12
|
+
* @param xmlData string
|
|
13
|
+
* @returns boolean
|
|
14
|
+
*/
|
|
15
|
+
static Import_AnimeXML(xmlData: string): Promise<boolean>;
|
|
16
|
+
/**
|
|
17
|
+
* Validate if MyAnimeList Anime XML file is valid or not
|
|
18
|
+
* @param xmlData string
|
|
19
|
+
* @returns boolean
|
|
20
|
+
*/
|
|
21
|
+
static Import_MangaXML(xmlData: string): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* Validate AniDB json-large file
|
|
24
|
+
* @param file string of anidb json-large
|
|
25
|
+
* @returns boolean
|
|
26
|
+
*/
|
|
27
|
+
static Import_AniDBJSONLarge(file: string): Promise<boolean>;
|
|
28
|
+
}
|
|
29
|
+
export { Validate };
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { parseStringPromise } from "xml2js";
|
|
11
|
+
class Validate {
|
|
12
|
+
/**
|
|
13
|
+
* Validate importable JSON file
|
|
14
|
+
* @param data string
|
|
15
|
+
* @returns boolean
|
|
16
|
+
*/
|
|
17
|
+
static Import_JSON(data) {
|
|
18
|
+
return (Array.isArray(data) &&
|
|
19
|
+
data.every((item) => typeof item === "object" && item !== null && "id" in item));
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validate if MyAnimeList Anime XML file is valid or not
|
|
23
|
+
* @param xmlData string
|
|
24
|
+
* @returns boolean
|
|
25
|
+
*/
|
|
26
|
+
static Import_AnimeXML(xmlData) {
|
|
27
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
28
|
+
try {
|
|
29
|
+
const result = yield parseStringPromise(xmlData, { explicitArray: false });
|
|
30
|
+
if (!result || !result.myanimelist) {
|
|
31
|
+
console.error("Invalid XML structure: Missing 'myanimelist' root element.");
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
const animeList = result.myanimelist.anime;
|
|
35
|
+
if (!animeList) {
|
|
36
|
+
console.error("Invalid XML structure: Missing 'anime' elements.");
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
const animeArray = Array.isArray(animeList) ? animeList : [animeList];
|
|
40
|
+
const isValid = animeArray.every((anime) => {
|
|
41
|
+
const isValidId = anime.series_animedb_id && !isNaN(Number(anime.series_animedb_id));
|
|
42
|
+
const hasRequiredFields = anime.series_title && anime.my_status;
|
|
43
|
+
return isValidId && hasRequiredFields;
|
|
44
|
+
});
|
|
45
|
+
if (!isValid) {
|
|
46
|
+
console.error("Validation failed: Some anime entries are missing required fields or have invalid IDs.");
|
|
47
|
+
}
|
|
48
|
+
return isValid;
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
console.error("Error parsing or validating XML:", error);
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Validate if MyAnimeList Anime XML file is valid or not
|
|
58
|
+
* @param xmlData string
|
|
59
|
+
* @returns boolean
|
|
60
|
+
*/
|
|
61
|
+
static Import_MangaXML(xmlData) {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
try {
|
|
64
|
+
const result = yield parseStringPromise(xmlData, { explicitArray: false });
|
|
65
|
+
if (!result || !result.myanimelist) {
|
|
66
|
+
console.error("Invalid XML structure: Missing 'myanimelist' root element.");
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
const mangaList = result.myanimelist.manga;
|
|
70
|
+
if (!mangaList) {
|
|
71
|
+
console.error("Invalid XML structure: Missing 'manga' elements.");
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
const mangaArray = Array.isArray(mangaList) ? mangaList : [mangaList];
|
|
75
|
+
const isValid = mangaArray.every((manga) => {
|
|
76
|
+
const isValidId = manga.manga_mangadb_id && !isNaN(Number(manga.manga_mangadb_id));
|
|
77
|
+
const hasRequiredFields = manga.manga_title && manga.my_status;
|
|
78
|
+
return isValidId && hasRequiredFields;
|
|
79
|
+
});
|
|
80
|
+
if (!isValid) {
|
|
81
|
+
console.error("Validation failed: Some manga entries are missing required fields or have invalid IDs.");
|
|
82
|
+
}
|
|
83
|
+
return isValid;
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
console.error("Error parsing or validating XML:", error);
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Validate AniDB json-large file
|
|
93
|
+
* @param file string of anidb json-large
|
|
94
|
+
* @returns boolean
|
|
95
|
+
*/
|
|
96
|
+
static Import_AniDBJSONLarge(file) {
|
|
97
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
+
try {
|
|
99
|
+
if (!(file === null || file === void 0 ? void 0 : file.trim())) {
|
|
100
|
+
console.error("File content is empty or invalid.");
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
const obj3ct = JSON.parse(file);
|
|
104
|
+
if (!obj3ct || !Array.isArray(obj3ct.anime)) {
|
|
105
|
+
console.error("Invalid JSON structure: Missing or malformed 'anime' array.");
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.error("Failed to parse JSON file:", error);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
export { Validate };
|
package/bin/helpers/workers.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MALAnimeStatus, MALMangaStatus, MediaWithProgress
|
|
1
|
+
import { DateMonthYear, MALAnimeStatus, MALMangaStatus, MediaWithProgress } from "./types.js";
|
|
2
2
|
declare const aniListEndpoint = "https://graphql.anilist.co";
|
|
3
3
|
declare const redirectUri = "https://anilist.co/api/v2/oauth/pin";
|
|
4
4
|
declare function getTitle(title: {
|
|
@@ -6,9 +6,9 @@ declare function getTitle(title: {
|
|
|
6
6
|
romaji?: string;
|
|
7
7
|
}): string;
|
|
8
8
|
declare function formatDateObject(dateObj: {
|
|
9
|
-
day?:
|
|
10
|
-
month?:
|
|
11
|
-
year?:
|
|
9
|
+
day?: number;
|
|
10
|
+
month?: number;
|
|
11
|
+
year?: number;
|
|
12
12
|
} | null): string;
|
|
13
13
|
declare function getNextSeasonAndYear(): {
|
|
14
14
|
nextSeason: string;
|
|
@@ -20,21 +20,30 @@ declare function getFormattedDate(): string;
|
|
|
20
20
|
/**
|
|
21
21
|
* Export JSON as JSON
|
|
22
22
|
* @param js0n
|
|
23
|
-
* @param dataType (eg: anime
|
|
23
|
+
* @param dataType (eg: anime|manga)
|
|
24
24
|
*/
|
|
25
25
|
declare function saveJSONasJSON(js0n: object, dataType: string): Promise<void>;
|
|
26
26
|
/**
|
|
27
27
|
* Export JSON as CSV
|
|
28
28
|
* @param js0n
|
|
29
|
-
* @param dataType (eg: anime
|
|
29
|
+
* @param dataType (eg: anime|manga)
|
|
30
30
|
*/
|
|
31
|
-
declare function saveJSONasCSV(js0n:
|
|
31
|
+
declare function saveJSONasCSV(js0n: MediaWithProgress[], dataType: string): Promise<void>;
|
|
32
|
+
declare function saveJSONasXML(js0n: MediaWithProgress[], data_type: 0 | 1): Promise<void>;
|
|
32
33
|
declare function selectFile(fileType: string): Promise<string>;
|
|
33
|
-
declare function createAnimeXML(malId: number, progress: number, status: MALAnimeStatus, episodes: number, title: string): string;
|
|
34
|
+
declare function createAnimeXML(malId: number, progress: number, status: MALAnimeStatus, episodes: number, title: string, format: string): string;
|
|
34
35
|
declare function createMangaXML(malId: number, progress: number, status: MALMangaStatus, chapters: number, title: string): string;
|
|
35
36
|
declare function createAnimeListXML(mediaWithProgress: MediaWithProgress[]): Promise<string>;
|
|
36
37
|
declare function createMangaListXML(mediaWithProgress: MediaWithProgress[]): Promise<string>;
|
|
37
38
|
declare function getCurrentPackageVersion(): string | null;
|
|
38
39
|
declare function timestampToTimeAgo(timestamp: number): string;
|
|
39
|
-
declare
|
|
40
|
-
|
|
40
|
+
declare const anidbToanilistMapper: (romanjiName: string, year: number, englishName?: string) => Promise<number | null>;
|
|
41
|
+
/**
|
|
42
|
+
* Extract the save file path
|
|
43
|
+
* @param data_type - anime|manga
|
|
44
|
+
* @param file_format - save format (eg: .json|.csv)
|
|
45
|
+
* @returns string of file path
|
|
46
|
+
*/
|
|
47
|
+
declare function saveToPath(data_type: string, file_format: string): Promise<string>;
|
|
48
|
+
declare function simpleDateFormat(date: DateMonthYear): string;
|
|
49
|
+
export { anidbToanilistMapper, aniListEndpoint, createAnimeListXML, createAnimeXML, createMangaListXML, createMangaXML, formatDateObject, getCurrentPackageVersion, getDownloadFolderPath, getFormattedDate, getNextSeasonAndYear, getTitle, redirectUri, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, saveJSONasXML, saveToPath, selectFile, simpleDateFormat, timestampToTimeAgo, };
|