@irfanshadikrishad/anilist 1.0.0-forbidden.2 → 1.0.0-forbidden.3
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 +373 -0
- package/LICENSE.md +382 -382
- package/README.md +255 -243
- package/bin/helpers/auth.d.ts +14 -4
- package/bin/helpers/auth.js +307 -209
- package/bin/helpers/lists.js +143 -123
- package/bin/helpers/queries.d.ts +4 -3
- package/bin/helpers/queries.js +10 -6
- package/bin/helpers/types.d.ts +110 -82
- package/bin/helpers/validation.d.ts +29 -0
- package/bin/helpers/validation.js +117 -0
- package/bin/helpers/workers.d.ts +14 -6
- package/bin/helpers/workers.js +80 -34
- package/bin/index.js +25 -1
- package/package.json +84 -81
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
|
}
|
|
@@ -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,48 +232,17 @@ 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
|
-
interface TheActivity {
|
|
216
|
-
type: string;
|
|
217
|
-
id: number;
|
|
218
|
-
message?: string;
|
|
219
|
-
createdAt: number;
|
|
220
|
-
recipient?: {
|
|
221
|
-
id: number;
|
|
222
|
-
name: string;
|
|
223
|
-
};
|
|
224
|
-
isLiked?: boolean;
|
|
225
|
-
user?: {
|
|
226
|
-
id?: number;
|
|
227
|
-
name?: string;
|
|
228
|
-
};
|
|
229
|
-
messenger?: {
|
|
230
|
-
name: string;
|
|
231
|
-
};
|
|
232
|
-
media?: {
|
|
233
|
-
title?: {
|
|
234
|
-
userPreferred: string;
|
|
235
|
-
};
|
|
236
|
-
};
|
|
237
|
-
progress?: string | null;
|
|
238
|
-
status?: string;
|
|
239
|
-
}
|
|
240
242
|
type UserActivitiesResponse = {
|
|
241
243
|
data?: {
|
|
242
244
|
Page: {
|
|
243
|
-
activities:
|
|
244
|
-
status: string;
|
|
245
|
-
progress: number;
|
|
246
|
-
createdAt: number;
|
|
247
|
-
media: {
|
|
248
|
-
title: MediaTitle;
|
|
249
|
-
};
|
|
250
|
-
}[];
|
|
245
|
+
activities: Activity[];
|
|
251
246
|
};
|
|
252
247
|
};
|
|
253
248
|
errors?: {
|
|
@@ -289,6 +284,17 @@ type UserResponse = {
|
|
|
289
284
|
message: string;
|
|
290
285
|
}[];
|
|
291
286
|
};
|
|
287
|
+
type User = {
|
|
288
|
+
id: number;
|
|
289
|
+
name: string;
|
|
290
|
+
avatar: {
|
|
291
|
+
large: string;
|
|
292
|
+
medium: string;
|
|
293
|
+
};
|
|
294
|
+
bannerImage: string;
|
|
295
|
+
isFollower: boolean;
|
|
296
|
+
isFollowing: boolean;
|
|
297
|
+
};
|
|
292
298
|
type UserFollower = {
|
|
293
299
|
data?: {
|
|
294
300
|
Page: {
|
|
@@ -299,30 +305,13 @@ type UserFollower = {
|
|
|
299
305
|
lastPage: number;
|
|
300
306
|
hasNextPage: boolean;
|
|
301
307
|
};
|
|
302
|
-
followers:
|
|
303
|
-
id: number;
|
|
304
|
-
name: string;
|
|
305
|
-
avatar: {
|
|
306
|
-
large: string;
|
|
307
|
-
medium: string;
|
|
308
|
-
};
|
|
309
|
-
bannerImage: string;
|
|
310
|
-
}[];
|
|
308
|
+
followers: User[];
|
|
311
309
|
};
|
|
312
310
|
};
|
|
313
311
|
errors?: {
|
|
314
312
|
message: string;
|
|
315
313
|
}[];
|
|
316
314
|
};
|
|
317
|
-
type User = {
|
|
318
|
-
id: number;
|
|
319
|
-
name: string;
|
|
320
|
-
avatar: {
|
|
321
|
-
large: string;
|
|
322
|
-
medium: string;
|
|
323
|
-
};
|
|
324
|
-
bannerImage: string;
|
|
325
|
-
};
|
|
326
315
|
type UserFollowing = {
|
|
327
316
|
data?: {
|
|
328
317
|
Page: {
|
|
@@ -357,36 +346,68 @@ type AnimeSearchResponse = {
|
|
|
357
346
|
message: string;
|
|
358
347
|
}[];
|
|
359
348
|
};
|
|
360
|
-
type
|
|
349
|
+
type ToggleFollowResponse = {
|
|
361
350
|
data?: {
|
|
362
|
-
|
|
351
|
+
ToggleFollow: {
|
|
363
352
|
id: number;
|
|
353
|
+
name: string;
|
|
354
|
+
isFollower: boolean;
|
|
355
|
+
isFollowing: boolean;
|
|
364
356
|
};
|
|
365
357
|
};
|
|
366
358
|
errors?: {
|
|
367
359
|
message: string;
|
|
368
360
|
}[];
|
|
369
361
|
};
|
|
370
|
-
type
|
|
362
|
+
type DeleteMediaListResponse = {
|
|
371
363
|
data?: {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
total: number;
|
|
375
|
-
perPage: number;
|
|
376
|
-
currentPage: number;
|
|
377
|
-
lastPage: number;
|
|
378
|
-
hasNextPage: boolean;
|
|
379
|
-
};
|
|
380
|
-
activities: TheActivity[];
|
|
364
|
+
DeleteMediaListEntry: {
|
|
365
|
+
deleted: boolean;
|
|
381
366
|
};
|
|
382
367
|
};
|
|
383
368
|
errors?: {
|
|
384
369
|
message: string;
|
|
385
370
|
}[];
|
|
386
371
|
};
|
|
387
|
-
type
|
|
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
|
+
interface TheActivity {
|
|
384
|
+
type: string;
|
|
385
|
+
id: number;
|
|
386
|
+
message?: string;
|
|
387
|
+
createdAt: number;
|
|
388
|
+
recipient?: {
|
|
389
|
+
id: number;
|
|
390
|
+
name: string;
|
|
391
|
+
};
|
|
392
|
+
isLiked?: boolean;
|
|
393
|
+
user?: {
|
|
394
|
+
id?: number;
|
|
395
|
+
name?: string;
|
|
396
|
+
};
|
|
397
|
+
messenger?: {
|
|
398
|
+
name: string;
|
|
399
|
+
};
|
|
400
|
+
media?: {
|
|
401
|
+
title?: {
|
|
402
|
+
userPreferred: string;
|
|
403
|
+
};
|
|
404
|
+
};
|
|
405
|
+
progress?: string | null;
|
|
406
|
+
status?: string;
|
|
407
|
+
}
|
|
408
|
+
type LikeActivityResponse = {
|
|
388
409
|
data?: {
|
|
389
|
-
|
|
410
|
+
ToggleLike: {
|
|
390
411
|
id: number;
|
|
391
412
|
};
|
|
392
413
|
};
|
|
@@ -394,14 +415,21 @@ type SaveTextActivityResponse = {
|
|
|
394
415
|
message: string;
|
|
395
416
|
}[];
|
|
396
417
|
};
|
|
397
|
-
type
|
|
418
|
+
type SpecificUserActivitiesResponse = {
|
|
398
419
|
data?: {
|
|
399
|
-
|
|
400
|
-
|
|
420
|
+
Page: {
|
|
421
|
+
pageInfo: {
|
|
422
|
+
total: number;
|
|
423
|
+
perPage: number;
|
|
424
|
+
currentPage: number;
|
|
425
|
+
lastPage: number;
|
|
426
|
+
hasNextPage: boolean;
|
|
427
|
+
};
|
|
428
|
+
activities: TheActivity[];
|
|
401
429
|
};
|
|
402
430
|
};
|
|
403
431
|
errors?: {
|
|
404
432
|
message: string;
|
|
405
433
|
}[];
|
|
406
434
|
};
|
|
407
|
-
export { AniListMediaStatus, AnimeDetails, AnimeList, AnimeSearchResponse, DateMonthYear,
|
|
435
|
+
export { Activity, AniListMediaStatus, AnimeDetails, AnimeList, AnimeSearchResponse, DateMonthYear, DeleteMangaResponse, DeleteMediaListResponse, LikeActivityResponse, List, MALAnimeStatus, MALAnimeXML, MALMangaStatus, MalIdToAnilistIdResponse, MediaEntry, MediaList, MediaListCollectionResponse, MediaListEntry, MediaTitle, MediaWithProgress, Myself, SaveMediaListEntryResponse, SaveTextActivityResponse, SpecificUserActivitiesResponse, TheActivity, 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
|
@@ -20,22 +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 function activityBy(activity: TheActivity): string;
|
|
40
40
|
declare const anidbToanilistMapper: (romanjiName: string, year: number, englishName?: string) => Promise<number | null>;
|
|
41
|
-
|
|
41
|
+
declare function activityBy(activity: TheActivity, count?: number): string;
|
|
42
|
+
/**
|
|
43
|
+
* Extract the save file path
|
|
44
|
+
* @param data_type - anime|manga
|
|
45
|
+
* @param file_format - save format (eg: .json|.csv)
|
|
46
|
+
* @returns string of file path
|
|
47
|
+
*/
|
|
48
|
+
declare function saveToPath(data_type: string, file_format: string): Promise<string>;
|
|
49
|
+
export { activityBy, anidbToanilistMapper, aniListEndpoint, createAnimeListXML, createAnimeXML, createMangaListXML, createMangaXML, formatDateObject, getCurrentPackageVersion, getDownloadFolderPath, getFormattedDate, getNextSeasonAndYear, getTitle, redirectUri, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, saveJSONasXML, saveToPath, selectFile, timestampToTimeAgo, };
|
package/bin/helpers/workers.js
CHANGED
|
@@ -7,13 +7,24 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
11
|
+
var t = {};
|
|
12
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
13
|
+
t[p] = s[p];
|
|
14
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
15
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
16
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
17
|
+
t[p[i]] = s[p[i]];
|
|
18
|
+
}
|
|
19
|
+
return t;
|
|
20
|
+
};
|
|
10
21
|
import fs from "fs";
|
|
11
22
|
import { readdir, writeFile } from "fs/promises";
|
|
12
23
|
import inquirer from "inquirer";
|
|
13
|
-
import { parse } from "json2csv";
|
|
14
24
|
import { createRequire } from "module";
|
|
15
25
|
import open from "open";
|
|
16
26
|
import { homedir } from "os";
|
|
27
|
+
import Papa from "papaparse";
|
|
17
28
|
import { join } from "path";
|
|
18
29
|
import process from "process";
|
|
19
30
|
import { Auth } from "./auth.js";
|
|
@@ -97,13 +108,13 @@ function getFormattedDate() {
|
|
|
97
108
|
/**
|
|
98
109
|
* Export JSON as JSON
|
|
99
110
|
* @param js0n
|
|
100
|
-
* @param dataType (eg: anime
|
|
111
|
+
* @param dataType (eg: anime|manga)
|
|
101
112
|
*/
|
|
102
113
|
function saveJSONasJSON(js0n, dataType) {
|
|
103
114
|
return __awaiter(this, void 0, void 0, function* () {
|
|
104
115
|
try {
|
|
105
116
|
const jsonData = JSON.stringify(js0n, null, 2);
|
|
106
|
-
const path =
|
|
117
|
+
const path = yield saveToPath(dataType, ".json");
|
|
107
118
|
yield writeFile(path, jsonData, "utf8");
|
|
108
119
|
console.log(`\nSaved as JSON successfully.`);
|
|
109
120
|
open(getDownloadFolderPath());
|
|
@@ -116,13 +127,17 @@ function saveJSONasJSON(js0n, dataType) {
|
|
|
116
127
|
/**
|
|
117
128
|
* Export JSON as CSV
|
|
118
129
|
* @param js0n
|
|
119
|
-
* @param dataType (eg: anime
|
|
130
|
+
* @param dataType (eg: anime|manga)
|
|
120
131
|
*/
|
|
121
132
|
function saveJSONasCSV(js0n, dataType) {
|
|
122
133
|
return __awaiter(this, void 0, void 0, function* () {
|
|
123
134
|
try {
|
|
124
|
-
const
|
|
125
|
-
|
|
135
|
+
const js0n_WTAS = js0n.map((_a) => {
|
|
136
|
+
var { title } = _a, rest = __rest(_a, ["title"]);
|
|
137
|
+
return (Object.assign(Object.assign({}, rest), { title: getTitle(title) }));
|
|
138
|
+
});
|
|
139
|
+
const csvData = Papa.unparse(js0n_WTAS);
|
|
140
|
+
const path = yield saveToPath(dataType, ".csv");
|
|
126
141
|
yield writeFile(path, csvData, "utf8");
|
|
127
142
|
console.log(`\nSaved as CSV successfully.`);
|
|
128
143
|
open(getDownloadFolderPath());
|
|
@@ -132,6 +147,20 @@ function saveJSONasCSV(js0n, dataType) {
|
|
|
132
147
|
}
|
|
133
148
|
});
|
|
134
149
|
}
|
|
150
|
+
function saveJSONasXML(js0n, data_type) {
|
|
151
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
152
|
+
try {
|
|
153
|
+
const xmlContent = data_type === 0 ? createAnimeListXML(js0n) : createMangaListXML(js0n);
|
|
154
|
+
const path = yield saveToPath(data_type === 0 ? "anime" : "manga", ".xml");
|
|
155
|
+
yield writeFile(path, yield xmlContent, "utf8");
|
|
156
|
+
console.log(`\nGenerated XML for MyAnimeList.`);
|
|
157
|
+
open(getDownloadFolderPath());
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
console.error(`Error saving XML data:`, error);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
135
164
|
function listFilesInDownloadFolder() {
|
|
136
165
|
return __awaiter(this, void 0, void 0, function* () {
|
|
137
166
|
const downloadFolderPath = getDownloadFolderPath();
|
|
@@ -162,21 +191,22 @@ function selectFile(fileType) {
|
|
|
162
191
|
return answers.fileName;
|
|
163
192
|
}
|
|
164
193
|
else {
|
|
165
|
-
|
|
194
|
+
console.error(`\nNo importable ${fileType} file(s) found in download folder.`);
|
|
195
|
+
return null;
|
|
166
196
|
}
|
|
167
197
|
}
|
|
168
198
|
catch (error) {
|
|
169
199
|
console.error("\nError selecting file:", error);
|
|
170
|
-
|
|
200
|
+
return null;
|
|
171
201
|
}
|
|
172
202
|
});
|
|
173
203
|
}
|
|
174
|
-
function createAnimeXML(malId, progress, status, episodes, title) {
|
|
204
|
+
function createAnimeXML(malId, progress, status, episodes, title, format) {
|
|
175
205
|
return `
|
|
176
206
|
<anime>
|
|
177
207
|
<series_animedb_id>${malId}</series_animedb_id>
|
|
178
208
|
<series_title><![CDATA[${title}]]></series_title>
|
|
179
|
-
<series_type
|
|
209
|
+
<series_type>${format}</series_type>
|
|
180
210
|
<series_episodes>${episodes}</series_episodes>
|
|
181
211
|
<my_id>0</my_id>
|
|
182
212
|
<my_watched_episodes>${progress}</my_watched_episodes>
|
|
@@ -226,13 +256,16 @@ function createAnimeListXML(mediaWithProgress) {
|
|
|
226
256
|
PAUSED: MALAnimeStatus.ON_HOLD,
|
|
227
257
|
DROPPED: MALAnimeStatus.DROPPED,
|
|
228
258
|
};
|
|
229
|
-
|
|
259
|
+
// Filter out anime without malId
|
|
260
|
+
const filteredMedia = mediaWithProgress.filter((anime) => anime.malId);
|
|
261
|
+
const xmlEntries = filteredMedia.map((anime) => {
|
|
230
262
|
const malId = anime.malId;
|
|
231
263
|
const progress = anime.progress;
|
|
232
264
|
const episodes = anime.episodes;
|
|
233
265
|
const title = getTitle(anime.title);
|
|
234
266
|
const status = statusMap[anime.status];
|
|
235
|
-
|
|
267
|
+
const format = anime.format ? anime.format : "";
|
|
268
|
+
return createAnimeXML(malId, progress, status, episodes, title, format);
|
|
236
269
|
});
|
|
237
270
|
return `<myanimelist>
|
|
238
271
|
<myinfo>
|
|
@@ -259,7 +292,9 @@ function createMangaListXML(mediaWithProgress) {
|
|
|
259
292
|
PAUSED: MALMangaStatus.ON_HOLD,
|
|
260
293
|
DROPPED: MALMangaStatus.DROPPED,
|
|
261
294
|
};
|
|
262
|
-
|
|
295
|
+
// Filter out manga without malId
|
|
296
|
+
const filteredMedia = mediaWithProgress.filter((manga) => manga.malId);
|
|
297
|
+
const xmlEntries = filteredMedia.map((manga) => {
|
|
263
298
|
const malId = manga.malId;
|
|
264
299
|
const progress = manga.progress;
|
|
265
300
|
const chapters = manga.chapters;
|
|
@@ -316,26 +351,6 @@ function timestampToTimeAgo(timestamp) {
|
|
|
316
351
|
return `${years} year${years === 1 ? "" : "s"} ago`;
|
|
317
352
|
}
|
|
318
353
|
}
|
|
319
|
-
function activityBy(activity) {
|
|
320
|
-
var _a, _b, _c, _d;
|
|
321
|
-
if ((_a = activity === null || activity === void 0 ? void 0 : activity.messenger) === null || _a === void 0 ? void 0 : _a.name) {
|
|
322
|
-
return `[${activity.id}]\t${activity.messenger.name} messaged ${activity.recipient.name}`;
|
|
323
|
-
}
|
|
324
|
-
else if ((_c = (_b = activity === null || activity === void 0 ? void 0 : activity.media) === null || _b === void 0 ? void 0 : _b.title) === null || _c === void 0 ? void 0 : _c.userPreferred) {
|
|
325
|
-
if (activity.progress) {
|
|
326
|
-
return `[${activity.id}]\t${activity.user.name} ${activity.status} ${activity.progress} of ${activity.media.title.userPreferred}`;
|
|
327
|
-
}
|
|
328
|
-
else {
|
|
329
|
-
return `[${activity.id}]\t${activity.user.name} ${activity.status} ${activity.media.title.userPreferred}`;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
else if ((_d = activity === null || activity === void 0 ? void 0 : activity.user) === null || _d === void 0 ? void 0 : _d.name) {
|
|
333
|
-
return `[${activity.id}]\t${activity.user.name}`;
|
|
334
|
-
}
|
|
335
|
-
else {
|
|
336
|
-
return `[${activity === null || activity === void 0 ? void 0 : activity.id}] ???`;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
354
|
const anidbToanilistMapper = (romanjiName, year, englishName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
340
355
|
const fetchAnime = (search) => __awaiter(void 0, void 0, void 0, function* () {
|
|
341
356
|
var _a;
|
|
@@ -365,4 +380,35 @@ const anidbToanilistMapper = (romanjiName, year, englishName) => __awaiter(void
|
|
|
365
380
|
}
|
|
366
381
|
return null;
|
|
367
382
|
});
|
|
368
|
-
|
|
383
|
+
function activityBy(activity, count) {
|
|
384
|
+
var _a, _b, _c, _d;
|
|
385
|
+
if ((_a = activity === null || activity === void 0 ? void 0 : activity.messenger) === null || _a === void 0 ? void 0 : _a.name) {
|
|
386
|
+
return `[${count ? `${count}/` : ""}${activity.id}]\t${activity.messenger.name} messaged ${activity.recipient.name}`;
|
|
387
|
+
}
|
|
388
|
+
else if ((_c = (_b = activity === null || activity === void 0 ? void 0 : activity.media) === null || _b === void 0 ? void 0 : _b.title) === null || _c === void 0 ? void 0 : _c.userPreferred) {
|
|
389
|
+
if (activity.progress) {
|
|
390
|
+
return `[${count ? `${count}/` : ""}${activity.id}]\t${activity.user.name} ${activity.status} ${activity.progress} of ${activity.media.title.userPreferred}`;
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
return `[${count ? `${count}/` : ""}${activity.id}]\t${activity.user.name} ${activity.status} ${activity.media.title.userPreferred}`;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
else if ((_d = activity === null || activity === void 0 ? void 0 : activity.user) === null || _d === void 0 ? void 0 : _d.name) {
|
|
397
|
+
return `[${count ? `${count}/` : ""}${activity.id}]\t${activity.user.name}`;
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
return `[${count ? `${count}/` : ""}${activity === null || activity === void 0 ? void 0 : activity.id}] ???`;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Extract the save file path
|
|
405
|
+
* @param data_type - anime|manga
|
|
406
|
+
* @param file_format - save format (eg: .json|.csv)
|
|
407
|
+
* @returns string of file path
|
|
408
|
+
*/
|
|
409
|
+
function saveToPath(data_type, file_format) {
|
|
410
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
411
|
+
return join(getDownloadFolderPath(), `${yield Auth.MyUserName()}@irfanshadikrishad-anilist-${data_type}-${getFormattedDate()}.${file_format}`);
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
export { activityBy, anidbToanilistMapper, aniListEndpoint, createAnimeListXML, createAnimeXML, createMangaListXML, createMangaXML, formatDateObject, getCurrentPackageVersion, getDownloadFolderPath, getFormattedDate, getNextSeasonAndYear, getTitle, redirectUri, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, saveJSONasXML, saveToPath, selectFile, timestampToTimeAgo, };
|