@irfanshadikrishad/anilist 1.1.10 → 1.2.1-forbidden.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  Minimalist unofficial AniList CLI for Anime and Manga Enthusiasts.
4
4
 
5
+ ![NPM Version](https://img.shields.io/npm/v/%40irfanshadikrishad%2Fanilist?style=for-the-badge&color=%23adc178)
6
+ ![NPM Downloads](https://img.shields.io/npm/dw/%40irfanshadikrishad%2Fanilist?style=for-the-badge&color=%23eaac8b)
7
+ ![NPM License](https://img.shields.io/npm/l/%40irfanshadikrishad%2Fanilist?style=for-the-badge&color=%23f2d0a4)
8
+
5
9
  #### How to install?
6
10
 
7
11
  Make sure [Node.js](https://nodejs.org/en) and [npm](https://www.npmjs.com) are already installed in your system.
@@ -35,7 +39,8 @@ To login:
35
39
  anilist login -i <client-id> -s <client-secret>
36
40
  ```
37
41
 
38
- here `<client-id>` and `<client-secret>` should be replaced by the ones that you recieved from the developer setting.
42
+ > [!NOTE]
43
+ > here `<client-id>` and `<client-secret>` should be replaced by the ones that you recieved from the developer setting.
39
44
 
40
45
  #### CLI Commands Overview
41
46
 
@@ -43,14 +48,14 @@ here `<client-id>` and `<client-secret>` should be replaced by the ones that you
43
48
  | ------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------ |
44
49
  | **`login`** | `-i, --id` `-s, --secret` | Log in with your AniList credentials |
45
50
  | **`logout`** | _None_ | Log out from your AniList account |
46
- | **`me`** | _None_ | Display information about the logged-in user |
51
+ | **`whoami`** | _None_ | Display information about the logged-in user |
47
52
  | **`-V, --version`** | _None_ | Display the current version of the CLI |
48
53
  | **`-h, --help`** | _None_ | Display available commands and options |
49
54
  | **`trending`** <br> _(alias: `tr`)_ | `-c (default: 10)` | Fetch trending anime (default count is 10) |
50
55
  | **`popular`** <br> _(alias: `plr`)_ | `-c (default: 10)` | Fetch popular anime (default count is 10) |
51
56
  | **`user`** | `<username>` | Get information about a specific AniList user |
52
57
  | **`lists`** <br> _(alias: `ls`)_ | `-a, --anime` <br> `-m, --manga` | Fetch anime or manga lists of the logged-in user |
53
- | **`delete`** <br> _(alias: `del`)_ | `-a, --anime` <br> `-m, --manga` <br> `-ac, --activity` | Delete collections of anime, manga or activities |
58
+ | **`delete`** <br> _(alias: `del`)_ | `-a, --anime` <br> `-m, --manga` <br> `-s, --activity` | Delete collections of anime, manga or activities |
54
59
  | **`upcoming`** <br> _(alias:`up`)_ | `-c (default: 10)` | Fetch upcoming anime (default count is 10) |
55
60
  | **`anime`** | `<anime-id>` | Get anime details by Anime Id |
56
61
  | **`search`** <br> _(alias:`srch`/`find`)_ | `<query>` <br> `-a, --anime` <br> `-m, --manga` <br> `-c (default: 10)` | Get anime/manga search results |
@@ -221,6 +226,9 @@ anilist import -m
221
226
  - `-m, --manga`: To import manga list.
222
227
  - **Description**: Import anime or manga list. If you want to import anime/manga list from MyAnimeList, export the XML from [here](https://myanimelist.net/panel.php?go=export).
223
228
 
229
+ > [!IMPORTANT]
230
+ > If you are importing from a file, place the file in the system specific download folder, And the exported file will also be exported there as well.
231
+
224
232
  #### Security
225
233
 
226
234
  Since you are creating your own API client for login no else else can get your credentials and the generated access token will be stored in your own system. So, As long as you don't share your device (in case you do, just logout) you are safe.
@@ -229,4 +237,9 @@ Since you are creating your own API client for login no else else can get your c
229
237
 
230
238
  Want to contribute to the project? Check out complete guideline [here](CONTRIBUTING.md).
231
239
 
240
+ #### Donation
241
+
242
+ <img src='/assets/binance.jpg' alt='irfanshadikrishad_binance_pay' width='200px'><br>
243
+ Support the project if you find it useful to you.
244
+
232
245
  #### **_Thanks for visiting 💙_**
Binary file
@@ -1,23 +1,56 @@
1
+ import { MediaTitle } from "./types.js";
1
2
  declare class Auth {
2
3
  /**
3
4
  * Get access-token from user
4
5
  */
5
- static GetAccessToken(): Promise<any>;
6
+ static GetAccessToken(): Promise<string>;
6
7
  static StoreAccessToken(token: string): Promise<void>;
7
8
  static RetriveAccessToken(): Promise<string>;
8
9
  static Login(clientId: number, clientSecret: string): Promise<void>;
9
- static Myself(): Promise<any>;
10
+ static Myself(): Promise<{
11
+ id: number;
12
+ name: string;
13
+ siteUrl: string;
14
+ options: {
15
+ profileColor: string;
16
+ timezone: string;
17
+ activityMergeTime: string;
18
+ };
19
+ donatorTier: string;
20
+ donatorBadge: string;
21
+ unreadNotificationCount: number;
22
+ createdAt: number;
23
+ updatedAt: number;
24
+ statistics: {
25
+ anime: {
26
+ count: number;
27
+ meanScore: string;
28
+ minutesWatched: string;
29
+ episodesWatched: number;
30
+ };
31
+ manga: {
32
+ count: number;
33
+ meanScore: string;
34
+ chaptersRead: number;
35
+ volumesRead: number;
36
+ };
37
+ };
38
+ }>;
10
39
  static isLoggedIn(): Promise<boolean>;
11
40
  static Logout(): Promise<void>;
12
- static MyUserId(): Promise<any>;
13
- static MyUserName(): Promise<any>;
41
+ static MyUserId(): Promise<number>;
42
+ static MyUserName(): Promise<string>;
14
43
  static DeleteMyActivities(): Promise<void>;
15
44
  static DeleteMyAnimeList(): Promise<void>;
16
- static DeleteAnimeById(id: number, title?: any): Promise<void>;
45
+ static DeleteAnimeById(id: number, title?: MediaTitle): Promise<void>;
17
46
  static DeleteMyMangaList(): Promise<void>;
18
- static DeleteMangaById(id: number, title?: any): Promise<void>;
47
+ static DeleteMangaById(id: number, title?: MediaTitle): Promise<void>;
19
48
  static Write(status: string): Promise<void>;
20
49
  static callAnimeImporter(): Promise<void>;
21
50
  static callMangaImporter(): Promise<void>;
51
+ private static LikeFollowing;
52
+ private static Like;
53
+ private static LikeSpecificUser;
54
+ static AutoLike(): Promise<void>;
22
55
  }
23
56
  export { Auth };
@@ -15,9 +15,9 @@ import os from "os";
15
15
  import path from "path";
16
16
  import { fetcher } from "./fetcher.js";
17
17
  import { AniList, MyAnimeList } from "./lists.js";
18
- import { deleteActivityMutation, saveTextActivityMutation, } from "./mutations.js";
19
- import { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, userActivityQuery, } from "./queries.js";
20
- import { aniListEndpoint, getTitle, redirectUri } from "./workers.js";
18
+ import { deleteActivityMutation, likeActivityMutation, saveTextActivityMutation, } from "./mutations.js";
19
+ import { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, followingActivitiesQuery, globalActivitiesQuery, specificUserActivitiesQuery, userActivityQuery, userQuery, } from "./queries.js";
20
+ import { aniListEndpoint, getTitle, redirectUri, timestampToTimeAgo, } from "./workers.js";
21
21
  const home_dir = os.homedir();
22
22
  const save_path = path.join(home_dir, ".anilist_token");
23
23
  class Auth {
@@ -109,7 +109,7 @@ class Auth {
109
109
  }
110
110
  static Myself() {
111
111
  return __awaiter(this, void 0, void 0, function* () {
112
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
112
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
113
113
  try {
114
114
  if (yield Auth.isLoggedIn()) {
115
115
  const headers = {
@@ -130,33 +130,35 @@ class Auth {
130
130
  perPage: 10,
131
131
  });
132
132
  const activities = (_b = (_a = activiResponse === null || activiResponse === void 0 ? void 0 : activiResponse.data) === null || _a === void 0 ? void 0 : _a.Page) === null || _b === void 0 ? void 0 : _b.activities;
133
- console.log(`
134
- ID: ${user === null || user === void 0 ? void 0 : user.id}
135
- Name: ${user === null || user === void 0 ? void 0 : user.name}
136
- siteUrl: ${user === null || user === void 0 ? void 0 : user.siteUrl}
137
- profileColor: ${(_c = user === null || user === void 0 ? void 0 : user.options) === null || _c === void 0 ? void 0 : _c.profileColor}
138
- timeZone: ${(_d = user === null || user === void 0 ? void 0 : user.options) === null || _d === void 0 ? void 0 : _d.timezone}
139
- activityMergeTime: ${(_e = user === null || user === void 0 ? void 0 : user.options) === null || _e === void 0 ? void 0 : _e.activityMergeTime}
140
- donatorTier: ${user === null || user === void 0 ? void 0 : user.donatorTier}
141
- donatorBadge: ${user === null || user === void 0 ? void 0 : user.donatorBadge}
142
- unreadNotificationCount:${user === null || user === void 0 ? void 0 : user.unreadNotificationCount}
143
- Account Created: ${new Date((user === null || user === void 0 ? void 0 : user.createdAt) * 1000).toUTCString()}
144
- Account Updated: ${new Date((user === null || user === void 0 ? void 0 : user.updatedAt) * 1000).toUTCString()}
145
-
146
- Statistics (Anime):
147
- Count: ${(_g = (_f = user === null || user === void 0 ? void 0 : user.statistics) === null || _f === void 0 ? void 0 : _f.anime) === null || _g === void 0 ? void 0 : _g.count}
148
- Mean Score: ${(_j = (_h = user === null || user === void 0 ? void 0 : user.statistics) === null || _h === void 0 ? void 0 : _h.anime) === null || _j === void 0 ? void 0 : _j.meanScore}
149
- Minutes Watched: ${(_l = (_k = user === null || user === void 0 ? void 0 : user.statistics) === null || _k === void 0 ? void 0 : _k.anime) === null || _l === void 0 ? void 0 : _l.minutesWatched}
150
-
151
- Statistics (Manga):
152
- Count: ${(_o = (_m = user === null || user === void 0 ? void 0 : user.statistics) === null || _m === void 0 ? void 0 : _m.manga) === null || _o === void 0 ? void 0 : _o.count}
153
- Chapters Read: ${(_q = (_p = user === null || user === void 0 ? void 0 : user.statistics) === null || _p === void 0 ? void 0 : _p.manga) === null || _q === void 0 ? void 0 : _q.chaptersRead}
154
- Volumes Read: ${(_s = (_r = user === null || user === void 0 ? void 0 : user.statistics) === null || _r === void 0 ? void 0 : _r.manga) === null || _s === void 0 ? void 0 : _s.volumesRead}
133
+ console.log(`
134
+ ID: ${user === null || user === void 0 ? void 0 : user.id}
135
+ Name: ${user === null || user === void 0 ? void 0 : user.name}
136
+ siteUrl: ${user === null || user === void 0 ? void 0 : user.siteUrl}
137
+ profileColor: ${(_c = user === null || user === void 0 ? void 0 : user.options) === null || _c === void 0 ? void 0 : _c.profileColor}
138
+ timeZone: ${(_d = user === null || user === void 0 ? void 0 : user.options) === null || _d === void 0 ? void 0 : _d.timezone}
139
+ activityMergeTime: ${(_e = user === null || user === void 0 ? void 0 : user.options) === null || _e === void 0 ? void 0 : _e.activityMergeTime}
140
+ donatorTier: ${user === null || user === void 0 ? void 0 : user.donatorTier}
141
+ donatorBadge: ${user === null || user === void 0 ? void 0 : user.donatorBadge}
142
+ unreadNotificationCount:${user === null || user === void 0 ? void 0 : user.unreadNotificationCount}
143
+ Account Created: ${new Date((user === null || user === void 0 ? void 0 : user.createdAt) * 1000).toUTCString()}
144
+ Account Updated: ${new Date((user === null || user === void 0 ? void 0 : user.updatedAt) * 1000).toUTCString()}
145
+
146
+ Statistics (Anime):
147
+ Count: ${(_g = (_f = user === null || user === void 0 ? void 0 : user.statistics) === null || _f === void 0 ? void 0 : _f.anime) === null || _g === void 0 ? void 0 : _g.count}
148
+ Mean Score: ${(_j = (_h = user === null || user === void 0 ? void 0 : user.statistics) === null || _h === void 0 ? void 0 : _h.anime) === null || _j === void 0 ? void 0 : _j.meanScore}
149
+ Minutes Watched: ${(_l = (_k = user === null || user === void 0 ? void 0 : user.statistics) === null || _k === void 0 ? void 0 : _k.anime) === null || _l === void 0 ? void 0 : _l.minutesWatched}
150
+ Episodes Watched: ${(_o = (_m = user === null || user === void 0 ? void 0 : user.statistics) === null || _m === void 0 ? void 0 : _m.anime) === null || _o === void 0 ? void 0 : _o.episodesWatched}
151
+
152
+ Statistics (Manga):
153
+ Count: ${(_q = (_p = user === null || user === void 0 ? void 0 : user.statistics) === null || _p === void 0 ? void 0 : _p.manga) === null || _q === void 0 ? void 0 : _q.count}
154
+ Mean Score: ${(_s = (_r = user === null || user === void 0 ? void 0 : user.statistics) === null || _r === void 0 ? void 0 : _r.manga) === null || _s === void 0 ? void 0 : _s.meanScore}
155
+ Chapters Read: ${(_u = (_t = user === null || user === void 0 ? void 0 : user.statistics) === null || _t === void 0 ? void 0 : _t.manga) === null || _u === void 0 ? void 0 : _u.chaptersRead}
156
+ Volumes Read: ${(_w = (_v = user === null || user === void 0 ? void 0 : user.statistics) === null || _v === void 0 ? void 0 : _v.manga) === null || _w === void 0 ? void 0 : _w.volumesRead}
155
157
  `);
156
158
  console.log(`\nRecent Activities:`);
157
159
  if (activities.length > 0) {
158
- activities.map(({ status, progress, media }) => {
159
- console.log(`${status} ${progress ? `${progress} of ` : ""}${getTitle(media === null || media === void 0 ? void 0 : media.title)}`);
160
+ activities.map(({ status, progress, media, createdAt }) => {
161
+ console.log(`${timestampToTimeAgo(createdAt)}\t${status} ${progress ? `${progress} of ` : ""}${getTitle(media === null || media === void 0 ? void 0 : media.title)}`);
160
162
  });
161
163
  }
162
164
  return user;
@@ -217,7 +219,7 @@ Statistics (Manga):
217
219
  return __awaiter(this, void 0, void 0, function* () {
218
220
  var _a, _b;
219
221
  if (!(yield Auth.isLoggedIn())) {
220
- console.log(`\nUser not logged in.`);
222
+ console.warn(`\nUser not logged in.`);
221
223
  return null;
222
224
  }
223
225
  const token = yield Auth.RetriveAccessToken();
@@ -281,8 +283,6 @@ Statistics (Manga):
281
283
  ],
282
284
  },
283
285
  ]);
284
- const userId = yield Auth.MyUserId();
285
- const variables = { page: 1, perPage: 100, userId };
286
286
  const queryMap = {
287
287
  0: activityAllQuery,
288
288
  1: activityTextQuery,
@@ -293,6 +293,7 @@ Statistics (Manga):
293
293
  };
294
294
  const query = queryMap[activityType];
295
295
  let hasMoreActivities = true;
296
+ let totalCount = 0;
296
297
  while (hasMoreActivities) {
297
298
  const response = yield fetcher(query, {
298
299
  page: 1,
@@ -315,7 +316,8 @@ Statistics (Manga):
315
316
  });
316
317
  const isDeleted = (_f = (_e = deleteResponse === null || deleteResponse === void 0 ? void 0 : deleteResponse.data) === null || _e === void 0 ? void 0 : _e.DeleteActivity) === null || _f === void 0 ? void 0 : _f.deleted;
317
318
  count++;
318
- console.log(`[${count}/${activities.length}] ${act === null || act === void 0 ? void 0 : act.id} ${isDeleted ? "✅" : "❌"}`);
319
+ totalCount++;
320
+ console.log(`[${count}/${activities.length}/${totalCount}]\t${act === null || act === void 0 ? void 0 : act.id} ${isDeleted ? "✅" : "❌"}`);
319
321
  // Avoiding rate-limit
320
322
  yield new Promise((resolve) => setTimeout(resolve, 1100));
321
323
  }
@@ -344,19 +346,8 @@ Statistics (Manga):
344
346
  if (yield Auth.isLoggedIn()) {
345
347
  const userID = yield Auth.MyUserId();
346
348
  if (userID) {
347
- const request = yield fetch(aniListEndpoint, {
348
- method: "POST",
349
- headers: {
350
- "content-type": "application/json",
351
- "Authorization": `Bearer ${yield Auth.RetriveAccessToken()}`,
352
- },
353
- body: JSON.stringify({
354
- query: currentUserAnimeList,
355
- variables: { id: userID },
356
- }),
357
- });
358
- const response = yield request.json();
359
- if (request.status === 200) {
349
+ const response = yield fetcher(currentUserAnimeList, { id: userID });
350
+ if (response !== null) {
360
351
  const lists = (_b = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists;
361
352
  if (lists.length > 0) {
362
353
  const { selectedList } = yield inquirer.prompt([
@@ -371,7 +362,7 @@ Statistics (Manga):
371
362
  const selectedEntries = lists.find((list) => list.name === selectedList);
372
363
  if (selectedEntries) {
373
364
  console.log(`\nDeleting entries of '${selectedEntries.name}':`);
374
- for (const [_, entry] of selectedEntries.entries.entries()) {
365
+ for (const [, entry] of selectedEntries.entries.entries()) {
375
366
  if (entry === null || entry === void 0 ? void 0 : entry.id) {
376
367
  yield Auth.DeleteAnimeById(entry === null || entry === void 0 ? void 0 : entry.id, (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title);
377
368
  yield new Promise((resolve) => setTimeout(resolve, 1100));
@@ -407,19 +398,8 @@ Statistics (Manga):
407
398
  return __awaiter(this, void 0, void 0, function* () {
408
399
  var _a, _b, _c;
409
400
  try {
410
- const request = yield fetch(aniListEndpoint, {
411
- method: "POST",
412
- headers: {
413
- "content-type": "application/json",
414
- "Authorization": `Bearer ${yield Auth.RetriveAccessToken()}`,
415
- },
416
- body: JSON.stringify({
417
- query: deleteMediaEntryMutation,
418
- variables: { id },
419
- }),
420
- });
421
- const response = yield request.json();
422
- if (request.status === 200) {
401
+ const response = yield fetcher(deleteMediaEntryMutation, { id: id });
402
+ if (response === null || response === void 0 ? void 0 : response.data) {
423
403
  const deleted = (_b = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.DeleteMediaListEntry) === null || _b === void 0 ? void 0 : _b.deleted;
424
404
  console.log(`del ${title ? getTitle(title) : ""} ${deleted ? "✅" : "❌"}`);
425
405
  }
@@ -440,19 +420,8 @@ Statistics (Manga):
440
420
  if (yield Auth.isLoggedIn()) {
441
421
  const userID = yield Auth.MyUserId();
442
422
  if (userID) {
443
- const request = yield fetch(aniListEndpoint, {
444
- method: "POST",
445
- headers: {
446
- "content-type": "application/json",
447
- "Authorization": `Bearer ${yield Auth.RetriveAccessToken()}`,
448
- },
449
- body: JSON.stringify({
450
- query: currentUserMangaList,
451
- variables: { id: userID },
452
- }),
453
- });
454
- const response = yield request.json();
455
- if (request.status === 200) {
423
+ const response = yield fetcher(currentUserMangaList, { id: userID });
424
+ if (response === null || response === void 0 ? void 0 : response.data) {
456
425
  const lists = (_b = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists;
457
426
  if (lists.length > 0) {
458
427
  const { selectedList } = yield inquirer.prompt([
@@ -467,7 +436,7 @@ Statistics (Manga):
467
436
  const selectedEntries = lists.find((list) => list.name === selectedList);
468
437
  if (selectedEntries) {
469
438
  console.log(`\nDeleting entries of '${selectedEntries.name}':`);
470
- for (const [_, entry] of selectedEntries.entries.entries()) {
439
+ for (const [, entry] of selectedEntries.entries.entries()) {
471
440
  if (entry === null || entry === void 0 ? void 0 : entry.id) {
472
441
  yield Auth.DeleteMangaById(entry === null || entry === void 0 ? void 0 : entry.id, (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title);
473
442
  yield new Promise((resolve) => setTimeout(resolve, 1100));
@@ -499,33 +468,22 @@ Statistics (Manga):
499
468
  }
500
469
  }
501
470
  catch (error) {
502
- console.error(`\nError deleting manga.`);
471
+ console.error(`\nError deleting manga. ${error.message}`);
503
472
  }
504
473
  });
505
474
  }
506
475
  static DeleteMangaById(id, title) {
507
476
  return __awaiter(this, void 0, void 0, function* () {
508
- var _a, _b;
477
+ var _a, _b, _c, _d;
509
478
  try {
510
- const request = yield fetch(aniListEndpoint, {
511
- method: "POST",
512
- headers: {
513
- "Content-Type": "application/json",
514
- "Authorization": `Bearer ${yield Auth.RetriveAccessToken()}`,
515
- },
516
- body: JSON.stringify({
517
- query: deleteMangaEntryMutation,
518
- variables: { id },
519
- }),
520
- });
521
- const { data, errors } = yield request.json();
479
+ const response = yield fetcher(deleteMangaEntryMutation, { id });
522
480
  const statusMessage = title ? getTitle(title) : "";
523
- if (request.ok) {
524
- const deleted = (_a = data === null || data === void 0 ? void 0 : data.DeleteMediaListEntry) === null || _a === void 0 ? void 0 : _a.deleted;
481
+ if (response === null || response === void 0 ? void 0 : response.data) {
482
+ const deleted = (_b = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.DeleteMediaListEntry) === null || _b === void 0 ? void 0 : _b.deleted;
525
483
  console.log(`del ${statusMessage} ${deleted ? "✅" : "❌"}`);
526
484
  }
527
485
  else {
528
- console.error(`Error deleting manga. ${(_b = errors === null || errors === void 0 ? void 0 : errors[0]) === null || _b === void 0 ? void 0 : _b.message}`);
486
+ console.error(`Error deleting manga. ${(_d = (_c = response === null || response === void 0 ? void 0 : response.errors) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.message}`);
529
487
  }
530
488
  }
531
489
  catch (error) {
@@ -541,12 +499,10 @@ Statistics (Manga):
541
499
  console.error(`\nPlease login to use this feature.`);
542
500
  return;
543
501
  }
544
- const query = saveTextActivityMutation;
545
- const variables = {
502
+ const data = yield fetcher(saveTextActivityMutation, {
546
503
  status: status +
547
504
  `<br><br><br><br>*Written using [@irfanshadikrishad/anilist](https://www.npmjs.com/package/@irfanshadikrishad/anilist).*`,
548
- };
549
- const data = yield fetcher(query, variables);
505
+ });
550
506
  if (!data) {
551
507
  console.error(`\nSomething went wrong. ${data}.`);
552
508
  return;
@@ -625,5 +581,215 @@ Statistics (Manga):
625
581
  }
626
582
  });
627
583
  }
584
+ static LikeFollowing() {
585
+ return __awaiter(this, void 0, void 0, function* () {
586
+ var _a, _b, _c, _d, _e;
587
+ try {
588
+ let page = 1;
589
+ let hasMoreActivities = true;
590
+ let retryCount = 0;
591
+ const maxRetries = 5;
592
+ while (hasMoreActivities) {
593
+ const activities = yield fetcher(followingActivitiesQuery, {
594
+ page,
595
+ perPage: 50,
596
+ });
597
+ if (activities && ((_b = (_a = activities === null || activities === void 0 ? void 0 : activities.data) === null || _a === void 0 ? void 0 : _a.Page) === null || _b === void 0 ? void 0 : _b.activities.length) > 0) {
598
+ retryCount = 0; // Reset retry count on successful fetch
599
+ const activiti = (_d = (_c = activities === null || activities === void 0 ? void 0 : activities.data) === null || _c === void 0 ? void 0 : _c.Page) === null || _d === void 0 ? void 0 : _d.activities;
600
+ for (let activ of activiti) {
601
+ if (!activ.isLiked && activ.id) {
602
+ try {
603
+ const like = yield fetcher(likeActivityMutation, {
604
+ activityId: activ.id,
605
+ });
606
+ console.info(`[${activ.id}]\t${(_e = activ.user) === null || _e === void 0 ? void 0 : _e.name} ${(like === null || like === void 0 ? void 0 : like.data) ? "✅" : "❌"}`);
607
+ }
608
+ catch (error) {
609
+ console.error(`Activity possibly deleted. ${error.message}`);
610
+ }
611
+ }
612
+ else {
613
+ console.log(`[${activ === null || activ === void 0 ? void 0 : activ.id}]\t${activ.user.name} already-liked`);
614
+ }
615
+ // avoiding rate-limit
616
+ yield new Promise((resolve) => {
617
+ setTimeout(resolve, 2000);
618
+ });
619
+ }
620
+ page++;
621
+ }
622
+ else {
623
+ if (retryCount < maxRetries) {
624
+ retryCount++;
625
+ console.warn(`Empty activities returned. Retrying... (${retryCount}/${maxRetries})`);
626
+ yield new Promise((resolve) => setTimeout(resolve, 3000));
627
+ }
628
+ else {
629
+ console.log(`\nProbably the end of activities after ${maxRetries} retries.`);
630
+ console.info(activities);
631
+ hasMoreActivities = false;
632
+ }
633
+ }
634
+ }
635
+ }
636
+ catch (error) {
637
+ console.error(`\nError from likeFollowing. ${error.message}`);
638
+ }
639
+ });
640
+ }
641
+ static Like(type) {
642
+ return __awaiter(this, void 0, void 0, function* () {
643
+ var _a, _b, _c, _d, _e;
644
+ try {
645
+ let page = 1;
646
+ let hasMoreActivities = true;
647
+ let activity = type === 0
648
+ ? followingActivitiesQuery
649
+ : type === 1
650
+ ? globalActivitiesQuery
651
+ : followingActivitiesQuery;
652
+ while (hasMoreActivities) {
653
+ const activities = yield fetcher(activity, {
654
+ page,
655
+ perPage: 50,
656
+ });
657
+ if (activities && ((_b = (_a = activities === null || activities === void 0 ? void 0 : activities.data) === null || _a === void 0 ? void 0 : _a.Page) === null || _b === void 0 ? void 0 : _b.activities.length) > 0) {
658
+ const activiti = (_d = (_c = activities === null || activities === void 0 ? void 0 : activities.data) === null || _c === void 0 ? void 0 : _c.Page) === null || _d === void 0 ? void 0 : _d.activities;
659
+ for (let activ of activiti) {
660
+ if (!activ.isLiked && activ.id) {
661
+ try {
662
+ const like = yield fetcher(likeActivityMutation, {
663
+ activityId: activ.id,
664
+ });
665
+ // const ToggleLike = like?.data?.ToggleLike
666
+ console.info(`[${activ.id}]\t${(_e = activ.user) === null || _e === void 0 ? void 0 : _e.name} ${(like === null || like === void 0 ? void 0 : like.data) ? "✅" : "❌"}`);
667
+ }
668
+ catch (error) {
669
+ console.error(`Activity possibly deleted. ${error.message}`);
670
+ }
671
+ }
672
+ else {
673
+ console.log(`[${activ === null || activ === void 0 ? void 0 : activ.id}]\t${activ.user.name} already-liked`);
674
+ }
675
+ // avoiding rate-limit
676
+ yield new Promise((resolve) => {
677
+ setTimeout(resolve, 1500);
678
+ });
679
+ }
680
+ page++;
681
+ }
682
+ else {
683
+ // No more activities to like
684
+ console.log(`\nProbably the end of activities.`);
685
+ console.info(activities);
686
+ hasMoreActivities = false;
687
+ }
688
+ }
689
+ }
690
+ catch (error) {
691
+ console.error(`\nError from likeFollowing. ${error.message}`);
692
+ }
693
+ });
694
+ }
695
+ static LikeSpecificUser() {
696
+ return __awaiter(this, void 0, void 0, function* () {
697
+ var _a, _b, _c, _d, _e, _f;
698
+ try {
699
+ const { username } = yield inquirer.prompt([
700
+ {
701
+ type: "input",
702
+ name: "username",
703
+ message: "Username of the user:",
704
+ },
705
+ ]);
706
+ const userDetails = yield fetcher(userQuery, { username: username });
707
+ if (userDetails) {
708
+ let page = 1;
709
+ const perPage = 50;
710
+ const userId = (_b = (_a = userDetails === null || userDetails === void 0 ? void 0 : userDetails.data) === null || _a === void 0 ? void 0 : _a.User) === null || _b === void 0 ? void 0 : _b.id;
711
+ if (userId) {
712
+ while (true) {
713
+ const activities = yield fetcher(specificUserActivitiesQuery, {
714
+ page,
715
+ perPage,
716
+ userId,
717
+ });
718
+ const activiti = (_d = (_c = activities === null || activities === void 0 ? void 0 : activities.data) === null || _c === void 0 ? void 0 : _c.Page) === null || _d === void 0 ? void 0 : _d.activities;
719
+ // Break the loop if no more activities are found
720
+ if (!activiti || activiti.length === 0) {
721
+ console.log("No more activities found.");
722
+ break;
723
+ }
724
+ for (let activ of activiti) {
725
+ if (!activ.isLiked && activ.id) {
726
+ try {
727
+ const like = yield fetcher(likeActivityMutation, {
728
+ activityId: activ.id,
729
+ });
730
+ console.info(`[${activ.id}]\t${(_e = activ.user) === null || _e === void 0 ? void 0 : _e.name} ${(like === null || like === void 0 ? void 0 : like.data) ? "✅" : "❌"}`);
731
+ }
732
+ catch (error) {
733
+ console.error(`Activity possibly deleted. ${error.message}`);
734
+ }
735
+ }
736
+ else {
737
+ console.log(`[${activ === null || activ === void 0 ? void 0 : activ.id}]\t${(_f = activ.user) === null || _f === void 0 ? void 0 : _f.name} already-liked`);
738
+ }
739
+ // Avoiding rate limit
740
+ yield new Promise((resolve) => {
741
+ setTimeout(resolve, 1500);
742
+ });
743
+ }
744
+ // Go to the next page
745
+ page += 1;
746
+ }
747
+ }
748
+ }
749
+ }
750
+ catch (error) {
751
+ console.error(`\nError from LikeSpecificUser. ${error.message}`);
752
+ }
753
+ });
754
+ }
755
+ static AutoLike() {
756
+ return __awaiter(this, void 0, void 0, function* () {
757
+ try {
758
+ if (!(yield Auth.isLoggedIn())) {
759
+ console.error(`\nPlease login to use this feature.`);
760
+ return;
761
+ }
762
+ const { activityType } = yield inquirer.prompt([
763
+ {
764
+ type: "list",
765
+ name: "activityType",
766
+ message: "Select activity type:",
767
+ choices: [
768
+ { name: "Following", value: 1 },
769
+ { name: "Global", value: 2 },
770
+ { name: "Specific User", value: 3 },
771
+ ],
772
+ pageSize: 10,
773
+ },
774
+ ]);
775
+ switch (activityType) {
776
+ case 1:
777
+ yield this.LikeFollowing();
778
+ break;
779
+ case 2:
780
+ yield this.Like(1);
781
+ break;
782
+ case 3:
783
+ yield this.LikeSpecificUser();
784
+ break;
785
+ default:
786
+ console.error(`\nInvalid choice. (${activityType})`);
787
+ }
788
+ }
789
+ catch (error) {
790
+ console.error(`\nError from autolike. ${error.message}`);
791
+ }
792
+ });
793
+ }
628
794
  }
629
795
  export { Auth };
@@ -2,7 +2,8 @@
2
2
  * Sends a GraphQL request to the AniList API.
3
3
  *
4
4
  * This function constructs a request with the provided query and variables,
5
- * handles authorization, and processes the API response.
5
+ * handles authorization, and processes the API response. If a rate-limit error (429) is returned,
6
+ * it waits for 1 minute and retries the request.
6
7
  *
7
8
  * @param {string} query - The AniList GraphQL query to be executed.
8
9
  * @param {object} variables - An object containing the variables for the query.
@@ -14,7 +14,8 @@ import { aniListEndpoint } from "./workers.js";
14
14
  * Sends a GraphQL request to the AniList API.
15
15
  *
16
16
  * This function constructs a request with the provided query and variables,
17
- * handles authorization, and processes the API response.
17
+ * handles authorization, and processes the API response. If a rate-limit error (429) is returned,
18
+ * it waits for 1 minute and retries the request.
18
19
  *
19
20
  * @param {string} query - The AniList GraphQL query to be executed.
20
21
  * @param {object} variables - An object containing the variables for the query.
@@ -22,7 +23,7 @@ import { aniListEndpoint } from "./workers.js";
22
23
  */
23
24
  function fetcher(query, variables) {
24
25
  return __awaiter(this, void 0, void 0, function* () {
25
- var _a;
26
+ var _a, _b;
26
27
  try {
27
28
  const headers = {
28
29
  "content-type": "application/json",
@@ -39,8 +40,13 @@ function fetcher(query, variables) {
39
40
  if (request.status === 200) {
40
41
  return response;
41
42
  }
43
+ else if (request.status === 429) {
44
+ console.warn("Rate limit reached. Retrying in 1 minute...");
45
+ yield new Promise((resolve) => setTimeout(resolve, 60000)); // Wait for 1 minute
46
+ return yield fetcher(query, variables); // Retry the request
47
+ }
42
48
  else {
43
- console.error(`\n${request.status} ${(_a = response === null || response === void 0 ? void 0 : response.errors[0]) === null || _a === void 0 ? void 0 : _a.message}.`);
49
+ console.error(`\n${request.status} ${((_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"}.`);
44
50
  return null;
45
51
  }
46
52
  }