@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 +32 -26
- package/bin/helpers/auth.d.ts +36 -6
- package/bin/helpers/auth.js +139 -95
- package/bin/helpers/fetcher.d.ts +3 -2
- package/bin/helpers/fetcher.js +29 -24
- package/bin/helpers/lists.d.ts +4 -1
- package/bin/helpers/lists.js +357 -268
- package/bin/helpers/queries.d.ts +6 -4
- package/bin/helpers/queries.js +19 -4
- package/bin/helpers/types.d.ts +304 -8
- package/bin/helpers/workers.d.ts +9 -5
- package/bin/helpers/workers.js +155 -69
- package/bin/index.js +13 -9
- package/package.json +18 -10
- package/assets/binance.jpg +0 -0
- /package/{LICENSE ā LICENSE.md} +0 -0
package/README.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Minimalist unofficial AniList CLI for Anime and Manga Enthusiasts.
|
|
4
4
|
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
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
|
-
|
|
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
|
-
| **`
|
|
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> `-
|
|
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
|
|
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
|
|
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 š_**
|
package/bin/helpers/auth.d.ts
CHANGED
|
@@ -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<
|
|
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<
|
|
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<
|
|
13
|
-
static MyUserName(): Promise<
|
|
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?:
|
|
45
|
+
static DeleteAnimeById(id: number, title?: MediaTitle): Promise<void>;
|
|
17
46
|
static DeleteMyMangaList(): Promise<void>;
|
|
18
|
-
static DeleteMangaById(id: number, title?:
|
|
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 };
|
package/bin/helpers/auth.js
CHANGED
|
@@ -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: ${(
|
|
138
|
-
timeZone: ${(
|
|
139
|
-
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: ${(
|
|
148
|
-
Mean Score: ${(
|
|
149
|
-
Minutes Watched: ${(
|
|
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: ${(
|
|
153
|
-
|
|
154
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
|
348
|
-
|
|
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 [
|
|
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
|
|
411
|
-
|
|
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
|
|
444
|
-
|
|
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 [
|
|
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
|
|
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 (
|
|
524
|
-
const deleted = (_a =
|
|
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. ${(
|
|
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
|
|
545
|
-
|
|
546
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
688
|
+
console.log(`${activityBy(activ)} šµ`);
|
|
718
689
|
}
|
|
719
690
|
// avoiding rate-limit
|
|
720
691
|
yield new Promise((resolve) => {
|
|
721
|
-
setTimeout(resolve,
|
|
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
|
|
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(
|
|
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(
|
|
752
|
+
console.log(`${activityBy(activ)} šµ`);
|
|
782
753
|
}
|
|
783
754
|
// Avoiding rate limit
|
|
784
755
|
yield new Promise((resolve) => {
|
|
785
|
-
setTimeout(resolve,
|
|
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 {
|
package/bin/helpers/fetcher.d.ts
CHANGED
|
@@ -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
|
|
12
|
+
declare function fetcher(query: string, variables: object): Promise<object | null>;
|
|
12
13
|
export { fetcher };
|