@irfanshadikrishad/anilist 1.0.0-forbidden.1 → 1.0.0-forbidden.2

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.
@@ -10,14 +10,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { XMLParser } from "fast-xml-parser";
11
11
  import { readFile, writeFile } from "fs/promises";
12
12
  import inquirer from "inquirer";
13
- import fetch from "node-fetch";
13
+ import { jsonrepair } from "jsonrepair";
14
+ import open from "open";
14
15
  import { join } from "path";
15
16
  import { Auth } from "./auth.js";
16
17
  import { fetcher } from "./fetcher.js";
17
18
  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";
19
+ import { animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, } from "./queries.js";
19
20
  import { AniListMediaStatus, } from "./types.js";
20
- import { aniListEndpoint, createAnimeListXML, createMangaListXML, formatDateObject, getDownloadFolderPath, getFormattedDate, getNextSeasonAndYear, getTitle, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, selectFile, } from "./workers.js";
21
+ import { anidbToanilistMapper, createAnimeListXML, createMangaListXML, formatDateObject, getDownloadFolderPath, getFormattedDate, getNextSeasonAndYear, getTitle, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, selectFile, timestampToTimeAgo, } from "./workers.js";
21
22
  class AniList {
22
23
  static importAnime() {
23
24
  return __awaiter(this, void 0, void 0, function* () {
@@ -45,7 +46,7 @@ class AniList {
45
46
  if (save) {
46
47
  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
48
  count++;
48
- console.log(`[${count}] ${anime === null || anime === void 0 ? void 0 : anime.id}-${id} ✅`);
49
+ console.log(`[${count}]\t${id}\t${anime === null || anime === void 0 ? void 0 : anime.id} ✅`);
49
50
  }
50
51
  else {
51
52
  console.error(`\nError saving ${anime === null || anime === void 0 ? void 0 : anime.id}`);
@@ -93,7 +94,7 @@ class AniList {
93
94
  if (save) {
94
95
  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
96
  count++;
96
- console.log(`[${count}] ${manga === null || manga === void 0 ? void 0 : manga.id}-${id} ✅`);
97
+ console.log(`[${count}]\t${id}\t${manga === null || manga === void 0 ? void 0 : manga.id} ✅`);
97
98
  }
98
99
  }
99
100
  catch (err) {
@@ -122,7 +123,7 @@ class AniList {
122
123
  choices: [
123
124
  { name: "CSV", value: 1 },
124
125
  { name: "JSON", value: 2 },
125
- { name: "XML (MyAnimeList)", value: 3 },
126
+ { name: "XML (MyAnimeList/AniDB)", value: 3 },
126
127
  ],
127
128
  pageSize: 10,
128
129
  },
@@ -237,7 +238,7 @@ class AniList {
237
238
  }
238
239
  static MyAnime() {
239
240
  return __awaiter(this, void 0, void 0, function* () {
240
- var _a, _b, _c;
241
+ var _a, _b, _c, _d, _e;
241
242
  try {
242
243
  if (!(yield Auth.isLoggedIn())) {
243
244
  return console.error(`\nPlease log in first to access your lists.`);
@@ -246,22 +247,11 @@ class AniList {
246
247
  if (!userId) {
247
248
  return console.log(`\nFailed getting current user Id.`);
248
249
  }
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}`);
250
+ const data = yield fetcher(currentUserAnimeList, { id: userId });
251
+ if (data === null || data === void 0 ? void 0 : data.errors) {
252
+ 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
253
  }
264
- const lists = (_b = data === null || data === void 0 ? void 0 : data.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists;
254
+ 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
255
  if (!lists || lists.length === 0) {
266
256
  return console.log(`\nYou seem to have no anime(s) in your lists.`);
267
257
  }
@@ -304,11 +294,12 @@ class AniList {
304
294
  ],
305
295
  },
306
296
  ]);
307
- const query = addAnimeToListMutation;
308
- const variables = { mediaId: selectedAnime, status: selectedListType };
309
- const saveResponse = yield fetcher(query, variables);
297
+ const saveResponse = yield fetcher(addAnimeToListMutation, {
298
+ mediaId: selectedAnime,
299
+ status: selectedListType,
300
+ });
310
301
  if (saveResponse) {
311
- const savedEntry = (_c = saveResponse.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
302
+ const savedEntry = (_e = saveResponse.data) === null || _e === void 0 ? void 0 : _e.SaveMediaListEntry;
312
303
  console.log(`\nEntry ${savedEntry === null || savedEntry === void 0 ? void 0 : savedEntry.id}. Saved as ${savedEntry === null || savedEntry === void 0 ? void 0 : savedEntry.status}.`);
313
304
  }
314
305
  else {
@@ -322,7 +313,7 @@ class AniList {
322
313
  }
323
314
  static MyManga() {
324
315
  return __awaiter(this, void 0, void 0, function* () {
325
- var _a, _b, _c, _d, _e;
316
+ var _a, _b, _c, _d, _e, _f, _g;
326
317
  try {
327
318
  if (!(yield Auth.isLoggedIn())) {
328
319
  return console.error(`\nPlease log in first to access your lists.`);
@@ -331,23 +322,11 @@ class AniList {
331
322
  if (!userId) {
332
323
  return console.error(`\nFailed to get the current user ID.`);
333
324
  }
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"}`);
325
+ const response = yield fetcher(currentUserMangaList, { id: userId });
326
+ if (!(response === null || response === void 0 ? void 0 : response.data)) {
327
+ 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
328
  }
350
- const lists = (_b = data === null || data === void 0 ? void 0 : data.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists;
329
+ 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
330
  if (!lists || lists.length === 0) {
352
331
  return console.log("\nYou don't seem to have any manga in your lists.");
353
332
  }
@@ -393,24 +372,16 @@ class AniList {
393
372
  ],
394
373
  },
395
374
  ]);
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
- }),
375
+ const saveResponse = yield fetcher(addMangaToListMutation, {
376
+ mediaId: selectedManga,
377
+ status: selectedListType,
406
378
  });
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;
379
+ const saved = (_e = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _e === void 0 ? void 0 : _e.SaveMediaListEntry;
409
380
  if (saved) {
410
381
  console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
411
382
  }
412
383
  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"}`);
384
+ 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
385
  }
415
386
  }
416
387
  catch (error) {
@@ -420,63 +391,70 @@ class AniList {
420
391
  }
421
392
  static getTrendingAnime(count) {
422
393
  return __awaiter(this, void 0, void 0, function* () {
423
- var _a, _b, _c, _d, _e;
394
+ var _a, _b, _c, _d, _e, _f, _g;
424
395
  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"}`);
396
+ let page = 1;
397
+ let allTrending = [];
398
+ while (true) {
399
+ const response = yield fetcher(trendingQuery, { page, perPage: count });
400
+ if (response === null || response === void 0 ? void 0 : response.errors) {
401
+ 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"}`);
402
+ return;
403
+ }
404
+ 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;
405
+ if (!media || media.length === 0) {
406
+ console.log(`\nNo more trending anime available.`);
407
+ break;
408
+ }
409
+ allTrending = [...allTrending, ...media];
410
+ const choices = allTrending.map((anime, idx) => ({
411
+ name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
412
+ value: String(anime === null || anime === void 0 ? void 0 : anime.id),
413
+ }));
414
+ choices.push({ name: "See more", value: "see_more" });
415
+ const { selectedAnime } = yield inquirer.prompt([
416
+ {
417
+ type: "list",
418
+ name: "selectedAnime",
419
+ message: "Select anime to add to the list:",
420
+ choices,
421
+ pageSize: choices.length + 1,
422
+ },
423
+ ]);
424
+ if (selectedAnime === "see_more") {
425
+ page++;
426
+ continue;
427
+ }
428
+ else {
429
+ const { selectedListType } = yield inquirer.prompt([
430
+ {
431
+ type: "list",
432
+ name: "selectedListType",
433
+ message: "Select the list where you want to save this anime:",
434
+ choices: [
435
+ { name: "Planning", value: "PLANNING" },
436
+ { name: "Watching", value: "CURRENT" },
437
+ { name: "Completed", value: "COMPLETED" },
438
+ { name: "Paused", value: "PAUSED" },
439
+ { name: "Dropped", value: "DROPPED" },
440
+ ],
441
+ },
442
+ ]);
443
+ if (!(yield Auth.isLoggedIn())) {
444
+ console.error(`\nPlease log in first to use this feature.`);
445
+ return;
446
+ }
447
+ const variables = { mediaId: selectedAnime, status: selectedListType };
448
+ const saveResponse = yield fetcher(addAnimeToListMutation, variables);
449
+ const saved = (_e = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _e === void 0 ? void 0 : _e.SaveMediaListEntry;
450
+ if (saved) {
451
+ console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
452
+ }
453
+ else {
454
+ 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"}`);
455
+ }
456
+ break;
457
+ }
480
458
  }
481
459
  }
482
460
  catch (error) {
@@ -486,63 +464,69 @@ class AniList {
486
464
  }
487
465
  static getPopularAnime(count) {
488
466
  return __awaiter(this, void 0, void 0, function* () {
489
- var _a, _b, _c, _d, _e;
467
+ var _a, _b, _c, _d, _e, _f, _g;
490
468
  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"}`);
469
+ let page = 1;
470
+ let allMedia = [];
471
+ while (true) {
472
+ const response = yield fetcher(popularQuery, { page, perPage: count });
473
+ if (!(response === null || response === void 0 ? void 0 : response.data)) {
474
+ 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"}`);
475
+ return;
476
+ }
477
+ 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;
478
+ if (!newMedia || newMedia.length === 0) {
479
+ console.log(`\nNo more popular anime available.`);
480
+ break;
481
+ }
482
+ allMedia = [...allMedia, ...newMedia];
483
+ const choices = allMedia.map((anime, idx) => ({
484
+ name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
485
+ value: String(anime === null || anime === void 0 ? void 0 : anime.id),
486
+ }));
487
+ choices.push({ name: "See more", value: "see_more" });
488
+ const { selectedAnime } = yield inquirer.prompt([
489
+ {
490
+ type: "list",
491
+ name: "selectedAnime",
492
+ message: "Select anime to add to the list:",
493
+ choices,
494
+ pageSize: choices.length,
495
+ },
496
+ ]);
497
+ if (selectedAnime === "see_more") {
498
+ page++;
499
+ continue;
500
+ }
501
+ else {
502
+ const { selectedListType } = yield inquirer.prompt([
503
+ {
504
+ type: "list",
505
+ name: "selectedListType",
506
+ message: "Select the list where you want to save this anime:",
507
+ choices: [
508
+ { name: "Planning", value: "PLANNING" },
509
+ { name: "Watching", value: "CURRENT" },
510
+ { name: "Completed", value: "COMPLETED" },
511
+ { name: "Paused", value: "PAUSED" },
512
+ { name: "Dropped", value: "DROPPED" },
513
+ ],
514
+ },
515
+ ]);
516
+ if (!(yield Auth.isLoggedIn())) {
517
+ return console.error(`\nPlease log in first to use this feature.`);
518
+ }
519
+ const variables = { mediaId: selectedAnime, status: selectedListType };
520
+ const saveResponse = yield fetcher(addAnimeToListMutation, variables);
521
+ const saved = (_e = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _e === void 0 ? void 0 : _e.SaveMediaListEntry;
522
+ if (saved) {
523
+ console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
524
+ }
525
+ else {
526
+ 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"}`);
527
+ }
528
+ break;
529
+ }
546
530
  }
547
531
  }
548
532
  catch (error) {
@@ -555,55 +539,72 @@ class AniList {
555
539
  var _a, _b, _c, _d, _e, _f;
556
540
  try {
557
541
  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"}`);
542
+ let page = 1;
543
+ let allUpcoming = [];
544
+ while (true) {
545
+ const request = yield fetcher(upcomingAnimesQuery, {
546
+ nextSeason,
547
+ nextYear,
548
+ page,
549
+ perPage: count,
550
+ });
551
+ if (!request || !request.data) {
552
+ 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"}`);
553
+ return;
554
+ }
555
+ const newUpcoming = (_c = request.data.Page.media) !== null && _c !== void 0 ? _c : [];
556
+ if (newUpcoming.length === 0) {
557
+ console.log(`\nNo more upcoming anime available.`);
558
+ break;
559
+ }
560
+ allUpcoming = [...allUpcoming, ...newUpcoming];
561
+ const choices = allUpcoming.map((anime, idx) => ({
562
+ name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
563
+ value: String(anime === null || anime === void 0 ? void 0 : anime.id),
564
+ }));
565
+ choices.push({ name: "See more", value: "see_more" });
566
+ const { selectedAnime } = yield inquirer.prompt([
567
+ {
568
+ type: "list",
569
+ name: "selectedAnime",
570
+ message: "Select anime to add to the list:",
571
+ choices,
572
+ pageSize: choices.length + 2,
573
+ },
574
+ ]);
575
+ if (selectedAnime === "see_more") {
576
+ page++;
577
+ continue;
578
+ }
579
+ else {
580
+ const { selectedListType } = yield inquirer.prompt([
581
+ {
582
+ type: "list",
583
+ name: "selectedListType",
584
+ message: "Select the list where you want to save this anime:",
585
+ choices: [
586
+ { name: "Planning", value: "PLANNING" },
587
+ { name: "Watching", value: "CURRENT" },
588
+ { name: "Completed", value: "COMPLETED" },
589
+ { name: "Paused", value: "PAUSED" },
590
+ { name: "Dropped", value: "DROPPED" },
591
+ ],
592
+ },
593
+ ]);
594
+ if (!(yield Auth.isLoggedIn())) {
595
+ return console.error(`\nPlease log in first to use this feature.`);
596
+ }
597
+ const variables = { mediaId: selectedAnime, status: selectedListType };
598
+ const saveResponse = yield fetcher(addAnimeToListMutation, variables);
599
+ const saved = (_d = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _d === void 0 ? void 0 : _d.SaveMediaListEntry;
600
+ if (saved) {
601
+ console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
602
+ }
603
+ else {
604
+ 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"}`);
605
+ }
606
+ break;
607
+ }
607
608
  }
608
609
  }
609
610
  catch (error) {
@@ -613,22 +614,11 @@ class AniList {
613
614
  }
614
615
  static getUserByUsername(username) {
615
616
  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;
617
+ 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
618
  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"}`);
619
+ const response = yield fetcher(userQuery, { username });
620
+ if (!((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.User)) {
621
+ 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
622
  }
633
623
  const user = response.data.User;
634
624
  const userActivityResponse = yield fetcher(userActivityQuery, {
@@ -637,6 +627,15 @@ class AniList {
637
627
  perPage: 10,
638
628
  });
639
629
  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 : [];
630
+ // Get follower/following information
631
+ const req_followers = yield fetcher(userFollowersQuery, {
632
+ userId: user === null || user === void 0 ? void 0 : user.id,
633
+ });
634
+ const req_following = yield fetcher(userFollowingQuery, {
635
+ userId: user === null || user === void 0 ? void 0 : user.id,
636
+ });
637
+ 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;
638
+ 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
639
  console.log(`\nID:\t\t${user.id}`);
641
640
  console.log(`Name:\t\t${user.name}`);
642
641
  console.log(`Site URL:\t${user.siteUrl}`);
@@ -647,14 +646,16 @@ class AniList {
647
646
  console.log(`Blocked:\t${user.isBlocked}`);
648
647
  console.log(`Follower:\t${user.isFollower}`);
649
648
  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}`);
649
+ console.log(`Profile Color:\t${(_o = user.options) === null || _o === void 0 ? void 0 : _o.profileColor}`);
650
+ 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"}`);
651
+ console.log(`\nFollowers:\t${followersCount}`);
652
+ console.log(`Following:\t${followingCount}`);
653
+ 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}`);
654
+ 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
655
  if (activities.length > 0) {
655
656
  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)}`);
657
+ activities.forEach(({ status, progress, media, createdAt }) => {
658
+ console.log(`${timestampToTimeAgo(createdAt)}\t${status} ${progress ? `${progress} of ` : ""}${getTitle(media === null || media === void 0 ? void 0 : media.title)}`);
658
659
  });
659
660
  }
660
661
  else {
@@ -669,9 +670,9 @@ class AniList {
669
670
  static getAnimeDetailsByID(anilistID) {
670
671
  return __awaiter(this, void 0, void 0, function* () {
671
672
  var _a;
672
- const query = animeDetailsQuery;
673
- const variables = { id: anilistID };
674
- const details = yield fetcher(query, variables);
673
+ const details = yield fetcher(animeDetailsQuery, {
674
+ id: anilistID,
675
+ });
675
676
  if ((_a = details === null || details === void 0 ? void 0 : details.data) === null || _a === void 0 ? void 0 : _a.Media) {
676
677
  const { id, title, description, duration, startDate, endDate, countryOfOrigin, isAdult, status, season, format, genres, siteUrl, } = details.data.Media;
677
678
  console.log(`\nID: ${id}`);
@@ -693,9 +694,11 @@ class AniList {
693
694
  static searchAnime(search, count) {
694
695
  return __awaiter(this, void 0, void 0, function* () {
695
696
  var _a, _b, _c;
696
- const query = animeSearchQuery;
697
- const variables = { search, page: 1, perPage: count };
698
- const searchResults = yield fetcher(query, variables);
697
+ const searchResults = yield fetcher(animeSearchQuery, {
698
+ search,
699
+ page: 1,
700
+ perPage: count,
701
+ });
699
702
  if (searchResults) {
700
703
  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
704
  if (results.length > 0) {
@@ -727,12 +730,10 @@ class AniList {
727
730
  ]);
728
731
  // Save selected anime to chosen list type
729
732
  if (yield Auth.isLoggedIn()) {
730
- const saveQuery = addAnimeToListMutation;
731
- const saveVariables = {
733
+ const response = yield fetcher(addAnimeToListMutation, {
732
734
  mediaId: selectedAnime,
733
735
  status: selectedListType,
734
- };
735
- const response = yield fetcher(saveQuery, saveVariables);
736
+ });
736
737
  if (response) {
737
738
  const saved = (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
738
739
  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 +755,11 @@ class AniList {
754
755
  static searchManga(search, count) {
755
756
  return __awaiter(this, void 0, void 0, function* () {
756
757
  var _a, _b, _c;
757
- const query = mangaSearchQuery;
758
- const variables = { search, page: 1, perPage: count };
759
- const mangaSearchResult = yield fetcher(query, variables);
758
+ const mangaSearchResult = yield fetcher(mangaSearchQuery, {
759
+ search,
760
+ page: 1,
761
+ perPage: count,
762
+ });
760
763
  if (mangaSearchResult) {
761
764
  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
765
  // List of manga search results
@@ -789,9 +792,10 @@ class AniList {
789
792
  ]);
790
793
  // If logged in save to the list
791
794
  if (yield Auth.isLoggedIn()) {
792
- const mutation = addMangaToListMutation;
793
- const variables = { mediaId: selectedMangaId, status: selectedListType };
794
- const response = yield fetcher(mutation, variables);
795
+ const response = yield fetcher(addMangaToListMutation, {
796
+ mediaId: selectedMangaId,
797
+ status: selectedListType,
798
+ });
795
799
  if (response) {
796
800
  const saved = (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
797
801
  console.log(`\nEntry ${saved === null || saved === void 0 ? void 0 : saved.id}. Saved as ${saved === null || saved === void 0 ? void 0 : saved.status}.`);
@@ -991,19 +995,16 @@ class MyAnimeList {
991
995
  });
992
996
  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
997
  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
- }));
998
+ const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => ({
999
+ id: entry.media.id,
1000
+ malId: entry.media.idMal,
1001
+ title: entry.media.title,
1002
+ private: entry.private,
1003
+ chapters: entry.media.chapters,
1004
+ progress: entry.progress,
1005
+ status: entry.status,
1006
+ hiddenFromStatusLists: entry.hiddenFromStatusLists,
1007
+ })));
1007
1008
  const XMLContent = createMangaListXML(mediaWithProgress);
1008
1009
  const path = join(getDownloadFolderPath(), `${yield Auth.MyUserName()}@irfanshadikrishad-anilist-myanimelist(manga)-${getFormattedDate()}.xml`);
1009
1010
  yield writeFile(path, yield XMLContent, "utf8");
@@ -1020,4 +1021,92 @@ class MyAnimeList {
1020
1021
  });
1021
1022
  }
1022
1023
  }
1023
- export { AniList, MyAnimeList };
1024
+ class AniDB {
1025
+ static importAnime() {
1026
+ return __awaiter(this, void 0, void 0, function* () {
1027
+ var _a, _b;
1028
+ try {
1029
+ const filename = yield selectFile(".json");
1030
+ const filePath = join(getDownloadFolderPath(), filename);
1031
+ const fileContent = yield readFile(filePath, "utf8");
1032
+ const js0n_repaired = jsonrepair(fileContent);
1033
+ if (fileContent) {
1034
+ const obj3ct = yield JSON.parse(js0n_repaired);
1035
+ const animeList = obj3ct === null || obj3ct === void 0 ? void 0 : obj3ct.anime;
1036
+ if ((animeList === null || animeList === void 0 ? void 0 : animeList.length) > 0) {
1037
+ let count = 0;
1038
+ let iteration = 0;
1039
+ let missed = [];
1040
+ for (const anime of animeList) {
1041
+ iteration++;
1042
+ const anidbId = anime.id;
1043
+ const released = anime.broadcastDate; // DD-MM-YYYY (eg: "23.07.2016")
1044
+ const status = anime.status;
1045
+ // const type = anime.type
1046
+ const totalEpisodes = anime.totalEpisodes;
1047
+ const ownEpisodes = anime.ownEpisodes;
1048
+ const romanjiName = anime.romanjiName;
1049
+ const englishName = anime.englishName;
1050
+ function getStatus(anidbStatus, episodesSeen) {
1051
+ if (anidbStatus === "complete") {
1052
+ return AniListMediaStatus.COMPLETED;
1053
+ }
1054
+ else if (anidbStatus === "incomplete" &&
1055
+ Number(episodesSeen) > 0) {
1056
+ return AniListMediaStatus.CURRENT;
1057
+ }
1058
+ else {
1059
+ return AniListMediaStatus.PLANNING;
1060
+ }
1061
+ }
1062
+ let anilistId = yield anidbToanilistMapper(romanjiName, Number(released.split(".")[2]), englishName);
1063
+ if (anilistId) {
1064
+ try {
1065
+ const saveResponse = yield fetcher(saveAnimeWithProgressMutation, {
1066
+ mediaId: anilistId,
1067
+ progress: ownEpisodes - 2,
1068
+ status: getStatus(status, ownEpisodes),
1069
+ hiddenFromStatusLists: false,
1070
+ private: false,
1071
+ });
1072
+ 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;
1073
+ if (entryId) {
1074
+ count++;
1075
+ console.log(`[${count}]\t${entryId} ✅\t${anidbId}\t${anilistId}\t(${ownEpisodes}/${totalEpisodes})\t${status}→${getStatus(status, ownEpisodes)}`);
1076
+ }
1077
+ // Rate limit each API call to avoid server overload
1078
+ // await new Promise((resolve) => setTimeout(resolve, 1100))
1079
+ }
1080
+ catch (error) {
1081
+ console.error(`Error processing AniDB ID ${anidbId}: ${error.message}`);
1082
+ }
1083
+ }
1084
+ else {
1085
+ missed.push({
1086
+ anidbId: anidbId,
1087
+ englishTitle: englishName,
1088
+ romajiTitle: romanjiName,
1089
+ });
1090
+ }
1091
+ }
1092
+ console.log(`\nAccuracy: ${(((animeList.length - missed.length) / animeList.length) * 100).toFixed(2)}%\tTotal Processed: ${iteration}\tMissed: ${missed.length}`);
1093
+ if (missed.length > 0) {
1094
+ console.log(`Exporting missed entries to JSON file, Please add them manually.`);
1095
+ yield saveJSONasJSON(missed, "anidb-missed");
1096
+ }
1097
+ }
1098
+ else {
1099
+ console.log(`\nNo anime list found in the file.`);
1100
+ }
1101
+ }
1102
+ else {
1103
+ console.log(`\nNo content found in the file or unable to read.`);
1104
+ }
1105
+ }
1106
+ catch (error) {
1107
+ console.error(`\nError in AniDB import process: ${error.message}`);
1108
+ }
1109
+ });
1110
+ }
1111
+ }
1112
+ export { AniDB, AniList, MyAnimeList };