@irfanshadikrishad/anilist 1.0.11 → 1.1.1-forbidden.0

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.
@@ -19,5 +19,8 @@ declare class Auth {
19
19
  static Write(status: string): Promise<void>;
20
20
  static callAnimeImporter(): Promise<void>;
21
21
  static callMangaImporter(): Promise<void>;
22
+ private static Like;
23
+ private static LikeSpecificUser;
24
+ static AutoLike(): Promise<void>;
22
25
  }
23
26
  export { Auth };
@@ -15,8 +15,8 @@ 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";
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
20
  import { aniListEndpoint, getTitle, redirectUri } from "./workers.js";
21
21
  const home_dir = os.homedir();
22
22
  const save_path = path.join(home_dir, ".anilist_token");
@@ -625,5 +625,158 @@ Statistics (Manga):
625
625
  }
626
626
  });
627
627
  }
628
+ static Like(type) {
629
+ return __awaiter(this, void 0, void 0, function* () {
630
+ var _a, _b, _c, _d;
631
+ try {
632
+ let page = 1;
633
+ let hasMoreActivities = true;
634
+ let activity = type === 0
635
+ ? followingActivitiesQuery
636
+ : type === 1
637
+ ? globalActivitiesQuery
638
+ : followingActivitiesQuery;
639
+ while (hasMoreActivities) {
640
+ const activities = yield fetcher(activity, {
641
+ page,
642
+ perPage: 50,
643
+ });
644
+ 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) {
645
+ 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;
646
+ for (let activ of activiti) {
647
+ if (!activ.isLiked && activ.id) {
648
+ try {
649
+ const like = yield fetcher(likeActivityMutation, {
650
+ activityId: activ.id,
651
+ });
652
+ // const ToggleLike = like?.data?.ToggleLike
653
+ console.info(`[${activ.id}] liked ${activ.user.name}`);
654
+ }
655
+ catch (error) {
656
+ console.error(`Activity possibly deleted.`);
657
+ }
658
+ }
659
+ else {
660
+ console.log(`[${activ === null || activ === void 0 ? void 0 : activ.id}] ${activ.user.name} already-liked`);
661
+ }
662
+ // avoiding rate-limit
663
+ yield new Promise((resolve) => {
664
+ setTimeout(resolve, 2000);
665
+ });
666
+ }
667
+ page++;
668
+ }
669
+ else {
670
+ // No more activities to like
671
+ console.log(`\nProbably the end of activities.`);
672
+ console.info(activities);
673
+ hasMoreActivities = false;
674
+ }
675
+ }
676
+ }
677
+ catch (error) {
678
+ console.error(`\nError from likeFollowing. ${error.message}`);
679
+ }
680
+ });
681
+ }
682
+ static LikeSpecificUser() {
683
+ return __awaiter(this, void 0, void 0, function* () {
684
+ var _a, _b, _c, _d, _e, _f;
685
+ try {
686
+ const { username } = yield inquirer.prompt([
687
+ {
688
+ type: "input",
689
+ name: "username",
690
+ message: "Username of the user:",
691
+ },
692
+ ]);
693
+ const userDetails = yield fetcher(userQuery, { username: username });
694
+ if (userDetails) {
695
+ let page = 1;
696
+ const perPage = 50;
697
+ 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;
698
+ if (userId) {
699
+ while (true) {
700
+ const activities = yield fetcher(specificUserActivitiesQuery, {
701
+ page,
702
+ perPage,
703
+ userId,
704
+ });
705
+ 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;
706
+ // Break the loop if no more activities are found
707
+ if (!activiti || activiti.length === 0) {
708
+ console.log("No more activities found.");
709
+ break;
710
+ }
711
+ for (let activ of activiti) {
712
+ if (!activ.isLiked && activ.id) {
713
+ try {
714
+ const like = yield fetcher(likeActivityMutation, {
715
+ activityId: activ.id,
716
+ });
717
+ console.info(`[${activ.id}] liked ${(_e = activ.user) === null || _e === void 0 ? void 0 : _e.name}`);
718
+ }
719
+ catch (error) {
720
+ console.error(`Activity possibly deleted.`);
721
+ }
722
+ }
723
+ else {
724
+ console.log(`[${activ === null || activ === void 0 ? void 0 : activ.id}] ${(_f = activ.user) === null || _f === void 0 ? void 0 : _f.name} already liked`);
725
+ }
726
+ // Avoiding rate limit
727
+ yield new Promise((resolve) => {
728
+ setTimeout(resolve, 2000);
729
+ });
730
+ }
731
+ // Go to the next page
732
+ page += 1;
733
+ }
734
+ }
735
+ }
736
+ }
737
+ catch (error) {
738
+ console.error(`\nError from LikeSpecificUser. ${error.message}`);
739
+ }
740
+ });
741
+ }
742
+ static AutoLike() {
743
+ return __awaiter(this, void 0, void 0, function* () {
744
+ try {
745
+ if (!(yield Auth.isLoggedIn())) {
746
+ console.error(`\nPlease login to use this feature.`);
747
+ return;
748
+ }
749
+ const { activityType } = yield inquirer.prompt([
750
+ {
751
+ type: "list",
752
+ name: "activityType",
753
+ message: "Select activity type:",
754
+ choices: [
755
+ { name: "Following", value: 1 },
756
+ { name: "Global", value: 2 },
757
+ { name: "Specific User", value: 3 },
758
+ ],
759
+ pageSize: 10,
760
+ },
761
+ ]);
762
+ switch (activityType) {
763
+ case 1:
764
+ yield this.Like(0);
765
+ break;
766
+ case 2:
767
+ yield this.Like(1);
768
+ break;
769
+ case 3:
770
+ yield this.LikeSpecificUser();
771
+ break;
772
+ default:
773
+ console.error(`\nInvalid choice. (${activityType})`);
774
+ }
775
+ }
776
+ catch (error) {
777
+ console.error(`\nError from autolike. ${error.message}`);
778
+ }
779
+ });
780
+ }
628
781
  }
