@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.
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,28 +39,29 @@ 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
 
42
- | **Command** | **Options** | **Description** |
43
- | ------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------------ |
44
- | **`login`** | `-i, --id` `-s, --secret` | Log in with your AniList credentials |
45
- | **`logout`** | _None_ | Log out from your AniList account |
46
- | **`me`** | _None_ | Display information about the logged-in user |
47
- | **`-V, --version`** | _None_ | Display the current version of the CLI |
48
- | **`-h, --help`** | _None_ | Display available commands and options |
49
- | **`trending`** <br> _(alias: `tr`)_ | `-c (default: 10)` | Fetch trending anime (default count is 10) |
50
- | **`popular`** <br> _(alias: `plr`)_ | `-c (default: 10)` | Fetch popular anime (default count is 10) |
51
- | **`user`** | `<username>` | Get information about a specific AniList user |
52
- | **`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 |
54
- | **`upcoming`** <br> _(alias:`up`)_ | `-c (default: 10)` | Fetch upcoming anime (default count is 10) |
55
- | **`anime`** | `<anime-id>` | Get anime details by Anime Id |
56
- | **`search`** <br> _(alias:`srch`/`find`)_ | `<query>` <br> `-a, --anime` <br> `-m, --manga` <br> `-c (default: 10)` | Get anime/manga search results |
57
- | **`status`** <br> _(alias: `write`/`post`)_ | `<status>` | Write a status... (text/markdown/html) |
58
- | **`export`** <br> _(alias: `exp`)_ | `-a, --anime` <br> `-m, --manga` | Export anime or manga list in JSON, CSV or XML (MyAnimeList) |
59
- | **`import`** <br> _(alias: `imp`)_ | `-a, --anime` <br> `-m, --manga` | Import anime or manga list from exported JSON or MyAnimeList (XML) |
47
+ | **Command** | **Options** | **Description** |
48
+ | ------------------------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
49
+ | **`login`** | `-i, --id` `-s, --secret` | Log in with your AniList credentials |
50
+ | **`logout`** | _None_ | Log out from your AniList account |
51
+ | **`whoami`** | _None_ | Display information about the logged-in user |
52
+ | **`-V, --version`** | _None_ | Display the current version of the CLI |
53
+ | **`-h, --help`** | _None_ | Display available commands and options |
54
+ | **`trending`** <br> _(alias: `tr`)_ | `-c (default: 10)` | Fetch trending anime (default count is 10) |
55
+ | **`popular`** <br> _(alias: `plr`)_ | `-c (default: 10)` | Fetch popular anime (default count is 10) |
56
+ | **`user`** | `<username>` | Get information about a specific AniList user |
57
+ | **`lists`** <br> _(alias: `ls`)_ | `-a, --anime` <br> `-m, --manga` | Fetch anime or manga lists of the logged-in user |
58
+ | **`delete`** <br> _(alias: `del`)_ | `-a, --anime` <br> `-m, --manga` <br> `-s, --activity` | Delete collections of anime, manga or activities |
59
+ | **`upcoming`** <br> _(alias:`up`)_ | `-c (default: 10)` | Fetch upcoming anime (default count is 10) |
60
+ | **`anime`** | `<anime-id>` | Get anime details by Anime Id |
61
+ | **`search`** <br> _(alias:`srch`/`find`)_ | `<query>` <br> `-a, --anime` <br> `-m, --manga` <br> `-c (default: 10)` | Get anime/manga search results |
62
+ | **`status`** <br> _(alias: `write`/`post`)_ | `<status>` | Write a status... (text/markdown/html) |
63
+ | **`export`** <br> _(alias: `exp`)_ | `-a, --anime` <br> `-m, --manga` | Export anime or manga list in JSON, CSV or XML (MyAnimeList/AniDB) |
64
+ | **`import`** <br> _(alias: `imp`)_ | `-a, --anime` <br> `-m, --manga` | Import anime or manga list from exported JSON, MyAnimeList (XML) or AniDB (json-large) |
60
65
 
61
66
  #### Command Breakdown:
62
67
 
@@ -208,7 +213,7 @@ anilist export -a
208
213
  - **Options**:
209
214
  - `-a, --anime`: To export anime list.
210
215
  - `-m, --manga`: To export manga list.
211
- - **Description**: Export anime or manga list. For `XML (MyAnimeList)` file, to import it on MyAnimeList, go [here](https://myanimelist.net/import.php) and choose `MyAnimeList Import`.
216
+ - **Description**: Export anime or manga list. For `XML (MyAnimeList/AniDB)` file, to import it on MyAnimeList, go [here](https://myanimelist.net/import.php) and choose `MyAnimeList Import` for `AniDB` go [here](https://anidb.net/user/import) and select `MyAnimeList.net - XML anime list export`.
212
217
 
213
218
  #### `import` _(alias: `imp`)_:
214
219
 
@@ -219,7 +224,13 @@ anilist import -m
219
224
  - **Options**:
220
225
  - `-a, --anime`: To import anime list.
221
226
  - `-m, --manga`: To import manga list.
222
- - **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).
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), for exporting list from `AniDB` go [here](https://anidb.net/user/export).
228
+
229
+ > [!NOTE]
230
+ > If you have exported from `AniDB`, you will have to unzip it, and there should be a file named `mylist.json`, copy and paste it in your systems download folder, and select it from import option.
231
+
232
+ > [!IMPORTANT]
233
+ > 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.
223
234
 
224
235
  #### Security
225
236
 
@@ -229,9 +240,4 @@ Since you are creating your own API client for login no else else can get your c
229
240
 
230
241
  Want to contribute to the project? Check out complete guideline [here](CONTRIBUTING.md).
231
242
 
232
- #### Donation
233
-
234
- <img src='/assets/binance.jpg' alt='irfanshadikrishad_binance_pay' width='200px'><br>
235
- Support the project if you find it useful to you.
236
-
237
243
  #### **_Thanks for visiting šŸ’™_**
@@ -1,27 +1,57 @@
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>;
22
51
  private static LikeFollowing;
23
52
  private static Like;
24
53
  private static LikeSpecificUser;
54
+ static LikeFollowingActivityV2(perPage: number): Promise<void>;
25
55
  static AutoLike(): Promise<void>;
26
56
  }
27
57
  export { Auth };
@@ -14,10 +14,10 @@ import open from "open";
14
14
  import os from "os";
15
15
  import path from "path";
16
16
  import { fetcher } from "./fetcher.js";
17
- import { AniList, MyAnimeList } from "./lists.js";
17
+ import { AniDB, AniList, MyAnimeList } from "./lists.js";
18
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 } from "./workers.js";
19
+ import { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, followingActivitiesQuery, globalActivitiesQuery, specificUserActivitiesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, } from "./queries.js";
20
+ import { activityBy, 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, _x, _y, _z, _0, _1, _2;
113
113
  try {
114
114
  if (yield Auth.isLoggedIn()) {
115
115
  const headers = {
@@ -130,33 +130,47 @@ 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
+ // Get follower/following information
134
+ const req_followers = yield fetcher(userFollowersQuery, {
135
+ userId: user === null || user === void 0 ? void 0 : user.id,
136
+ });
137
+ const req_following = yield fetcher(userFollowingQuery, {
138
+ userId: user === null || user === void 0 ? void 0 : user.id,
139
+ });
140
+ const followersCount = ((_e = (_d = (_c = req_followers === null || req_followers === void 0 ? void 0 : req_followers.data) === null || _c === void 0 ? void 0 : _c.Page) === null || _d === void 0 ? void 0 : _d.pageInfo) === null || _e === void 0 ? void 0 : _e.total) || 0;
141
+ const followingCount = ((_h = (_g = (_f = req_following === null || req_following === void 0 ? void 0 : req_following.data) === null || _f === void 0 ? void 0 : _f.Page) === null || _g === void 0 ? void 0 : _g.pageInfo) === null || _h === void 0 ? void 0 : _h.total) || 0;
133
142
  console.log(`
