@irfanshadikrishad/anilist 1.0.0-forbidden.1 → 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.
@@ -8,24 +8,32 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { XMLParser } from "fast-xml-parser";
11
- import { readFile, writeFile } from "fs/promises";
11
+ import { readFile } from "fs/promises";
12
12
  import inquirer from "inquirer";
13
- import fetch from "node-fetch";
13
+ import { jsonrepair } from "jsonrepair";
14
14
  import { join } from "path";
15
15
  import { Auth } from "./auth.js";
16
16
  import { fetcher } from "./fetcher.js";
17
17
  import { addAnimeToListMutation, addMangaToListMutation, saveAnimeWithProgressMutation, saveMangaWithProgressMutation, } from "./mutations.js";
18
- import { animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userQuery, } from "./queries.js";
18
+ import { animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, } from "./queries.js";
19
19
  import { AniListMediaStatus, } from "./types.js";
20
- import { aniListEndpoint, createAnimeListXML, createMangaListXML, formatDateObject, getDownloadFolderPath, getFormattedDate, getNextSeasonAndYear, getTitle, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, selectFile, } from "./workers.js";
20
+ import { Validate } from "./validation.js";
21
+ import { anidbToanilistMapper, formatDateObject, getDownloadFolderPath, getNextSeasonAndYear, getTitle, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, saveJSONasXML, selectFile, timestampToTimeAgo, } from "./workers.js";
21
22
  class AniList {
22
23
  static importAnime() {
23
24
  return __awaiter(this, void 0, void 0, function* () {
24
25
  try {
25
26
  const filename = yield selectFile(".json");
27
+ if (!filename) {
28
+ return;
29
+ }
26
30
  const filePath = join(getDownloadFolderPath(), filename);
27
31
  const fileContent = yield readFile(filePath, "utf8");
28
32
  const importedData = JSON.parse(fileContent);
33
+ if (!Validate.Import_JSON(importedData)) {
34
+ console.error(`\nInvalid JSON file.`);
35
+ return;
36
+ }
29
37
  let count = 0;
30
38
  const batchSize = 1; // Number of requests in each batch
31
39
  const delay = 1100; // delay to avoid rate-limiting
@@ -45,7 +53,7 @@ class AniList {
45
53
  if (save) {
46
54
  const id = (_b = (_a = save === null || save === void 0 ? void 0 : save.data) === null || _a === void 0 ? void 0 : _a.SaveMediaListEntry) === null || _b === void 0 ? void 0 : _b.id;
47
55
  count++;
48
- console.log(`[${count}] ${anime === null || anime === void 0 ? void 0 : anime.id}-${id} ✅`);
56
+ console.log(`[${count}]\t${id}\t${anime === null || anime === void 0 ? void 0 : anime.id} ✅`);
49
57
  }
50
58
  else {
51
59
  console.error(`\nError saving ${anime === null || anime === void 0 ? void 0 : anime.id}`);
@@ -69,9 +77,16 @@ class AniList {
69
77
  return __awaiter(this, void 0, void 0, function* () {
70
78
  try {
71
79
  const filename = yield selectFile(".json");
80
+ if (!filename) {
81
+ return;
82
+ }
72
83
  const filePath = join(getDownloadFolderPath(), filename);
73
84
  const fileContent = yield readFile(filePath, "utf8");
74
85
  const importedData = JSON.parse(fileContent);
86
+ if (!Validate.Import_JSON(importedData)) {
87
+ console.error(`\nInvalid JSON file.`);
88
+ return;
89
+ }
75
90
  let count = 0;
76
91
  const batchSize = 1; // Adjust batch size as per rate-limit constraints
77
92
  const delay = 1100; // 2 seconds delay to avoid rate-limit
@@ -93,7 +108,7 @@ class AniList {
93
108
  if (save) {
94
109
  const id = (_b = (_a = save === null || save === void 0 ? void 0 : save.data) === null || _a === void 0 ? void 0 : _a.SaveMediaListEntry) === null || _b === void 0 ? void 0 : _b.id;
95
110
  count++;
96
- console.log(`[${count}] ${manga === null || manga === void 0 ? void 0 : manga.id}-${id} ✅`);
111
+ console.log(`[${count}]\t${id}\t${manga === null || manga === void 0 ? void 0 : manga.id} ✅`);
97
112
  }
98
113
  }
99
114
  catch (err) {
@@ -113,7 +128,76 @@ class AniList {
113
128
  static exportAnime() {
114
129
  return __awaiter(this, void 0, void 0, function* () {
115
130
  var _a, _b, _c;
116
- if (yield Auth.isLoggedIn()) {
131
+ if (!(yield Auth.isLoggedIn())) {
132
+ console.error(`\nMust login to use this feature.`);
133
+ return;
134
+ }
135
+ const { exportType } = yield inquirer.prompt([
136
+ {
137
+ type: "list",
138
+ name: "exportType",
139
+ message: "Choose export type:",
140
+ choices: [
141
+ { name: "CSV", value: 1 },
142
+ { name: "JSON", value: 2 },
143
+ { name: "XML (MyAnimeList/AniDB)", value: 3 },
144
+ ],
145
+ pageSize: 10,
146
+ },
147
+ ]);
148
+ const animeList = yield fetcher(currentUserAnimeList, {
149
+ id: yield Auth.MyUserId(),
150
+ });
151
+ if (animeList) {
152
+ const lists = (_c = (_b = (_a = animeList === null || animeList === void 0 ? void 0 : animeList.data) === null || _a === void 0 ? void 0 : _a.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists) !== null && _c !== void 0 ? _c : [];
153
+ const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
154
+ var _a, _b, _c, _d;
155
+ return ({
156
+ id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
157
+ title: (_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.title,
158
+ episodes: (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.episodes,
159
+ siteUrl: (_d = entry === null || entry === void 0 ? void 0 : entry.media) === null || _d === void 0 ? void 0 : _d.siteUrl,
160
+ progress: entry.progress,
161
+ status: entry === null || entry === void 0 ? void 0 : entry.status,
162
+ hiddenFromStatusLists: entry.hiddenFromStatusLists,
163
+ });
164
+ }));
165
+ switch (exportType) {
166
+ case 1:
167
+ yield saveJSONasCSV(mediaWithProgress, "anime");
168
+ break;
169
+ case 2:
170
+ yield saveJSONasJSON(mediaWithProgress, "anime");
171
+ break;
172
+ case 3:
173
+ yield MyAnimeList.exportAnime();
174
+ break;
175
+ default:
176
+ console.log(`\nInvalid export type. ${exportType}`);
177
+ break;
178
+ }
179
+ }
180
+ else {
181
+ console.error(`\nNo anime(s) found in your lists.`);
182
+ }
183
+ });
184
+ }
185
+ static exportManga() {
186
+ return __awaiter(this, void 0, void 0, function* () {
187
+ var _a, _b;
188
+ if (!(yield Auth.isLoggedIn())) {
189
+ console.error(`\nPlease login to use this feature.`);
190
+ return;
191
+ }
192
+ const mangaLists = yield fetcher(currentUserMangaList, {
193
+ id: yield Auth.MyUserId(),
194
+ });
195
+ if (!(mangaLists === null || mangaLists === void 0 ? void 0 : mangaLists.data)) {
196
+ console.error(`\nCould not get manga list.`);
197
+ return;
198
+ }
199
+ const lists = ((_b = (_a = mangaLists === null || mangaLists === void 0 ? void 0 : mangaLists.data) === null || _a === void 0 ? void 0 : _a.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists) || [];
200
+ if (lists.length > 0) {
117
201
  const { exportType } = yield inquirer.prompt([
118
202
  {
119
203
  type: "list",
@@ -127,141 +211,53 @@ class AniList {
127
211
  pageSize: 10,
128
212
  },
129
213
  ]);
130
- const animeList = yield fetcher(currentUserAnimeList, {
131
- id: yield Auth.MyUserId(),
132
- });
133
- if (animeList) {
134
- const lists = (_c = (_b = (_a = animeList === null || animeList === void 0 ? void 0 : animeList.data) === null || _a === void 0 ? void 0 : _a.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists) !== null && _c !== void 0 ? _c : [];
135
- const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
136
- var _a, _b, _c, _d, _e;
137
- return ({
138
- id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
139
- title: exportType === 1
140
- ? getTitle((_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.title)
141
- : (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title,
142
- episodes: (_d = entry === null || entry === void 0 ? void 0 : entry.media) === null || _d === void 0 ? void 0 : _d.episodes,
143
- siteUrl: (_e = entry === null || entry === void 0 ? void 0 : entry.media) === null || _e === void 0 ? void 0 : _e.siteUrl,
144
- progress: entry.progress,
145
- status: entry === null || entry === void 0 ? void 0 : entry.status,
146
- hiddenFromStatusLists: entry.hiddenFromStatusLists,
147
- });
148
- }));
149
- switch (exportType) {
150
- case 1:
151
- yield saveJSONasCSV(mediaWithProgress, "anime");
152
- break;
153
- case 2:
154
- yield saveJSONasJSON(mediaWithProgress, "anime");
155
- break;
156
- case 3:
157
- yield MyAnimeList.exportAnime();
158
- break;
159
- default:
160
- console.log(`\nInvalid export type. ${exportType}`);
161
- break;
162
- }
163
- }
164
- else {
165
- console.error(`\nNo anime(s) found in your lists.`);
166
- }
167
- }
168
- else {
169
- console.error(`\nMust login to use this feature.`);
170
- }
171
- });
172
- }
173
- static exportManga() {
174
- return __awaiter(this, void 0, void 0, function* () {
175
- var _a, _b;
176
- if (yield Auth.isLoggedIn()) {
177
- const mangaLists = yield fetcher(currentUserMangaList, {
178
- id: yield Auth.MyUserId(),
179
- });
180
- if (mangaLists) {
181
- const lists = ((_b = (_a = mangaLists === null || mangaLists === void 0 ? void 0 : mangaLists.data) === null || _a === void 0 ? void 0 : _a.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists) || [];
182
- if (lists.length > 0) {
183
- const { exportType } = yield inquirer.prompt([
184
- {
185
- type: "list",
186
- name: "exportType",
187
- message: "Choose export type:",
188
- choices: [
189
- { name: "CSV", value: 1 },
190
- { name: "JSON", value: 2 },
191
- { name: "XML (MyAnimeList)", value: 3 },
192
- ],
193
- pageSize: 10,
194
- },
195
- ]);
196
- const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
197
- var _a, _b, _c;
198
- return ({
199
- id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
200
- title: exportType === 1
201
- ? getTitle((_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.title)
202
- : (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title,
203
- private: entry.private,
204
- chapters: entry.media.chapters,
205
- progress: entry.progress,
206
- status: entry === null || entry === void 0 ? void 0 : entry.status,
207
- hiddenFromStatusLists: entry.hiddenFromStatusLists,
208
- });
209
- }));
210
- switch (exportType) {
211
- case 1:
212
- yield saveJSONasCSV(mediaWithProgress, "manga");
213
- break;
214
- case 2:
215
- yield saveJSONasJSON(mediaWithProgress, "manga");
216
- break;
217
- case 3:
218
- yield MyAnimeList.exportManga();
219
- break;
220
- default:
221
- console.log(`\nInvalid export type. ${exportType}`);
222
- break;
223
- }
224
- }
225
- else {
226
- console.log(`\nList seems to be empty.`);
227
- }
228
- }
229
- else {
230
- console.error(`\nCould not get manga list.`);
214
+ const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
215
+ var _a, _b;
216
+ return ({
217
+ id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
218
+ title: (_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.title,
219
+ private: entry.private,
220
+ chapters: entry.media.chapters,
221
+ progress: entry.progress,
222
+ status: entry === null || entry === void 0 ? void 0 : entry.status,
223
+ hiddenFromStatusLists: entry.hiddenFromStatusLists,
224
+ });
225
+ }));
226
+ switch (exportType) {
227
+ case 1:
228
+ yield saveJSONasCSV(mediaWithProgress, "manga");
229
+ break;
230
+ case 2:
231
+ yield saveJSONasJSON(mediaWithProgress, "manga");
232
+ break;
233
+ case 3:
234
+ yield MyAnimeList.exportManga();
235
+ break;
236
+ default:
237
+ console.log(`\nInvalid export type. ${exportType}`);
238
+ break;
231
239
  }
232
240
  }
233
241
  else {
234
- console.error(`\nPlease login to use this feature.`);
242
+ console.log(`\nList seems to be empty.`);
235
243
  }
236
244
  });
237
245
  }
238
246
  static MyAnime() {
239
247
  return __awaiter(this, void 0, void 0, function* () {
240
- var _a, _b, _c;
248
+ var _a, _b, _c, _d, _e;
241
249
  try {
242
250
  if (!(yield Auth.isLoggedIn())) {
243
251
  return console.error(`\nPlease log in first to access your lists.`);
244
252
  }
245
- const userId = yield Auth.MyUserId();
246
- if (!userId) {
253
+ if (!(yield Auth.MyUserId())) {
247
254
  return console.log(`\nFailed getting current user Id.`);
248
255
  }
249
- const request = yield fetch(aniListEndpoint, {
250
- method: "POST",
251
- headers: {
252
- "content-type": "application/json",
253
- "Authorization": `Bearer ${yield Auth.RetriveAccessToken()}`,
254
- },
255
- body: JSON.stringify({
256
- query: currentUserAnimeList,
257
- variables: { id: userId },
258
- }),
259
- });
260
- const { data, errors } = yield request.json();
261
- if (request.status !== 200 || errors) {
262
- return console.log(`\nSomething went wrong. ${(_a = errors === null || errors === void 0 ? void 0 : errors[0]) === null || _a === void 0 ? void 0 : _a.message}`);
256
+ const data = yield fetcher(currentUserAnimeList, { id: yield Auth.MyUserId() });
257
+ if (data === null || data === void 0 ? void 0 : data.errors) {
258
+ return console.log(`\nSomething went wrong. ${(_b = (_a = data === null || data === void 0 ? void 0 : data.errors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message}`);
263
259
  }
264
- const lists = (_b = data === null || data === void 0 ? void 0 : data.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists;
260
+ const lists = (_d = (_c = data === null || data === void 0 ? void 0 : data.data) === null || _c === void 0 ? void 0 : _c.MediaListCollection) === null || _d === void 0 ? void 0 : _d.lists;
265
261
  if (!lists || lists.length === 0) {
266
262
  return console.log(`\nYou seem to have no anime(s) in your lists.`);
267
263
  }
@@ -304,11 +300,12 @@ class AniList {
304
300
  ],
305
301
  },
306
302
  ]);
307
- const query = addAnimeToListMutation;
308
- const variables = { mediaId: selectedAnime, status: selectedListType };
309
- const saveResponse = yield fetcher(query, variables);
303
+ const saveResponse = yield fetcher(addAnimeToListMutation, {
304
+ mediaId: selectedAnime,
305
+ status: selectedListType,
306
+ });
310
307
  if (saveResponse) {
311
- const savedEntry = (_c = saveResponse.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
308
+ const savedEntry = (_e = saveResponse.data) === null || _e === void 0 ? void 0 : _e.SaveMediaListEntry;
312
309
  console.log(`\nEntry ${savedEntry === null || savedEntry === void 0 ? void 0 : savedEntry.id}. Saved as ${savedEntry === null || savedEntry === void 0 ? void 0 : savedEntry.status}.`);
313
310
  }
314
311
  else {
@@ -322,7 +319,7 @@ class AniList {
322
319
  }
323
320
  static MyManga() {
324
321
  return __awaiter(this, void 0, void 0, function* () {
325
- var _a, _b, _c, _d, _e;
322
+ var _a, _b, _c, _d, _e, _f, _g;
326
323
  try {
327
324
  if (!(yield Auth.isLoggedIn())) {
328
325
  return console.error(`\nPlease log in first to access your lists.`);
@@ -331,23 +328,11 @@ class AniList {
331
328
  if (!userId) {
332
329
  return console.error(`\nFailed to get the current user ID.`);
333
330
  }
334
- const token = yield Auth.RetriveAccessToken();
335
- const request = yield fetch(aniListEndpoint, {
336
- method: "POST",
337
- headers: {
338
- "Content-Type": "application/json",
339
- "Authorization": `Bearer ${token}`,
340
- },
341
- body: JSON.stringify({
342
- query: currentUserMangaList,
343
- variables: { id: userId },
344
- }),
345
- });
346
- const { data, errors } = yield request.json();
347
- if (request.status !== 200 || errors) {
348
- return console.error(`\nFailed to fetch manga lists. ${((_a = errors === null || errors === void 0 ? void 0 : errors[0]) === null || _a === void 0 ? void 0 : _a.message) || "Unknown error"}`);
331
+ const response = yield fetcher(currentUserMangaList, { id: userId });
332
+ if (!(response === null || response === void 0 ? void 0 : response.data)) {
333
+ return console.error(`\nFailed to fetch manga lists. ${((_b = (_a = response === null || response === void 0 ? void 0 : response.errors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message) || "Unknown error"}`);
349
334
  }
350
- const lists = (_b = data === null || data === void 0 ? void 0 : data.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists;
335
+ const lists = (_d = (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.MediaListCollection) === null || _d === void 0 ? void 0 : _d.lists;
351
336
  if (!lists || lists.length === 0) {
352
337
  return console.log("\nYou don't seem to have any manga in your lists.");
353
338
  }
@@ -393,24 +378,16 @@ class AniList {
393
378
  ],
394
379
  },
395
380
  ]);
396
- const saveRequest = yield fetch(aniListEndpoint, {
397
- method: "POST",
398
- headers: {
399
- "Content-Type": "application/json",
400
- "Authorization": `Bearer ${token}`,
401
- },
402
- body: JSON.stringify({
403
- query: addMangaToListMutation,
404
- variables: { mediaId: selectedManga, status: selectedListType },
405
- }),
381
+ const saveResponse = yield fetcher(addMangaToListMutation, {
382
+ mediaId: selectedManga,
383
+ status: selectedListType,
406
384
  });
407
- const saveResponse = yield saveRequest.json();
408
- const saved = (_c = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
385
+ const saved = (_e = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _e === void 0 ? void 0 : _e.SaveMediaListEntry;
409
386
  if (saved) {
410
387
  console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
411
388
  }
412
389
  else {
413
- console.error(`\nFailed to save the manga. ${((_e = (_d = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.errors) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.message) || "Unknown error"}`);
390
+ console.error(`\nFailed to save the manga. ${((_g = (_f = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.errors) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.message) || "Unknown error"}`);
414
391
  }
415
392
  }
416
393
  catch (error) {
@@ -420,63 +397,70 @@ class AniList {
420
397
  }
421
398
  static getTrendingAnime(count) {
422
399
  return __awaiter(this, void 0, void 0, function* () {
423
- var _a, _b, _c, _d, _e;
400
+ var _a, _b, _c, _d, _e, _f, _g;
424
401
  try {
425
- const request = yield fetch(aniListEndpoint, {
426
- method: "POST",
427
- headers: {
428
- "Content-Type": "application/json",
429
- },
430
- body: JSON.stringify({
431
- query: trendingQuery,
432
- variables: { page: 1, perPage: count },
433
- }),
434
- });
435
- const { data, errors } = yield request.json();
436
- if (request.status !== 200 || errors) {
437
- return console.log(`\nSomething went wrong. ${((_a = errors === null || errors === void 0 ? void 0 : errors[0]) === null || _a === void 0 ? void 0 : _a.message) || "Unknown error"}`);
438
- }
439
- const media = (_b = data === null || data === void 0 ? void 0 : data.Page) === null || _b === void 0 ? void 0 : _b.media;
440
- if (!media || media.length === 0) {
441
- return console.log(`\nNo trending available at the moment.`);
442
- }
443
- const { selectedAnime } = yield inquirer.prompt([
444
- {
445
- type: "list",
446
- name: "selectedAnime",
447
- message: "Select anime to add to the list:",
448
- choices: media.map((anime, idx) => ({
449
- name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
450
- value: anime === null || anime === void 0 ? void 0 : anime.id,
451
- })),
452
- pageSize: 10,
453
- },
454
- ]);
455
- const { selectedListType } = yield inquirer.prompt([
456
- {
457
- type: "list",
458
- name: "selectedListType",
459
- message: "Select the list where you want to save this anime:",
460
- choices: [
461
- { name: "Planning", value: "PLANNING" },
462
- { name: "Watching", value: "CURRENT" },
463
- { name: "Completed", value: "COMPLETED" },
464
- { name: "Paused", value: "PAUSED" },
465
- { name: "Dropped", value: "DROPPED" },
466
- ],
467
- },
468
- ]);
469
- if (!(yield Auth.isLoggedIn())) {
470
- return console.error(`\nPlease log in first to use this feature.`);
471
- }
472
- const variables = { mediaId: selectedAnime, status: selectedListType };
473
- const saveResponse = yield fetcher(addAnimeToListMutation, variables);
474
- const saved = (_c = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
475
- if (saved) {
476
- console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
477
- }
478
- else {
479
- console.error(`\nFailed to save the anime. ${((_e = (_d = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.errors) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.message) || "Unknown error"}`);
402
+ let page = 1;
403
+ let allTrending = [];
404
+ while (true) {
405
+ const response = yield fetcher(trendingQuery, { page, perPage: count });
406
+ if (response === null || response === void 0 ? void 0 : response.errors) {
407
+ console.error(`\nSomething went wrong. ${((_b = (_a = response === null || response === void 0 ? void 0 : response.errors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message) || "Unknown error"}`);
408
+ return;
409
+ }
410
+ const media = (_d = (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.Page) === null || _d === void 0 ? void 0 : _d.media;
411
+ if (!media || media.length === 0) {
412
+ console.log(`\nNo more trending anime available.`);
413
+ break;
414
+ }
415
+ allTrending = [...allTrending, ...media];
416
+ const choices = allTrending.map((anime, idx) => ({
417
+ name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
418
+ value: String(anime === null || anime === void 0 ? void 0 : anime.id),
419
+ }));
420
+ choices.push({ name: "See more", value: "see_more" });
421
+ const { selectedAnime } = yield inquirer.prompt([
422
+ {
423
+ type: "list",
424
+ name: "selectedAnime",
425
+ message: "Select anime to add to the list:",
426
+ choices,
427
+ pageSize: choices.length + 1,
428
+ },
429
+ ]);
430
+ if (selectedAnime === "see_more") {
431
+ page++;
432
+ continue;
433
+ }
434
+ else {
435
+ const { selectedListType } = yield inquirer.prompt([
436
+ {
437
+ type: "list",
438
+ name: "selectedListType",
439
+ message: "Select the list where you want to save this anime:",
440
+ choices: [
441
+ { name: "Planning", value: "PLANNING" },
442
+ { name: "Watching", value: "CURRENT" },
443
+ { name: "Completed", value: "COMPLETED" },
444
+ { name: "Paused", value: "PAUSED" },
445
+ { name: "Dropped", value: "DROPPED" },
446
+ ],
447
+ },
448
+ ]);
449
+ if (!(yield Auth.isLoggedIn())) {
450
+ console.error(`\nPlease log in first to use this feature.`);
451
+ return;
452
+ }
453
+ const variables = { mediaId: selectedAnime, status: selectedListType };
454
+ const saveResponse = yield fetcher(addAnimeToListMutation, variables);
455
+ const saved = (_e = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _e === void 0 ? void 0 : _e.SaveMediaListEntry;
456
+ if (saved) {
457
+ console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
458
+ }
459
+ else {
460
+ console.error(`\nFailed to save the anime. ${((_g = (_f = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.errors) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.message) || "Unknown error"}`);
461
+ }
462
+ break;
463
+ }
480
464
  }
481
465
  }
482
466
  catch (error) {
@@ -486,63 +470,69 @@ class AniList {
486
470
  }
487
471
  static getPopularAnime(count) {
488
472
  return __awaiter(this, void 0, void 0, function* () {
489
- var _a, _b, _c, _d, _e;
473
+ var _a, _b, _c, _d, _e, _f, _g;
490
474
  try {
491
- const request = yield fetch(aniListEndpoint, {
492
- method: "POST",
493
- headers: {
494
- "Content-Type": "application/json",
495
- },
496
- body: JSON.stringify({
497
- query: popularQuery,
498
- variables: { page: 1, perPage: count },
499
- }),
500
- });
501
- const { data, errors } = yield request.json();
502
- if (request.status !== 200 || errors) {
503
- return console.log(`\nSomething went wrong. ${((_a = errors === null || errors === void 0 ? void 0 : errors[0]) === null || _a === void 0 ? void 0 : _a.message) || "Unknown error"}`);
504
- }
505
- const media = (_b = data === null || data === void 0 ? void 0 : data.Page) === null || _b === void 0 ? void 0 : _b.media;
506
- if (!media || media.length === 0) {
507
- return console.log(`\nNo popular anime available at the moment.`);
508
- }
509
- const { selectedAnime } = yield inquirer.prompt([
510
- {
511
- type: "list",
512
- name: "selectedAnime",
513
- message: "Select anime to add to the list:",
514
- choices: media.map((anime, idx) => ({
515
- name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
516
- value: anime === null || anime === void 0 ? void 0 : anime.id,
517
- })),
518
- pageSize: 10,
519
- },
520
- ]);
521
- const { selectedListType } = yield inquirer.prompt([
522
- {
523
- type: "list",
524
- name: "selectedListType",
525
- message: "Select the list where you want to save this anime:",
526
- choices: [
527
- { name: "Planning", value: "PLANNING" },
528
- { name: "Watching", value: "CURRENT" },
529
- { name: "Completed", value: "COMPLETED" },
530
- { name: "Paused", value: "PAUSED" },
531
- { name: "Dropped", value: "DROPPED" },
532
- ],
533
- },
534
- ]);
535
- if (!(yield Auth.isLoggedIn())) {
536
- return console.error(`\nPlease log in first to use this feature.`);
537
- }
538
- const variables = { mediaId: selectedAnime, status: selectedListType };
539
- const saveResponse = yield fetcher(addAnimeToListMutation, variables);
540
- const saved = (_c = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
541
- if (saved) {
542
- console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
543
- }
544
- else {
545
- console.error(`\nFailed to save the anime. ${((_e = (_d = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.errors) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.message) || "Unknown error"}`);
475
+ let page = 1;
476
+ let allMedia = [];
477
+ while (true) {
478
+ const response = yield fetcher(popularQuery, { page, perPage: count });
479
+ if (!(response === null || response === void 0 ? void 0 : response.data)) {
480
+ console.error(`\nSomething went wrong. ${((_b = (_a = response === null || response === void 0 ? void 0 : response.errors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message) || "Unknown error"}`);
481
+ return;
482
+ }
483
+ const newMedia = (_d = (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.Page) === null || _d === void 0 ? void 0 : _d.media;
484
+ if (!newMedia || newMedia.length === 0) {
485
+ console.log(`\nNo more popular anime available.`);
486
+ break;
487
+ }
488
+ allMedia = [...allMedia, ...newMedia];
489
+ const choices = allMedia.map((anime, idx) => ({
490
+ name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
491
+ value: String(anime === null || anime === void 0 ? void 0 : anime.id),
492
+ }));
493
+ choices.push({ name: "See more", value: "see_more" });
494
+ const { selectedAnime } = yield inquirer.prompt([
495
+ {
496
+ type: "list",
497
+ name: "selectedAnime",
498
+ message: "Select anime to add to the list:",
499
+ choices,
500
+ pageSize: choices.length,
501
+ },
502
+ ]);
503
+ if (selectedAnime === "see_more") {
504
+ page++;
505
+ continue;
506
+ }
507
+ else {
508
+ const { selectedListType } = yield inquirer.prompt([
509
+ {
510
+ type: "list",
511
+ name: "selectedListType",
512
+ message: "Select the list where you want to save this anime:",
513
+ choices: [
514
+ { name: "Planning", value: "PLANNING" },
515
+ { name: "Watching", value: "CURRENT" },
516
+ { name: "Completed", value: "COMPLETED" },
517
+ { name: "Paused", value: "PAUSED" },
518
+ { name: "Dropped", value: "DROPPED" },
519
+ ],
520
+ },
521
+ ]);
522
+ if (!(yield Auth.isLoggedIn())) {
523
+ return console.error(`\nPlease log in first to use this feature.`);
524
+ }
525
+ const variables = { mediaId: selectedAnime, status: selectedListType };
526
+ const saveResponse = yield fetcher(addAnimeToListMutation, variables);
527
+ const saved = (_e = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _e === void 0 ? void 0 : _e.SaveMediaListEntry;
528
+ if (saved) {
529
+ console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
530
+ }
531
+ else {
532
+ console.error(`\nFailed to save the anime. ${((_g = (_f = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.errors) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.message) || "Unknown error"}`);
533
+ }
534
+ break;
535
+ }
546
536
  }
547
537
  }
548
538
  catch (error) {
@@ -555,55 +545,72 @@ class AniList {
555
545
  var _a, _b, _c, _d, _e, _f;
556
546
  try {
557
547
  const { nextSeason, nextYear } = getNextSeasonAndYear();
558
- const request = yield fetcher(upcomingAnimesQuery, {
559
- nextSeason,
560
- nextYear,
561
- perPage: count,
562
- });
563
- if (!request || !request.data) {
564
- return console.error(`\nSomething went wrong. ${((_b = (_a = request === null || request === void 0 ? void 0 : request.errors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message) || "Unknown error"}`);
565
- }
566
- const upcoming = (_c = request.data.Page.media) !== null && _c !== void 0 ? _c : [];
567
- if (upcoming.length === 0) {
568
- return console.log(`\nNo upcoming anime available.`);
569
- }
570
- const { selectedAnime } = yield inquirer.prompt([
571
- {
572
- type: "list",
573
- name: "selectedAnime",
574
- message: "Select anime to add to the list:",
575
- choices: upcoming.map((anime, idx) => ({
576
- name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
577
- value: anime === null || anime === void 0 ? void 0 : anime.id,
578
- })),
579
- pageSize: 10,
580
- },
581
- ]);
582
- const { selectedListType } = yield inquirer.prompt([
583
- {
584
- type: "list",
585
- name: "selectedListType",
586
- message: "Select the list where you want to save this anime:",
587
- choices: [
588
- { name: "Planning", value: "PLANNING" },
589
- { name: "Watching", value: "CURRENT" },
590
- { name: "Completed", value: "COMPLETED" },
591
- { name: "Paused", value: "PAUSED" },
592
- { name: "Dropped", value: "DROPPED" },
593
- ],
594
- },
595
- ]);
596
- if (!(yield Auth.isLoggedIn())) {
597
- return console.error(`\nPlease log in first to use this feature.`);
598
- }
599
- const variables = { mediaId: selectedAnime, status: selectedListType };
600
- const saveResponse = yield fetcher(addAnimeToListMutation, variables);
601
- const saved = (_d = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _d === void 0 ? void 0 : _d.SaveMediaListEntry;
602
- if (saved) {
603
- console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
604
- }
605
- else {
606
- console.error(`\nFailed to save the anime. ${((_f = (_e = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.errors) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.message) || "Unknown error"}`);
548
+ let page = 1;
549
+ let allUpcoming = [];
550
+ while (true) {
551
+ const request = yield fetcher(upcomingAnimesQuery, {
552
+ nextSeason,
553
+ nextYear,
554
+ page,
555
+ perPage: count,
556
+ });
557
+ if (!request || !request.data) {
558
+ console.error(`\nSomething went wrong. ${((_b = (_a = request === null || request === void 0 ? void 0 : request.errors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message) || "Unknown error"}`);
559
+ return;
560
+ }
561
+ const newUpcoming = (_c = request.data.Page.media) !== null && _c !== void 0 ? _c : [];
562
+ if (newUpcoming.length === 0) {
563
+ console.log(`\nNo more upcoming anime available.`);
564
+ break;
565
+ }
566
+ allUpcoming = [...allUpcoming, ...newUpcoming];
567
+ const choices = allUpcoming.map((anime, idx) => ({
568
+ name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
569
+ value: String(anime === null || anime === void 0 ? void 0 : anime.id),
570
+ }));
571
+ choices.push({ name: "See more", value: "see_more" });
572
+ const { selectedAnime } = yield inquirer.prompt([
573
+ {
574
+ type: "list",
575
+ name: "selectedAnime",
576
+ message: "Select anime to add to the list:",
577
+ choices,
578
+ pageSize: choices.length + 2,
579
+ },
580
+ ]);
581
+ if (selectedAnime === "see_more") {
582
+ page++;
583
+ continue;
584
+ }
585
+ else {
586
+ const { selectedListType } = yield inquirer.prompt([
587
+ {
588
+ type: "list",
589
+ name: "selectedListType",
590
+ message: "Select the list where you want to save this anime:",
591
+ choices: [
592
+ { name: "Planning", value: "PLANNING" },
593
+ { name: "Watching", value: "CURRENT" },
594
+ { name: "Completed", value: "COMPLETED" },
595
+ { name: "Paused", value: "PAUSED" },
596
+ { name: "Dropped", value: "DROPPED" },
597
+ ],
598
+ },
599
+ ]);
600
+ if (!(yield Auth.isLoggedIn())) {
601
+ return console.error(`\nPlease log in first to use this feature.`);
602
+ }
603
+ const variables = { mediaId: selectedAnime, status: selectedListType };
604
+ const saveResponse = yield fetcher(addAnimeToListMutation, variables);
605
+ const saved = (_d = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _d === void 0 ? void 0 : _d.SaveMediaListEntry;
606
+ if (saved) {
607
+ console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
608
+ }
609
+ else {
610
+ console.error(`\nFailed to save the anime. ${((_f = (_e = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.errors) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.message) || "Unknown error"}`);
611
+ }
612
+ break;
613
+ }
607
614
  }
608
615
  }
609
616
  catch (error) {
@@ -613,22 +620,11 @@ class AniList {
613
620
  }
614
621
  static getUserByUsername(username) {
615
622
  return __awaiter(this, void 0, void 0, function* () {
616
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
623
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2;
617
624
  try {
618
- const headers = {
619
- "Content-Type": "application/json",
620
- };
621
- if (yield Auth.isLoggedIn()) {
622
- headers["Authorization"] = `Bearer ${yield Auth.RetriveAccessToken()}`;
623
- }
624
- const request = yield fetch(aniListEndpoint, {
625
- method: "POST",
626
- headers,
627
- body: JSON.stringify({ query: userQuery, variables: { username } }),
628
- });
629
- const response = yield request.json();
630
- if (request.status !== 200 || !((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.User)) {
631
- return console.error(`\n${request.status} ${((_c = (_b = response === null || response === void 0 ? void 0 : response.errors) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.message) || "Unknown error"}`);
625
+ const response = yield fetcher(userQuery, { username });
626
+ if (!((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.User)) {
627
+ return console.error(`\n${((_c = (_b = response === null || response === void 0 ? void 0 : response.errors) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.message) || "Unknown error"}`);
632
628
  }
633
629
  const user = response.data.User;
634
630
  const userActivityResponse = yield fetcher(userActivityQuery, {
@@ -637,6 +633,15 @@ class AniList {
637
633
  perPage: 10,
638
634
  });
639
635
  const activities = (_f = (_e = (_d = userActivityResponse === null || userActivityResponse === void 0 ? void 0 : userActivityResponse.data) === null || _d === void 0 ? void 0 : _d.Page) === null || _e === void 0 ? void 0 : _e.activities) !== null && _f !== void 0 ? _f : [];
636
+ // Get follower/following information
637
+ const req_followers = yield fetcher(userFollowersQuery, {
638
+ userId: user === null || user === void 0 ? void 0 : user.id,
639
+ });
640
+ const req_following = yield fetcher(userFollowingQuery, {
641
+ userId: user === null || user === void 0 ? void 0 : user.id,
642
+ });
643
+ const followersCount = ((_j = (_h = (_g = req_followers === null || req_followers === void 0 ? void 0 : req_followers.data) === null || _g === void 0 ? void 0 : _g.Page) === null || _h === void 0 ? void 0 : _h.pageInfo) === null || _j === void 0 ? void 0 : _j.total) || 0;
644
+ const followingCount = ((_m = (_l = (_k = req_following === null || req_following === void 0 ? void 0 : req_following.data) === null || _k === void 0 ? void 0 : _k.Page) === null || _l === void 0 ? void 0 : _l.pageInfo) === null || _m === void 0 ? void 0 : _m.total) || 0;
640
645
  console.log(`\nID:\t\t${user.id}`);
641
646
  console.log(`Name:\t\t${user.name}`);
642
647
  console.log(`Site URL:\t${user.siteUrl}`);
@@ -647,14 +652,16 @@ class AniList {
647
652
  console.log(`Blocked:\t${user.isBlocked}`);
648
653
  console.log(`Follower:\t${user.isFollower}`);
649
654
  console.log(`Following:\t${user.isFollowing}`);
650
- console.log(`Profile Color:\t${(_g = user.options) === null || _g === void 0 ? void 0 : _g.profileColor}`);
651
- console.log(`Timezone:\t${(_h = user.options) === null || _h === void 0 ? void 0 : _h.timezone}`);
652
- console.log(`\nStatistics (Anime)\nCount: ${((_k = (_j = user.statistics) === null || _j === void 0 ? void 0 : _j.anime) === null || _k === void 0 ? void 0 : _k.count) || 0} Episodes Watched: ${((_m = (_l = user.statistics) === null || _l === void 0 ? void 0 : _l.anime) === null || _m === void 0 ? void 0 : _m.episodesWatched) || 0} Minutes Watched: ${((_p = (_o = user.statistics) === null || _o === void 0 ? void 0 : _o.anime) === null || _p === void 0 ? void 0 : _p.minutesWatched) || 0}`);
653
- console.log(`Statistics (Manga)\nCount: ${((_r = (_q = user.statistics) === null || _q === void 0 ? void 0 : _q.manga) === null || _r === void 0 ? void 0 : _r.count) || 0} Chapters Read: ${((_t = (_s = user.statistics) === null || _s === void 0 ? void 0 : _s.manga) === null || _t === void 0 ? void 0 : _t.chaptersRead) || 0} Volumes Read: ${((_v = (_u = user.statistics) === null || _u === void 0 ? void 0 : _u.manga) === null || _v === void 0 ? void 0 : _v.volumesRead) || 0}`);
655
+ console.log(`Profile Color:\t${(_o = user.options) === null || _o === void 0 ? void 0 : _o.profileColor}`);
656
+ console.log(`Timezone:\t${((_p = user.options) === null || _p === void 0 ? void 0 : _p.timezone) ? (_q = user.options) === null || _q === void 0 ? void 0 : _q.timezone : "N/A"}`);
657
+ console.log(`\nFollowers:\t${followersCount}`);
658
+ console.log(`Following:\t${followingCount}`);
659
+ console.log(`\nStatistics (Anime)\n\tCount: ${((_s = (_r = user.statistics) === null || _r === void 0 ? void 0 : _r.anime) === null || _s === void 0 ? void 0 : _s.count) || 0}\tEpisodes Watched: ${((_u = (_t = user.statistics) === null || _t === void 0 ? void 0 : _t.anime) === null || _u === void 0 ? void 0 : _u.episodesWatched) || 0}\tMinutes Watched: ${((_w = (_v = user.statistics) === null || _v === void 0 ? void 0 : _v.anime) === null || _w === void 0 ? void 0 : _w.minutesWatched) || 0}`);
660
+ console.log(`Statistics (Manga)\n\tCount: ${((_y = (_x = user.statistics) === null || _x === void 0 ? void 0 : _x.manga) === null || _y === void 0 ? void 0 : _y.count) || 0}\tChapters Read: ${((_0 = (_z = user.statistics) === null || _z === void 0 ? void 0 : _z.manga) === null || _0 === void 0 ? void 0 : _0.chaptersRead) || 0}\tVolumes Read: ${((_2 = (_1 = user.statistics) === null || _1 === void 0 ? void 0 : _1.manga) === null || _2 === void 0 ? void 0 : _2.volumesRead) || 0}`);
654
661
  if (activities.length > 0) {
655
662
  console.log(`\nRecent Activities:`);
656
- activities.forEach(({ status, progress, media }) => {
657
- console.log(`${status} ${progress ? `${progress} of ` : ""}${getTitle(media === null || media === void 0 ? void 0 : media.title)}`);
663
+ activities.forEach(({ status, progress, media, createdAt }) => {
664
+ console.log(`${timestampToTimeAgo(createdAt)}\t${status} ${progress ? `${progress} of ` : ""}${getTitle(media === null || media === void 0 ? void 0 : media.title)}`);
658
665
  });
659
666
  }
660
667
  else {
@@ -669,9 +676,9 @@ class AniList {
669
676
  static getAnimeDetailsByID(anilistID) {
670
677
  return __awaiter(this, void 0, void 0, function* () {
671
678
  var _a;
672
- const query = animeDetailsQuery;
673
- const variables = { id: anilistID };
674
- const details = yield fetcher(query, variables);
679
+ const details = yield fetcher(animeDetailsQuery, {
680
+ id: anilistID,
681
+ });
675
682
  if ((_a = details === null || details === void 0 ? void 0 : details.data) === null || _a === void 0 ? void 0 : _a.Media) {
676
683
  const { id, title, description, duration, startDate, endDate, countryOfOrigin, isAdult, status, season, format, genres, siteUrl, } = details.data.Media;
677
684
  console.log(`\nID: ${id}`);
@@ -693,9 +700,11 @@ class AniList {
693
700
  static searchAnime(search, count) {
694
701
  return __awaiter(this, void 0, void 0, function* () {
695
702
  var _a, _b, _c;
696
- const query = animeSearchQuery;
697
- const variables = { search, page: 1, perPage: count };
698
- const searchResults = yield fetcher(query, variables);
703
+ const searchResults = yield fetcher(animeSearchQuery, {
704
+ search,
705
+ page: 1,
706
+ perPage: count,
707
+ });
699
708
  if (searchResults) {
700
709
  const results = (_b = (_a = searchResults === null || searchResults === void 0 ? void 0 : searchResults.data) === null || _a === void 0 ? void 0 : _a.Page) === null || _b === void 0 ? void 0 : _b.media;
701
710
  if (results.length > 0) {
@@ -727,12 +736,10 @@ class AniList {
727
736
  ]);
728
737
  // Save selected anime to chosen list type
729
738
  if (yield Auth.isLoggedIn()) {
730
- const saveQuery = addAnimeToListMutation;
731
- const saveVariables = {
739
+ const response = yield fetcher(addAnimeToListMutation, {
732
740
  mediaId: selectedAnime,
733
741
  status: selectedListType,
734
- };
735
- const response = yield fetcher(saveQuery, saveVariables);
742
+ });
736
743
  if (response) {
737
744
  const saved = (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
738
745
  console.log(`\nEntry ${saved === null || saved === void 0 ? void 0 : saved.id}. Saved as ${saved === null || saved === void 0 ? void 0 : saved.status}.`);
@@ -754,9 +761,11 @@ class AniList {
754
761
  static searchManga(search, count) {
755
762
  return __awaiter(this, void 0, void 0, function* () {
756
763
  var _a, _b, _c;
757
- const query = mangaSearchQuery;
758
- const variables = { search, page: 1, perPage: count };
759
- const mangaSearchResult = yield fetcher(query, variables);
764
+ const mangaSearchResult = yield fetcher(mangaSearchQuery, {
765
+ search,
766
+ page: 1,
767
+ perPage: count,
768
+ });
760
769
  if (mangaSearchResult) {
761
770
  const results = (_b = (_a = mangaSearchResult === null || mangaSearchResult === void 0 ? void 0 : mangaSearchResult.data) === null || _a === void 0 ? void 0 : _a.Page) === null || _b === void 0 ? void 0 : _b.media;
762
771
  // List of manga search results
@@ -789,9 +798,10 @@ class AniList {
789
798
  ]);
790
799
  // If logged in save to the list
791
800
  if (yield Auth.isLoggedIn()) {
792
- const mutation = addMangaToListMutation;
793
- const variables = { mediaId: selectedMangaId, status: selectedListType };
794
- const response = yield fetcher(mutation, variables);
801
+ const response = yield fetcher(addMangaToListMutation, {
802
+ mediaId: selectedMangaId,
803
+ status: selectedListType,
804
+ });
795
805
  if (response) {
796
806
  const saved = (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
797
807
  console.log(`\nEntry ${saved === null || saved === void 0 ? void 0 : saved.id}. Saved as ${saved === null || saved === void 0 ? void 0 : saved.status}.`);
@@ -813,8 +823,15 @@ class MyAnimeList {
813
823
  var _a, _b, _c, _d, _e;
814
824
  try {
815
825
  const filename = yield selectFile(".xml");
826
+ if (!filename) {
827
+ return;
828
+ }
816
829
  const filePath = join(getDownloadFolderPath(), filename);
817
830
  const fileContent = yield readFile(filePath, "utf8");
831
+ if (!(yield Validate.Import_AnimeXML(fileContent))) {
832
+ console.error(`\nInvalid XML file.`);
833
+ return;
834
+ }
818
835
  const parser = new XMLParser();
819
836
  if (fileContent) {
820
837
  const XMLObject = parser.parse(fileContent);
@@ -878,8 +895,15 @@ class MyAnimeList {
878
895
  var _a, _b, _c, _d, _e;
879
896
  try {
880
897
  const filename = yield selectFile(".xml");
898
+ if (!filename) {
899
+ return;
900
+ }
881
901
  const filePath = join(getDownloadFolderPath(), filename);
882
902
  const fileContent = yield readFile(filePath, "utf8");
903
+ if (!(yield Validate.Import_MangaXML(fileContent))) {
904
+ console.error(`\nInvalid XML file.`);
905
+ return;
906
+ }
883
907
  const parser = new XMLParser();
884
908
  if (fileContent) {
885
909
  const XMLObject = parser.parse(fileContent);
@@ -950,7 +974,7 @@ class MyAnimeList {
950
974
  if (((_b = (_a = animeList === null || animeList === void 0 ? void 0 : animeList.data) === null || _a === void 0 ? void 0 : _a.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists.length) > 0) {
951
975
  const lists = (_d = (_c = animeList === null || animeList === void 0 ? void 0 : animeList.data) === null || _c === void 0 ? void 0 : _c.MediaListCollection) === null || _d === void 0 ? void 0 : _d.lists;
952
976
  const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
953
- var _a, _b, _c, _d, _e;
977
+ var _a, _b, _c, _d, _e, _f;
954
978
  return ({
955
979
  id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
956
980
  malId: (_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.idMal,
@@ -960,13 +984,10 @@ class MyAnimeList {
960
984
  progress: entry.progress,
961
985
  status: entry === null || entry === void 0 ? void 0 : entry.status,
962
986
  hiddenFromStatusLists: false,
987
+ format: (_f = entry === null || entry === void 0 ? void 0 : entry.media) === null || _f === void 0 ? void 0 : _f.format,
963
988
  });
964
989
  }));
965
- const xmlContent = createAnimeListXML(mediaWithProgress);
966
- const path = join(getDownloadFolderPath(), `${yield Auth.MyUserName()}@irfanshadikrishad-anilist-myanimelist(anime)-${getFormattedDate()}.xml`);
967
- yield writeFile(path, yield xmlContent, "utf8");
968
- console.log(`Generated XML for MyAnimeList.`);
969
- open(getDownloadFolderPath());
990
+ yield saveJSONasXML(mediaWithProgress, 0);
970
991
  }
971
992
  else {
972
993
  console.log(`\nHey, ${yield Auth.MyUserName()}. Your anime list seems to be empty.`);
@@ -991,24 +1012,17 @@ class MyAnimeList {
991
1012
  });
992
1013
  if (mangaList && ((_b = (_a = mangaList === null || mangaList === void 0 ? void 0 : mangaList.data) === null || _a === void 0 ? void 0 : _a.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists.length) > 0) {
993
1014
  const lists = (_d = (_c = mangaList === null || mangaList === void 0 ? void 0 : mangaList.data) === null || _c === void 0 ? void 0 : _c.MediaListCollection) === null || _d === void 0 ? void 0 : _d.lists;
994
- const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
995
- var _a, _b, _c;
996
- return ({
997
- id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
998
- malId: (_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.idMal,
999
- title: (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title,
1000
- private: entry.private,
1001
- chapters: entry.media.chapters,
1002
- progress: entry.progress,
1003
- status: entry === null || entry === void 0 ? void 0 : entry.status,
1004
- hiddenFromStatusLists: entry.hiddenFromStatusLists,
1005
- });
1006
- }));
1007
- const XMLContent = createMangaListXML(mediaWithProgress);
1008
- const path = join(getDownloadFolderPath(), `${yield Auth.MyUserName()}@irfanshadikrishad-anilist-myanimelist(manga)-${getFormattedDate()}.xml`);
1009
- yield writeFile(path, yield XMLContent, "utf8");
1010
- console.log(`Generated XML for MyAnimeList.`);
1011
- open(getDownloadFolderPath());
1015
+ const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => ({
1016
+ id: entry.media.id,
1017
+ malId: entry.media.idMal,
1018
+ title: entry.media.title,
1019
+ private: entry.private,
1020
+ chapters: entry.media.chapters,
1021
+ progress: entry.progress,
1022
+ status: entry.status,
1023
+ hiddenFromStatusLists: entry.hiddenFromStatusLists,
1024
+ })));
1025
+ yield saveJSONasXML(mediaWithProgress, 1);
1012
1026
  }
1013
1027
  else {
1014
1028
  console.log(`\nHey, ${yield Auth.MyUserName()}. Your anime list seems to be empty.`);
@@ -1020,4 +1034,99 @@ class MyAnimeList {
1020
1034
  });
1021
1035
  }
1022
1036
  }
1023
- export { AniList, MyAnimeList };
1037
+ class AniDB {
1038
+ static importAnime() {
1039
+ return __awaiter(this, void 0, void 0, function* () {
1040
+ var _a, _b;
1041
+ try {
1042
+ const filename = yield selectFile(".json");
1043
+ if (!filename) {
1044
+ return;
1045
+ }
1046
+ const filePath = join(getDownloadFolderPath(), filename);
1047
+ const fileContent = yield readFile(filePath, "utf8");
1048
+ const js0n_repaired = jsonrepair(fileContent);
1049
+ if (!(yield Validate.Import_AniDBJSONLarge(js0n_repaired))) {
1050
+ console.error(`\nInvalid JSON Large file.`);
1051
+ return;
1052
+ }
1053
+ if (js0n_repaired) {
1054
+ const obj3ct = yield JSON.parse(js0n_repaired);
1055
+ const animeList = obj3ct === null || obj3ct === void 0 ? void 0 : obj3ct.anime;
1056
+ if ((animeList === null || animeList === void 0 ? void 0 : animeList.length) > 0) {
1057
+ let count = 0;
1058
+ let iteration = 0;
1059
+ let missed = [];
1060
+ for (const anime of animeList) {
1061
+ iteration++;
1062
+ const anidbId = anime.id;
1063
+ const released = anime.broadcastDate; // DD-MM-YYYY (eg: "23.07.2016")
1064
+ const status = anime.status;
1065
+ // const type = anime.type
1066
+ const totalEpisodes = anime.totalEpisodes;
1067
+ const ownEpisodes = anime.ownEpisodes;
1068
+ const romanjiName = anime.romanjiName;
1069
+ const englishName = anime.englishName;
1070
+ function getStatus(anidbStatus, episodesSeen) {
1071
+ if (anidbStatus === "complete") {
1072
+ return AniListMediaStatus.COMPLETED;
1073
+ }
1074
+ else if (anidbStatus === "incomplete" &&
1075
+ Number(episodesSeen) > 0) {
1076
+ return AniListMediaStatus.CURRENT;
1077
+ }
1078
+ else {
1079
+ return AniListMediaStatus.PLANNING;
1080
+ }
1081
+ }
1082
+ let anilistId = yield anidbToanilistMapper(romanjiName, Number(released.split(".")[2]), englishName);
1083
+ if (anilistId) {
1084
+ try {
1085
+ const saveResponse = yield fetcher(saveAnimeWithProgressMutation, {
1086
+ mediaId: anilistId,
1087
+ progress: ownEpisodes - 2,
1088
+ status: getStatus(status, ownEpisodes),
1089
+ hiddenFromStatusLists: false,
1090
+ private: false,
1091
+ });
1092
+ const entryId = (_b = (_a = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _a === void 0 ? void 0 : _a.SaveMediaListEntry) === null || _b === void 0 ? void 0 : _b.id;
1093
+ if (entryId) {
1094
+ count++;
1095
+ console.log(`[${count}]\t${entryId} ✅\t${anidbId}\t${anilistId}\t(${ownEpisodes}/${totalEpisodes})\t${status}–>${getStatus(status, ownEpisodes)}`);
1096
+ }
1097
+ // Rate limit each API call to avoid server overload
1098
+ // await new Promise((resolve) => setTimeout(resolve, 1100))
1099
+ }
1100
+ catch (error) {
1101
+ console.error(`Error processing AniDB ID ${anidbId}: ${error.message}`);
1102
+ }
1103
+ }
1104
+ else {
1105
+ missed.push({
1106
+ anidbId: anidbId,
1107
+ englishTitle: englishName,
1108
+ romajiTitle: romanjiName,
1109
+ });
1110
+ }
1111
+ }
1112
+ console.log(`\nAccuracy: ${(((animeList.length - missed.length) / animeList.length) * 100).toFixed(2)}%\tTotal Processed: ${iteration}\tMissed: ${missed.length}`);
1113
+ if (missed.length > 0) {
1114
+ console.log(`Exporting missed entries to JSON file, Please add them manually.`);
1115
+ yield saveJSONasJSON(missed, "anidb-missed");
1116
+ }
1117
+ }
1118
+ else {
1119
+ console.log(`\nNo anime list found in the file.`);
1120
+ }
1121
+ }
1122
+ else {
1123
+ console.log(`\nNo content found in the file or unable to read.`);
1124
+ }
1125
+ }
1126
+ catch (error) {
1127
+ console.error(`\nError in AniDB import process: ${error.message}`);
1128
+ }
1129
+ });
1130
+ }
1131
+ }
1132
+ export { AniDB, AniList, MyAnimeList };