629
782
  export { Auth };
@@ -8,5 +8,5 @@
8
8
  * @param {object} variables - An object containing the variables for the query.
9
9
  * @returns {Promise<object|null>} The response from the API as a JSON object if successful; otherwise, null.
10
10
  */
11
- declare function fetcher(query: string, variables: object): Promise<object | null>;
11
+ declare function fetcher(query: string, variables?: object): Promise<any | null>;
12
12
  export { fetcher };
@@ -9,7 +9,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import fetch from "node-fetch";
11
11
  import { Auth } from "./auth.js";
12
- import { aniListEndpoint } from "./workers.js";
13
12
  /**
14
13
  * Sends a GraphQL request to the AniList API.
15
14
  *
@@ -22,32 +21,34 @@ import { aniListEndpoint } from "./workers.js";
22
21
  */
23
22
  function fetcher(query, variables) {
24
23
  return __awaiter(this, void 0, void 0, function* () {
25
- var _a;
26
- try {
27
- const headers = {
28
- "content-type": "application/json",
29
- };
30
- if (yield Auth.isLoggedIn()) {
31
- headers["Authorization"] = `Bearer ${yield Auth.RetriveAccessToken()}`;
32
- }
33
- const request = yield fetch(aniListEndpoint, {
34
- method: "POST",
35
- headers: headers,
36
- body: JSON.stringify({ query, variables }),
37
- });
38
- const response = yield request.json();
39
- if (request.status === 200) {
40
- return response;
24
+ const headers = {
25
+ "content-type": "application/json",
26
+ };
27
+ if (yield Auth.isLoggedIn()) {
28
+ headers["Authorization"] = `Bearer ${yield Auth.RetriveAccessToken()}`;
29
+ }
30
+ const response = yield fetch("https://graphql.anilist.co", {
31
+ method: "POST",
32
+ headers: headers,
33
+ body: JSON.stringify({
34
+ query,
35
+ variables,
36
+ }),
37
+ });
38
+ // Check if the response is successful
39
+ if (response.status !== 200) {
40
+ // If the status is 429, handle the rate limit
41
+ if (response.status === 429) {
42
+ console.warn("Rate limit hit. Waiting for 1 minute before retrying...");
43
+ yield new Promise((resolve) => setTimeout(resolve, 60000)); // Wait for 1 minute
44
+ return fetcher(query, variables); // Retry the request
41
45
  }
42
46
  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}.`);
44
- return null;
47
+ throw new Error(`\nError fetching data: ${response.statusText}`);
45
48
  }
46
49
  }
47
- catch (error) {
48
- console.error(`\nSomething went wrong. ${error.message}.`);
49
- return null;
50
- }
50
+ const data = yield response.json();
51
+ return data;
51
52
  });
52
53
  }
53
54
  export { fetcher };
@@ -4,4 +4,5 @@ declare const deleteActivityMutation = "\nmutation($id: Int!) {\n DeleteActivit
4
4
  declare const saveTextActivityMutation = "\nmutation SaveTextActivity($status: String!) {\n SaveTextActivity(text: $status) { id text userId createdAt }\n}\n";
5
5
  declare const saveAnimeWithProgressMutation = "\nmutation ($mediaId: Int, $progress: Int, $status: MediaListStatus, $hiddenFromStatusLists: Boolean) {\n SaveMediaListEntry(mediaId: $mediaId, progress: $progress, status: $status, hiddenFromStatusLists: $hiddenFromStatusLists) {\n id progress hiddenFromStatusLists\n }\n}\n";
6
6
  declare const saveMangaWithProgressMutation = "\nmutation ($mediaId: Int, $progress: Int, $status: MediaListStatus, $hiddenFromStatusLists: Boolean, $private: Boolean) {\n SaveMediaListEntry( mediaId: $mediaId, progress: $progress, status: $status, hiddenFromStatusLists: $hiddenFromStatusLists, private: $private\n ) { id progress hiddenFromStatusLists private }\n}\n";
7
- export { addAnimeToListMutation, addMangaToListMutation, deleteActivityMutation, saveAnimeWithProgressMutation, saveMangaWithProgressMutation, saveTextActivityMutation, };
7
+ declare const likeActivityMutation = "\nmutation($activityId: Int!) {\n ToggleLike(id: $activityId, type: ACTIVITY) { id }\n}\n";
8
+ export { addAnimeToListMutation, addMangaToListMutation, deleteActivityMutation, likeActivityMutation, saveAnimeWithProgressMutation, saveMangaWithProgressMutation, saveTextActivityMutation, };
@@ -35,4 +35,9 @@ mutation ($mediaId: Int, $progress: Int, $status: MediaListStatus, $hiddenFromSt
35
35
  ) { id progress hiddenFromStatusLists private }
36
36
  }
37
37
  `;
38
- export { addAnimeToListMutation, addMangaToListMutation, deleteActivityMutation, saveAnimeWithProgressMutation, saveMangaWithProgressMutation, saveTextActivityMutation, };
38
+ const likeActivityMutation = `
39
+ mutation($activityId: Int!) {
40
+ ToggleLike(id: $activityId, type: ACTIVITY) { id }
41
+ }
42
+ `;
43
+ export { addAnimeToListMutation, addMangaToListMutation, deleteActivityMutation, likeActivityMutation, saveAnimeWithProgressMutation, saveMangaWithProgressMutation, saveTextActivityMutation, };
@@ -17,6 +17,9 @@ declare const activityMangaListQuery = "query ($userId: Int, $page: Int, $perPag
17
17
  declare const activityMessageQuery = "query ($userId: Int, $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n activities(userId: $userId, type: MESSAGE, sort: ID_DESC) {\n ... on MessageActivity { id type message recipient { id name } createdAt }\n }\n }\n}";
18
18
  declare const activityAllQuery = "query ($userId: Int, $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n activities(userId: $userId, sort: ID_DESC) {\n ... on TextActivity { id type text createdAt user { id name } }\n ... on ListActivity { id type status progress createdAt media { id title { romaji english native } } }\n ... on MessageActivity { id type message recipient { id name } createdAt }\n }\n }\n}";
19
19
  declare const activityMediaList = "query ($userId: Int, $page: Int, $perPage: Int, $type: ActivityType) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total currentPage lastPage hasNextPage perPage }\n activities(userId: $userId, type: $type, sort: ID_DESC) {\n ... on ListActivity { id type status progress media { id title { romaji english native } format } createdAt }\n }\n }\n}";
20
- declare const malIdToAnilistAnimeId = "query ($malId: Int) {\n Media(idMal: $malId, type: ANIME) {\n id title { romaji english } } \n}\n";
21
- declare const malIdToAnilistMangaId = "query ($malId: Int) {\n Media(idMal: $malId, type: MANGA) {\n id title { romaji english } } \n}\n";
22
- export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userQuery, };
20
+ declare const malIdToAnilistAnimeId = "query ($malId: Int) {\n Media(idMal: $malId, type: ANIME) { id title { romaji english } } }\n";
21
+ declare const malIdToAnilistMangaId = "query ($malId: Int) {\n Media(idMal: $malId, type: MANGA) { id title { romaji english } } }\n";
22
+ declare const followingActivitiesQuery = "\nquery ($page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n activities(isFollowing: true, sort: ID_DESC) {\n ... on TextActivity { id type isLiked createdAt user { id name } }\n ... on ListActivity { id type isLiked status progress media { title { userPreferred } } createdAt user { id name } }\n ... on MessageActivity { id type isLiked message createdAt recipient { id name } }\n }\n }\n}\n";
23
+ declare const globalActivitiesQuery = "\nquery ($page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n activities(sort: ID_DESC) {\n ... on TextActivity { id type isLiked createdAt user { id name } }\n ... on ListActivity { id type isLiked status progress media { title { userPreferred } } createdAt user { id name } }\n ... on MessageActivity { id type isLiked message createdAt recipient { id name } }\n }\n }\n}\n";
24
+ declare const specificUserActivitiesQuery = "\nquery ($page: Int, $perPage: Int, $userId: Int) {\n Page(page: $page, perPage: $perPage) {\n activities(userId: $userId, sort: ID_DESC) {\n ... on TextActivity { id type isLiked createdAt user { id name } }\n ... on ListActivity { id type isLiked status progress media { title { userPreferred } } createdAt user { id name } }\n ... on MessageActivity { id type isLiked message createdAt recipient { id name } }\n }\n }\n}\n";
25
+ export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, followingActivitiesQuery, globalActivitiesQuery, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, specificUserActivitiesQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userQuery, };
@@ -120,13 +120,42 @@ const activityMediaList = `query ($userId: Int, $page: Int, $perPage: Int, $type
120
120
  }
121
121
  }`;
122
122
  const malIdToAnilistAnimeId = `query ($malId: Int) {
123
- Media(idMal: $malId, type: ANIME) {
124
- id title { romaji english } }
125
- }
123
+ Media(idMal: $malId, type: ANIME) { id title { romaji english } } }
126
124
  `;
127
125
  const malIdToAnilistMangaId = `query ($malId: Int) {
128
- Media(idMal: $malId, type: MANGA) {
129
- id title { romaji english } }
126
+ Media(idMal: $malId, type: MANGA) { id title { romaji english } } }
127
+ `;
128
+ const followingActivitiesQuery = `
129
+ query ($page: Int, $perPage: Int) {
130
+ Page(page: $page, perPage: $perPage) {
131
+ activities(isFollowing: true, sort: ID_DESC) {
132
+ ... on TextActivity { id type isLiked createdAt user { id name } }
133
+ ... on ListActivity { id type isLiked status progress media { title { userPreferred } } createdAt user { id name } }
134
+ ... on MessageActivity { id type isLiked message createdAt recipient { id name } }
135
+ }
136
+ }
137
+ }
138
+ `;
139
+ const globalActivitiesQuery = `
140
+ query ($page: Int, $perPage: Int) {
141
+ Page(page: $page, perPage: $perPage) {
142
+ activities(sort: ID_DESC) {
143
+ ... on TextActivity { id type isLiked createdAt user { id name } }
144
+ ... on ListActivity { id type isLiked status progress media { title { userPreferred } } createdAt user { id name } }
145
+ ... on MessageActivity { id type isLiked message createdAt recipient { id name } }
146
+ }
147
+ }
148
+ }
149
+ `;
150
+ const specificUserActivitiesQuery = `
151
+ query ($page: Int, $perPage: Int, $userId: Int) {
152
+ Page(page: $page, perPage: $perPage) {
153
+ activities(userId: $userId, sort: ID_DESC) {
154
+ ... on TextActivity { id type isLiked createdAt user { id name } }
155
+ ... on ListActivity { id type isLiked status progress media { title { userPreferred } } createdAt user { id name } }
156
+ ... on MessageActivity { id type isLiked message createdAt recipient { id name } }
157
+ }
158
+ }
130
159
  }
131
160
  `;
132
- export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userQuery, };
161
+ export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, followingActivitiesQuery, globalActivitiesQuery, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, specificUserActivitiesQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userQuery, };
package/bin/index.js CHANGED
@@ -16,7 +16,7 @@ const cli = new Command();
16
16
  cli
17
17
  .name("anilist")
18
18
  .description("Minimalist unofficial AniList CLI for Anime and Manga Enthusiasts.")
19
- .version("1.0.11");
19
+ .version("1.1.1-forbidden.0");
20
20
  cli
21
21
  .command("login")
22
22
  .description("Login with AniList")
@@ -202,4 +202,11 @@ cli
202
202
  }
203
203
  }
204
204
  }));
205
+ cli
206
+ .command("autolike")
207
+ .alias("al")
208
+ .description("Autolike following or global activities.")
209
+ .action(() => __awaiter(void 0, void 0, void 0, function* () {
210
+ yield Auth.AutoLike();
211
+ }));
205
212
  cli.parse(process.argv);
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@irfanshadikrishad/anilist",
3
3
  "description": "Minimalist unofficial AniList CLI for Anime and Manga Enthusiasts",
4
4
  "author": "Irfan Shadik Rishad",
5
- "version": "1.0.11",
5
+ "version": "1.1.1-forbidden.0",
6
6
  "main": "./bin/index.js",
7
7
  "type": "module",
8
8
  "types": "./bin/index.d.ts",