134
143
  ID: ${user === null || user === void 0 ? void 0 : user.id}
135
144
  Name: ${user === null || user === void 0 ? void 0 : user.name}
136
145
  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}
146
+ profileColor: ${(_j = user === null || user === void 0 ? void 0 : user.options) === null || _j === void 0 ? void 0 : _j.profileColor}
147
+ timeZone: ${(_k = user === null || user === void 0 ? void 0 : user.options) === null || _k === void 0 ? void 0 : _k.timezone}
148
+ activityMergeTime: ${(_l = user === null || user === void 0 ? void 0 : user.options) === null || _l === void 0 ? void 0 : _l.activityMergeTime}
140
149
  donatorTier: ${user === null || user === void 0 ? void 0 : user.donatorTier}
141
150
  donatorBadge: ${user === null || user === void 0 ? void 0 : user.donatorBadge}
142
151
  unreadNotificationCount:${user === null || user === void 0 ? void 0 : user.unreadNotificationCount}
143
152
  Account Created: ${new Date((user === null || user === void 0 ? void 0 : user.createdAt) * 1000).toUTCString()}
144
153
  Account Updated: ${new Date((user === null || user === void 0 ? void 0 : user.updatedAt) * 1000).toUTCString()}
154
+
155
+ Followers: ${followersCount}
156
+ Following: ${followingCount}
145
157
 
