@irfanshadikrishad/anilist 1.2.3 → 1.2.5

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* () {
@@ -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,27 +391,17 @@ 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
396
  let page = 1;
426
397
  let allTrending = [];
427
398
  while (true) {
428
- const request = yield fetch(aniListEndpoint, {
429
- method: "POST",
430
- headers: {
431
- "Content-Type": "application/json",
432
- },
433
- body: JSON.stringify({
434
- query: trendingQuery,
435
- variables: { page, perPage: count },
436
- }),
437
- });
438
- const { data, errors } = yield request.json();
439
- if (request.status !== 200 || errors) {
440
- console.error(`\nSomething went wrong. ${((_a = errors === null || errors === void 0 ? void 0 : errors[0]) === null || _a === void 0 ? void 0 : _a.message) || "Unknown error"}`);
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"}`);
441
402
  return;
442
403
  }
443
- const media = (_b = data === null || data === void 0 ? void 0 : data.Page) === null || _b === void 0 ? void 0 : _b.media;
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;
444
405
  if (!media || media.length === 0) {
445
406
  console.log(`\nNo more trending anime available.`);
446
407
  break;
@@ -448,7 +409,7 @@ class AniList {
448
409
  allTrending = [...allTrending, ...media];
449
410
  const choices = allTrending.map((anime, idx) => ({
450
411
  name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
451
- value: anime === null || anime === void 0 ? void 0 : anime.id,
412
+ value: String(anime === null || anime === void 0 ? void 0 : anime.id),
452
413
  }));
453
414
  choices.push({ name: "See more", value: "see_more" });
454
415
  const { selectedAnime } = yield inquirer.prompt([
@@ -485,12 +446,12 @@ class AniList {
485
446
  }
486
447
  const variables = { mediaId: selectedAnime, status: selectedListType };
487
448
  const saveResponse = yield fetcher(addAnimeToListMutation, variables);
488
- const saved = (_c = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
449
+ const saved = (_e = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _e === void 0 ? void 0 : _e.SaveMediaListEntry;
489
450
  if (saved) {
490
451
  console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
491
452
  }
492
453
  else {
493
- 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"}`);
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"}`);
494
455
  }
495
456
  break;
496
457
  }
@@ -503,27 +464,17 @@ class AniList {
503
464
  }
504
465
  static getPopularAnime(count) {
505
466
  return __awaiter(this, void 0, void 0, function* () {
506
- var _a, _b, _c, _d, _e;
467
+ var _a, _b, _c, _d, _e, _f, _g;
507
468
  try {
508
469
  let page = 1;
509
470
  let allMedia = [];
510
471
  while (true) {
511
- const request = yield fetch(aniListEndpoint, {
512
- method: "POST",
513
- headers: {
514
- "Content-Type": "application/json",
515
- },
516
- body: JSON.stringify({
517
- query: popularQuery,
518
- variables: { page, perPage: count },
519
- }),
520
- });
521
- const { data, errors } = yield request.json();
522
- if (request.status !== 200 || errors) {
523
- console.error(`\nSomething went wrong. ${((_a = errors === null || errors === void 0 ? void 0 : errors[0]) === null || _a === void 0 ? void 0 : _a.message) || "Unknown error"}`);
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"}`);
524
475
  return;
525
476
  }
526
- const newMedia = (_b = data === null || data === void 0 ? void 0 : data.Page) === null || _b === void 0 ? void 0 : _b.media;
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;
527
478
  if (!newMedia || newMedia.length === 0) {
528
479
  console.log(`\nNo more popular anime available.`);
529
480
  break;
@@ -531,7 +482,7 @@ class AniList {
531
482
  allMedia = [...allMedia, ...newMedia];
532
483
  const choices = allMedia.map((anime, idx) => ({
533
484
  name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
534
- value: anime === null || anime === void 0 ? void 0 : anime.id,
485
+ value: String(anime === null || anime === void 0 ? void 0 : anime.id),
535
486
  }));
536
487
  choices.push({ name: "See more", value: "see_more" });
537
488
  const { selectedAnime } = yield inquirer.prompt([
@@ -567,12 +518,12 @@ class AniList {
567
518
  }
568
519
  const variables = { mediaId: selectedAnime, status: selectedListType };
569
520
  const saveResponse = yield fetcher(addAnimeToListMutation, variables);
570
- const saved = (_c = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
521
+ const saved = (_e = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _e === void 0 ? void 0 : _e.SaveMediaListEntry;
571
522
  if (saved) {
572
523
  console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
573
524
  }
574
525
  else {
575
- 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"}`);
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"}`);
576
527
  }
577
528
  break;
578
529
  }
@@ -609,7 +560,7 @@ class AniList {
609
560
  allUpcoming = [...allUpcoming, ...newUpcoming];
610
561
  const choices = allUpcoming.map((anime, idx) => ({
611
562
  name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
612
- value: anime === null || anime === void 0 ? void 0 : anime.id,
563
+ value: String(anime === null || anime === void 0 ? void 0 : anime.id),
613
564
  }));
614
565
  choices.push({ name: "See more", value: "see_more" });
615
566
  const { selectedAnime } = yield inquirer.prompt([
@@ -663,22 +614,11 @@ class AniList {
663
614
  }
664
615
  static getUserByUsername(username) {
665
616
  return __awaiter(this, void 0, void 0, function* () {
666
- 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;
667
618
  try {
668
- const headers = {
669
- "Content-Type": "application/json",
670
- };
671
- if (yield Auth.isLoggedIn()) {
672
- headers["Authorization"] = `Bearer ${yield Auth.RetriveAccessToken()}`;
673
- }
674
- const request = yield fetch(aniListEndpoint, {
675
- method: "POST",
676
- headers,
677
- body: JSON.stringify({ query: userQuery, variables: { username } }),
678
- });
679
- const response = yield request.json();
680
- if (request.status !== 200 || !((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.User)) {
681
- 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"}`);
682
622
  }
683
623
  const user = response.data.User;
684
624
  const userActivityResponse = yield fetcher(userActivityQuery, {
@@ -687,6 +627,15 @@ class AniList {
687
627
  perPage: 10,
688
628
  });
689
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;
690
639
  console.log(`\nID:\t\t${user.id}`);
691
640
  console.log(`Name:\t\t${user.name}`);
692
641
  console.log(`Site URL:\t${user.siteUrl}`);
@@ -697,14 +646,16 @@ class AniList {
697
646
  console.log(`Blocked:\t${user.isBlocked}`);
698
647
  console.log(`Follower:\t${user.isFollower}`);
699
648
  console.log(`Following:\t${user.isFollowing}`);
700
- console.log(`Profile Color:\t${(_g = user.options) === null || _g === void 0 ? void 0 : _g.profileColor}`);
701
- console.log(`Timezone:\t${(_h = user.options) === null || _h === void 0 ? void 0 : _h.timezone}`);
702
- 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}`);
703
- 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}`);
704
655
  if (activities.length > 0) {
705
656
  console.log(`\nRecent Activities:`);
706
- activities.forEach(({ status, progress, media }) => {
707
- 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)}`);
708
659
  });
709
660
  }
710
661
  else {
@@ -719,9 +670,9 @@ class AniList {
719
670
  static getAnimeDetailsByID(anilistID) {
720
671
  return __awaiter(this, void 0, void 0, function* () {
721
672
  var _a;
722
- const query = animeDetailsQuery;
723
- const variables = { id: anilistID };
724
- const details = yield fetcher(query, variables);
673
+ const details = yield fetcher(animeDetailsQuery, {
674
+ id: anilistID,
675
+ });
725
676
  if ((_a = details === null || details === void 0 ? void 0 : details.data) === null || _a === void 0 ? void 0 : _a.Media) {
726
677
  const { id, title, description, duration, startDate, endDate, countryOfOrigin, isAdult, status, season, format, genres, siteUrl, } = details.data.Media;
727
678
  console.log(`\nID: ${id}`);
@@ -743,9 +694,11 @@ class AniList {
743
694
  static searchAnime(search, count) {
744
695
  return __awaiter(this, void 0, void 0, function* () {
745
696
  var _a, _b, _c;
746
- const query = animeSearchQuery;
747
- const variables = { search, page: 1, perPage: count };
748
- const searchResults = yield fetcher(query, variables);
697
+ const searchResults = yield fetcher(animeSearchQuery, {
698
+ search,
699
+ page: 1,
700
+ perPage: count,
701
+ });
749
702
  if (searchResults) {
750
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;
751
704
  if (results.length > 0) {
@@ -777,12 +730,10 @@ class AniList {
777
730
  ]);
778
731
  // Save selected anime to chosen list type
779
732
  if (yield Auth.isLoggedIn()) {
780
- const saveQuery = addAnimeToListMutation;
781
- const saveVariables = {
733
+ const response = yield fetcher(addAnimeToListMutation, {
782
734
  mediaId: selectedAnime,
783
735
  status: selectedListType,
784
- };
785
- const response = yield fetcher(saveQuery, saveVariables);
736
+ });
786
737
  if (response) {
787
738
  const saved = (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
788
739
  console.log(`\nEntry ${saved === null || saved === void 0 ? void 0 : saved.id}. Saved as ${saved === null || saved === void 0 ? void 0 : saved.status}.`);
@@ -804,9 +755,11 @@ class AniList {
804
755
  static searchManga(search, count) {
805
756
  return __awaiter(this, void 0, void 0, function* () {
806
757
  var _a, _b, _c;
807
- const query = mangaSearchQuery;
808
- const variables = { search, page: 1, perPage: count };
809
- const mangaSearchResult = yield fetcher(query, variables);
758
+ const mangaSearchResult = yield fetcher(mangaSearchQuery, {
759
+ search,
760
+ page: 1,
761
+ perPage: count,
762
+ });
810
763
  if (mangaSearchResult) {
811
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;
812
765
  // List of manga search results
@@ -839,9 +792,10 @@ class AniList {
839
792
  ]);
840
793
  // If logged in save to the list
841
794
  if (yield Auth.isLoggedIn()) {
842
- const mutation = addMangaToListMutation;
843
- const variables = { mediaId: selectedMangaId, status: selectedListType };
844
- const response = yield fetcher(mutation, variables);
795
+ const response = yield fetcher(addMangaToListMutation, {
796
+ mediaId: selectedMangaId,
797
+ status: selectedListType,
798
+ });
845
799
  if (response) {
846
800
  const saved = (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
847
801
  console.log(`\nEntry ${saved === null || saved === void 0 ? void 0 : saved.id}. Saved as ${saved === null || saved === void 0 ? void 0 : saved.status}.`);
@@ -1041,19 +995,16 @@ class MyAnimeList {
1041
995
  });
1042
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) {
1043
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;
1044
- const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
1045
- var _a, _b, _c;
1046
- return ({
1047
- id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
1048
- malId: (_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.idMal,
1049
- title: (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title,
1050
- private: entry.private,
1051
- chapters: entry.media.chapters,
1052
- progress: entry.progress,
1053
- status: entry === null || entry === void 0 ? void 0 : entry.status,
1054
- hiddenFromStatusLists: entry.hiddenFromStatusLists,
1055
- });
1056
- }));
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
+ })));
1057
1008
  const XMLContent = createMangaListXML(mediaWithProgress);
1058
1009
  const path = join(getDownloadFolderPath(), `${yield Auth.MyUserName()}@irfanshadikrishad-anilist-myanimelist(manga)-${getFormattedDate()}.xml`);
1059
1010
  yield writeFile(path, yield XMLContent, "utf8");
@@ -1070,4 +1021,92 @@ class MyAnimeList {
1070
1021
  });
1071
1022
  }
1072
1023
  }
1073
- 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 };
@@ -1,4 +1,4 @@
1
- declare const currentUserQuery = "{\n Viewer {\n id name about bans siteUrl options { profileColor timezone activityMergeTime }\n donatorTier donatorBadge createdAt updatedAt unreadNotificationCount previousNames { name createdAt updatedAt }\n moderatorRoles favourites { anime { nodes { id title { romaji english } } } manga { nodes { id title { romaji english } } } }\n statistics { anime { count meanScore minutesWatched } manga { count chaptersRead volumesRead } }\n mediaListOptions { scoreFormat rowOrder animeList { sectionOrder } mangaList { sectionOrder } }\n }\n}";
1
+ declare const currentUserQuery = "{\n Viewer {\n id name about bans siteUrl options { profileColor timezone activityMergeTime }\n donatorTier donatorBadge createdAt updatedAt unreadNotificationCount previousNames { name createdAt updatedAt }\n moderatorRoles favourites { anime { nodes { id title { romaji english } } } manga { nodes { id title { romaji english } } } }\n statistics { anime { count meanScore minutesWatched episodesWatched } manga { count chaptersRead volumesRead meanScore } }\n mediaListOptions { scoreFormat rowOrder animeList { sectionOrder } mangaList { sectionOrder } }\n }\n}";
2
2
  declare const trendingQuery = "query ($page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n media(sort: TRENDING_DESC, type: ANIME) { id title { romaji english } }\n }\n}";
3
3
  declare const popularQuery = "query ($page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n media(sort: POPULARITY_DESC, type: ANIME) { id title { romaji english } }\n }\n}";
4
4
  declare const userQuery = "query ($username: String) {\n User(name: $username) {\n id name siteUrl donatorTier donatorBadge createdAt updatedAt previousNames { name createdAt updatedAt }\n isBlocked isFollower isFollowing options { profileColor timezone activityMergeTime }\n statistics { anime { count episodesWatched minutesWatched } manga { count chaptersRead volumesRead } }\n }\n}";
@@ -9,7 +9,7 @@ declare const deleteMangaEntryMutation = "mutation($id: Int) {\n DeleteMediaLis
9
9
  declare const upcomingAnimesQuery = "query GetNextSeasonAnime($nextSeason: MediaSeason, $nextYear: Int, $perPage: Int) {\n Page(perPage: $perPage) {\n media(season: $nextSeason, seasonYear: $nextYear, type: ANIME, sort: POPULARITY_DESC) {\n id title { romaji english native userPreferred } season seasonYear startDate { year month day }\n episodes description genres\n }\n }\n}";
10
10
  declare const animeDetailsQuery = "query ($id: Int) {\n Media(id: $id) {\n id idMal title { romaji english native userPreferred } episodes nextAiringEpisode { id }\n duration startDate { year month day } endDate { year month day } countryOfOrigin description isAdult status season format genres siteUrl\n stats { scoreDistribution { score amount } statusDistribution { status amount } }\n }\n}";
11
11
  declare const userActivityQuery = "query ($id: Int, $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n activities(userId: $id, type_in: [ANIME_LIST, MANGA_LIST], sort: ID_DESC) {\n ... on ListActivity { id status progress createdAt media { id title { romaji english } } }\n }\n }\n}";
12
- declare const animeSearchQuery = "query ($search: String, $perPage: Int) {\n Page(perPage: $perPage) {\n media(search: $search, type: ANIME) { id title { romaji english native userPreferred } episodes status description }\n }\n}";
12
+ declare const animeSearchQuery = "query ($search: String, $perPage: Int) {\n Page(perPage: $perPage) {\n media(search: $search, type: ANIME) { id title { romaji english native userPreferred } startDate { day month year } episodes status description }\n }\n}";
13
13
  declare const mangaSearchQuery = "query ($search: String, $perPage: Int) {\n Page(perPage: $perPage) {\n media(search: $search, type: MANGA) { id title { romaji english native userPreferred } chapters status description }\n }\n}";
14
14
  declare const activityTextQuery = "query ($userId: Int, $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n activities(userId: $userId, type: TEXT, sort: ID_DESC) {\n ... on TextActivity { id type text createdAt user { id name } }\n }\n }\n}";
15
15
  declare const activityAnimeListQuery = "query ($userId: Int, $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n activities(userId: $userId, type: ANIME_LIST, sort: ID_DESC) {\n ... on ListActivity { id type status progress createdAt media { id title { romaji english native } } }\n }\n }\n}";
@@ -19,4 +19,6 @@ declare const activityAllQuery = "query ($userId: Int, $page: Int, $perPage: Int
19
19
  declare const activityMediaList = "query ($userId: Int, $page: Int, $perPage: Int, $type: ActivityType) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total currentPage lastPage hasNextPage perPage }\n activities(userId: $userId, type: $type, sort: ID_DESC) {\n ... on ListActivity { id type status progress media { id title { romaji english native } format } createdAt }\n }\n }\n}";
20
20
  declare const malIdToAnilistAnimeId = "query ($malId: Int) {\n Media(idMal: $malId, type: ANIME) {\n id title { romaji english } } \n}\n";
21
21
  declare const malIdToAnilistMangaId = "query ($malId: Int) {\n Media(idMal: $malId, type: MANGA) {\n id title { romaji english } } \n}\n";
22
- export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userQuery, };
22
+ declare const userFollowingQuery = "query ($userId: Int!) {\n Page {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n following(userId: $userId, sort: [USERNAME]) { id name avatar { large medium } bannerImage }\n }\n}\n";
23
+ declare const userFollowersQuery = "query ($userId: Int!) {\n Page {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n followers(userId: $userId, sort: [USERNAME]) { id name avatar { large medium } bannerImage }\n }\n}\n";
24
+ export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, };
@@ -3,7 +3,7 @@ const currentUserQuery = `{
3
3
  id name about bans siteUrl options { profileColor timezone activityMergeTime }
4
4
  donatorTier donatorBadge createdAt updatedAt unreadNotificationCount previousNames { name createdAt updatedAt }
5
5
  moderatorRoles favourites { anime { nodes { id title { romaji english } } } manga { nodes { id title { romaji english } } } }
6
- statistics { anime { count meanScore minutesWatched } manga { count chaptersRead volumesRead } }
6
+ statistics { anime { count meanScore minutesWatched episodesWatched } manga { count chaptersRead volumesRead meanScore } }
7
7
  mediaListOptions { scoreFormat rowOrder animeList { sectionOrder } mangaList { sectionOrder } }
8
8
  }
9
9
  }`;
@@ -66,7 +66,7 @@ const userActivityQuery = `query ($id: Int, $page: Int, $perPage: Int) {
66
66
  }`;
67
67
  const animeSearchQuery = `query ($search: String, $perPage: Int) {
68
68
  Page(perPage: $perPage) {
69
- media(search: $search, type: ANIME) { id title { romaji english native userPreferred } episodes status description }
69
+ media(search: $search, type: ANIME) { id title { romaji english native userPreferred } startDate { day month year } episodes status description }
70
70
  }
71
71
  }`;
72
72
  const mangaSearchQuery = `query ($search: String, $perPage: Int) {
@@ -129,4 +129,18 @@ const malIdToAnilistMangaId = `query ($malId: Int) {
129
129
  id title { romaji english } }
130
130
  }
131
131
  `;
132
- export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userQuery, };
132
+ const userFollowingQuery = `query ($userId: Int!) {
133
+ Page {
134
+ pageInfo { total perPage currentPage lastPage hasNextPage }
135
+ following(userId: $userId, sort: [USERNAME]) { id name avatar { large medium } bannerImage }
136
+ }
137
+ }
138
+ `;
139
+ const userFollowersQuery = `query ($userId: Int!) {
140
+ Page {
141
+ pageInfo { total perPage currentPage lastPage hasNextPage }
142
+ followers(userId: $userId, sort: [USERNAME]) { id name avatar { large medium } bannerImage }
143
+ }
144
+ }
145
+ `;
146
+ export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, };