146
158
  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}
159
+ Count: ${(_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.count}
160
+ Mean Score: ${(_q = (_p = user === null || user === void 0 ? void 0 : user.statistics) === null || _p === void 0 ? void 0 : _p.anime) === null || _q === void 0 ? void 0 : _q.meanScore}
161
+ Minutes Watched: ${(_s = (_r = user === null || user === void 0 ? void 0 : user.statistics) === null || _r === void 0 ? void 0 : _r.anime) === null || _s === void 0 ? void 0 : _s.minutesWatched}
162
+ Episodes Watched: ${(_u = (_t = user === null || user === void 0 ? void 0 : user.statistics) === null || _t === void 0 ? void 0 : _t.anime) === null || _u === void 0 ? void 0 : _u.episodesWatched}
150
163
 
151
164
  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}
165
+ Count: ${(_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.count}
166
+ Mean Score: ${(_y = (_x = user === null || user === void 0 ? void 0 : user.statistics) === null || _x === void 0 ? void 0 : _x.manga) === null || _y === void 0 ? void 0 : _y.meanScore}
167
+ Chapters Read: ${(_0 = (_z = user === null || user === void 0 ? void 0 : user.statistics) === null || _z === void 0 ? void 0 : _z.manga) === null || _0 === void 0 ? void 0 : _0.chaptersRead}
168
+ Volumes Read: ${(_2 = (_1 = user === null || user === void 0 ? void 0 : user.statistics) === null || _1 === void 0 ? void 0 : _1.manga) === null || _2 === void 0 ? void 0 : _2.volumesRead}
155
169
  `);
156
170
  console.log(`\nRecent Activities:`);
157
171
  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)}`);
172
+ activities.map(({ status, progress, media, createdAt }) => {
173
+ console.log(`${timestampToTimeAgo(createdAt)}\t${status} ${progress ? `${progress} of ` : ""}${getTitle(media === null || media === void 0 ? void 0 : media.title)}`);
160
174
  });
161
175
  }
162
176
  return user;
@@ -217,7 +231,7 @@ Statistics (Manga):
217
231
  return __awaiter(this, void 0, void 0, function* () {
218
232
  var _a, _b;
219
233
  if (!(yield Auth.isLoggedIn())) {
220
- console.log(`\nUser not logged in.`);
234
+ console.warn(`\nUser not logged in.`);
221
235
  return null;
222
236
  }
223
237
  const token = yield Auth.RetriveAccessToken();
@@ -281,8 +295,6 @@ Statistics (Manga):
281
295
  ],
282
296
  },
283
297
  ]);
284
- const userId = yield Auth.MyUserId();
285
- const variables = { page: 1, perPage: 100, userId };
286
298
  const queryMap = {
287
299
  0: activityAllQuery,
288
300
  1: activityTextQuery,
@@ -293,6 +305,7 @@ Statistics (Manga):
293
305
  };
294
306
  const query = queryMap[activityType];
295
307
  let hasMoreActivities = true;
308
+ let totalCount = 0;
296
309
  while (hasMoreActivities) {
297
310
  const response = yield fetcher(query, {
298
311
  page: 1,
@@ -315,7 +328,8 @@ Statistics (Manga):
315
328
  });
316
329
  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
330
  count++;
318
- console.log(`[${count}/${activities.length}] ${act === null || act === void 0 ? void 0 : act.id} ${isDeleted ? "āœ…" : "āŒ"}`);
331
+ totalCount++;
332
+ console.log(`[${count}/${activities.length}/${totalCount}]\t${act === null || act === void 0 ? void 0 : act.id} ${isDeleted ? "āœ…" : "āŒ"}`);
319
333
  // Avoiding rate-limit
320
334
  yield new Promise((resolve) => setTimeout(resolve, 1100));
321
335
  }
@@ -344,19 +358,8 @@ Statistics (Manga):
344
358
  if (yield Auth.isLoggedIn()) {
345
359
  const userID = yield Auth.MyUserId();
346
360
  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) {
361
+ const response = yield fetcher(currentUserAnimeList, { id: userID });
362
+ if (response !== null) {
360
363
  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
364
  if (lists.length > 0) {
362
365
  const { selectedList } = yield inquirer.prompt([
@@ -371,7 +374,7 @@ Statistics (Manga):
371
374
  const selectedEntries = lists.find((list) => list.name === selectedList);
372
375
  if (selectedEntries) {
373
376
  console.log(`\nDeleting entries of '${selectedEntries.name}':`);
374
- for (const [_, entry] of selectedEntries.entries.entries()) {
377
+ for (const [, entry] of selectedEntries.entries.entries()) {
375
378
  if (entry === null || entry === void 0 ? void 0 : entry.id) {
376
379
  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
380
  yield new Promise((resolve) => setTimeout(resolve, 1100));
@@ -407,19 +410,8 @@ Statistics (Manga):
407
410
  return __awaiter(this, void 0, void 0, function* () {
408
411
  var _a, _b, _c;
409
412
  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) {
413
+ const response = yield fetcher(deleteMediaEntryMutation, { id: id });
414
+ if (response === null || response === void 0 ? void 0 : response.data) {
423
415
  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
416
  console.log(`del ${title ? getTitle(title) : ""} ${deleted ? "āœ…" : "āŒ"}`);
425
417
  }
@@ -440,19 +432,8 @@ Statistics (Manga):
440
432
  if (yield Auth.isLoggedIn()) {
441
433
  const userID = yield Auth.MyUserId();
442
434
  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) {
435
+ const response = yield fetcher(currentUserMangaList, { id: userID });
436
+ if (response === null || response === void 0 ? void 0 : response.data) {
456
437
  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
438
  if (lists.length > 0) {
458
439
  const { selectedList } = yield inquirer.prompt([
@@ -467,7 +448,7 @@ Statistics (Manga):
467
448
  const selectedEntries = lists.find((list) => list.name === selectedList);
468
449
  if (selectedEntries) {
469
450
  console.log(`\nDeleting entries of '${selectedEntries.name}':`);
470
- for (const [_, entry] of selectedEntries.entries.entries()) {
451
+ for (const [, entry] of selectedEntries.entries.entries()) {
471
452
  if (entry === null || entry === void 0 ? void 0 : entry.id) {
472
453
  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
454
  yield new Promise((resolve) => setTimeout(resolve, 1100));
@@ -499,33 +480,22 @@ Statistics (Manga):
499
480
  }
500
481
  }
501
482
  catch (error) {
502
- console.error(`\nError deleting manga.`);
483
+ console.error(`\nError deleting manga. ${error.message}`);
503
484
  }
504
485
  });
505
486
  }
506
487
  static DeleteMangaById(id, title) {
507
488
  return __awaiter(this, void 0, void 0, function* () {
508
- var _a, _b;
489
+ var _a, _b, _c, _d;
509
490
  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();
491
+ const response = yield fetcher(deleteMangaEntryMutation, { id });
522
492
  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;
493
+ if (response === null || response === void 0 ? void 0 : response.data) {
494
+ 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
495
  console.log(`del ${statusMessage} ${deleted ? "āœ…" : "āŒ"}`);
526
496
  }
527
497
  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}`);
498
+ 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
499
  }
530
500
  }
531
501
  catch (error) {
@@ -541,12 +511,9 @@ Statistics (Manga):
541
511
  console.error(`\nPlease login to use this feature.`);
542
512
  return;
543
513
  }
544
- const query = saveTextActivityMutation;
545
- const variables = {
546
- status: status +
547
- `<br><br><br><br>*Written using [@irfanshadikrishad/anilist](https://www.npmjs.com/package/@irfanshadikrishad/anilist).*`,
548
- };
549
- const data = yield fetcher(query, variables);
514
+ const data = yield fetcher(saveTextActivityMutation, {
515
+ status: status,
516
+ });
550
517
  if (!data) {
551
518
  console.error(`\nSomething went wrong. ${data}.`);
552
519
  return;
@@ -572,6 +539,7 @@ Statistics (Manga):
572
539
  choices: [
573
540
  { name: "Exported JSON file.", value: 1 },
574
541
  { name: "MyAnimeList (XML)", value: 2 },
542
+ { name: "AniDB (json-large)", value: 3 },
575
543
  ],
576
544
  pageSize: 10,
577
545
  },
@@ -583,6 +551,9 @@ Statistics (Manga):
583
551
  case 2:
584
552
  yield MyAnimeList.importAnime();
585
553
  break;
554
+ case 3:
555
+ yield AniDB.importAnime();
556
+ break;
586
557
  default:
587
558
  console.log(`\nInvalid Choice.`);
588
559
  break;
@@ -647,14 +618,14 @@ Statistics (Manga):
647
618
  const like = yield fetcher(likeActivityMutation, {
648
619
  activityId: activ.id,
649
620
  });
650
- console.info(`[${activ.id}] liked ${activ.user.name}`);
621
+ console.info(`${activityBy(activ)} ${(like === null || like === void 0 ? void 0 : like.data) ? "āœ…" : "āŒ"}`);
651
622
  }
652
623
  catch (error) {
653
- console.error(`Activity possibly deleted.`);
624
+ console.error(`Activity possibly deleted. ${error.message}`);
654
625
  }
655
626
  }
656
627
  else {
657
- console.log(`[${activ === null || activ === void 0 ? void 0 : activ.id}] ${activ.user.name} already-liked`);
628
+ console.log(`${activityBy(activ)} šŸ”µ`);
658
629
  }
659
630
  // avoiding rate-limit
660
631
  yield new Promise((resolve) => {
@@ -707,18 +678,18 @@ Statistics (Manga):
707
678
  activityId: activ.id,
708
679
  });
709
680
  // const ToggleLike = like?.data?.ToggleLike
710
- console.info(`[${activ.id}] liked ${activ.user.name}`);
681
+ console.info(`${activityBy(activ)} ${(like === null || like === void 0 ? void 0 : like.data) ? "āœ…" : "āŒ"}`);
711
682
  }
712
683
  catch (error) {
713
- console.error(`Activity possibly deleted.`);
684
+ console.error(`Activity possibly deleted. ${error.message}`);
714
685
  }
715
686
  }
716
687
  else {
717
- console.log(`[${activ === null || activ === void 0 ? void 0 : activ.id}] ${activ.user.name} already-liked`);
688
+ console.log(`${activityBy(activ)} šŸ”µ`);
718
689
  }
719
690
  // avoiding rate-limit
720
691
  yield new Promise((resolve) => {
721
- setTimeout(resolve, 2000);
692
+ setTimeout(resolve, 1500);
722
693
  });
723
694
  }
724
695
  page++;
@@ -738,7 +709,7 @@ Statistics (Manga):
738
709
  }
739
710
  static LikeSpecificUser() {
740
711
  return __awaiter(this, void 0, void 0, function* () {
741
- var _a, _b, _c, _d, _e, _f;
712
+ var _a, _b, _c, _d;
742
713
  try {
743
714
  const { username } = yield inquirer.prompt([
744
715
  {
@@ -771,18 +742,18 @@ Statistics (Manga):
771
742
  const like = yield fetcher(likeActivityMutation, {
772
743
  activityId: activ.id,
773
744
  });
774
- console.info(`[${activ.id}] liked ${(_e = activ.user) === null || _e === void 0 ? void 0 : _e.name}`);
745
+ console.info(`${activityBy(activ)} ${(like === null || like === void 0 ? void 0 : like.data) ? "āœ…" : "āŒ"}`);
775
746
  }
776
747
  catch (error) {
777
- console.error(`Activity possibly deleted.`);
748
+ console.error(`Activity possibly deleted. ${error.message}`);
778
749
  }
779
750
  }
780
751
  else {
781
- console.log(`[${activ === null || activ === void 0 ? void 0 : activ.id}] ${(_f = activ.user) === null || _f === void 0 ? void 0 : _f.name} already liked`);
752
+ console.log(`${activityBy(activ)} šŸ”µ`);
782
753
  }
783
754
  // Avoiding rate limit
784
755
  yield new Promise((resolve) => {
785
- setTimeout(resolve, 2000);
756
+ setTimeout(resolve, 1500);
786
757
  });
787
758
  }
788
759
  // Go to the next page
@@ -796,6 +767,79 @@ Statistics (Manga):
796
767
  }
797
768
  });
798
769
  }
770
+ static LikeFollowingActivityV2(perPage) {
771
+ return __awaiter(this, void 0, void 0, function* () {
772
+ var _a, _b, _c, _d, _e;
773
+ try {
774
+ if (!(yield Auth.isLoggedIn())) {
775
+ console.error(`\nPlease log in to use this feature.`);
776
+ return;
777
+ }
778
+ const allFollowingUsers = [];
779
+ let hasNextPage = true;
780
+ let page = 1;
781
+ // Fetch all following users
782
+ while (hasNextPage) {
783
+ const followingUsers = yield fetcher(userFollowingQuery, {
784
+ userId: yield Auth.MyUserId(),
785
+ page,
786
+ });
787
+ if (!((_b = (_a = followingUsers === null || followingUsers === void 0 ? void 0 : followingUsers.data) === null || _a === void 0 ? void 0 : _a.Page) === null || _b === void 0 ? void 0 : _b.following)) {
788
+ console.error(`\nFailed to fetch following users.`);
789
+ return;
790
+ }
791
+ allFollowingUsers.push(...followingUsers.data.Page.following);
792
+ hasNextPage = followingUsers.data.Page.pageInfo.hasNextPage;
793
+ page++;
794
+ }
795
+ // Extract the IDs of all following users
796
+ const followingUserIds = allFollowingUsers.map((user) => user.id);
797
+ console.log(`\nTotal Following: ${followingUserIds.length}\nApproximately ${followingUserIds.length * perPage} activities to like.\nWill take around ${((followingUserIds.length * perPage * 1200) /
798
+ 1000 /
799
+ 60).toFixed(2)} minutes.`);
800
+ // Traverse the array and fetch users' activities one by one
801
+ let userNumber = 0;
802
+ for (const userId of followingUserIds) {
803
+ userNumber++;
804
+ console.log(`\n[${userNumber}]\tID: ${userId}`);
805
+ // Fetch `perPage` activities for the current user
806
+ const activities = yield fetcher(specificUserActivitiesQuery, {
807
+ userId,
808
+ page: 1, // Always fetch from the first page
809
+ perPage,
810
+ });
811
+ if (!((_e = (_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) === null || _e === void 0 ? void 0 : _e.length)) {
812
+ console.log(`[${userNumber}] No activities found for User ID: ${userId}`);
813
+ continue;
814
+ }
815
+ const activiti = activities.data.Page.activities;
816
+ for (let i = 0; i < activiti.length; i++) {
817
+ const activ = activiti[i];
818
+ if (!activ.isLiked && activ.id) {
819
+ try {
820
+ const like = yield fetcher(likeActivityMutation, {
821
+ activityId: activ.id,
822
+ });
823
+ console.info(`[${userNumber}/${i + 1}/${activiti.length}] ${activityBy(activ)} ${(like === null || like === void 0 ? void 0 : like.data) ? "āœ…" : "āŒ"}`);
824
+ }
825
+ catch (error) {
826
+ console.error(`[${userNumber}/${i + 1}/${activiti.length}] Activity possibly deleted. ${error.message}`);
827
+ }
828
+ }
829
+ else {
830
+ console.log(`[${userNumber}/${i + 1}/${activiti.length}] ${activityBy(activ)} šŸ”µ`);
831
+ }
832
+ // Avoid rate-limiting
833
+ yield new Promise((resolve) => setTimeout(resolve, 1200));
834
+ }
835
+ }
836
+ console.log(`\nāœ… All activities liked successfully.`);
837
+ }
838
+ catch (error) {
839
+ console.error(`\nError in LikeFollowingActivityV2: ${error.message}`);
840
+ }
841
+ });
842
+ }
799
843
  static AutoLike() {
800
844
  return __awaiter(this, void 0, void 0, function* () {
801
845
  try {
@@ -2,11 +2,12 @@
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.
9
10
  * @returns {Promise<object|null>} The response from the API as a JSON object if successful; otherwise, null.
10
11
  */
11
- declare function fetcher(query: string, variables?: object): Promise<any | null>;
12
+ declare function fetcher(query: string, variables: object): Promise<object | null>;
12
13
  export { fetcher };