@irfanshadikrishad/anilist 1.4.6 ā 1.4.8
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/CITATION.cff +8 -0
- package/bin/helpers/auth.d.ts +2 -30
- package/bin/helpers/auth.js +2 -2
- package/bin/helpers/fetcher.js +8 -7
- package/bin/helpers/lists.js +5 -31
- package/bin/helpers/mutations.d.ts +7 -4
- package/bin/helpers/mutations.js +9 -10
- package/bin/helpers/queries.d.ts +3 -6
- package/bin/helpers/queries.js +3 -17
- package/bin/helpers/types.d.ts +55 -115
- package/bin/helpers/workers.d.ts +4 -2
- package/bin/helpers/workers.js +56 -1
- package/package.json +6 -6
package/CITATION.cff
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite it as below."
|
|
3
|
+
title: "@irfanshadikrishad/anilist"
|
|
4
|
+
authors:
|
|
5
|
+
- name: "Irfan Shadik Rishad"
|
|
6
|
+
orcid: "0009-0001-6745-5291"
|
|
7
|
+
date-released: "2024-10-12"
|
|
8
|
+
repository-code: "https://github.com/irfanshadikrishad/anilist"
|
package/bin/helpers/auth.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MediaTitle } from "./types.js";
|
|
1
|
+
import { MediaTitle, User } from "./types.js";
|
|
2
2
|
declare class Auth {
|
|
3
3
|
/**
|
|
4
4
|
* Get access-token from user
|
|
@@ -7,35 +7,7 @@ declare class Auth {
|
|
|
7
7
|
static StoreAccessToken(token: string): Promise<void>;
|
|
8
8
|
static RetriveAccessToken(): Promise<string | null>;
|
|
9
9
|
static Login(clientId: number, clientSecret: string): Promise<void>;
|
|
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
|
+
static Myself(): Promise<User>;
|
|
39
11
|
static isLoggedIn(): Promise<boolean>;
|
|
40
12
|
static Logout(): Promise<void>;
|
|
41
13
|
static MyUserId(): Promise<number>;
|
package/bin/helpers/auth.js
CHANGED
|
@@ -17,8 +17,8 @@ import path from "path";
|
|
|
17
17
|
import Spinner from "tiny-spinner";
|
|
18
18
|
import { fetcher } from "./fetcher.js";
|
|
19
19
|
import { AniDB, AniList, MyAnimeList } from "./lists.js";
|
|
20
|
-
import { deleteActivityMutation, saveTextActivityMutation, } from "./mutations.js";
|
|
21
|
-
import { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery,
|
|
20
|
+
import { deleteActivityMutation, deleteMangaEntryMutation, deleteMediaEntryMutation, saveTextActivityMutation, toggleFollowMutation, } from "./mutations.js";
|
|
21
|
+
import { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, } from "./queries.js";
|
|
22
22
|
import { responsiveOutput } from "./truncate.js";
|
|
23
23
|
import { aniListEndpoint, getTitle, redirectUri, timestampToTimeAgo, } from "./workers.js";
|
|
24
24
|
const home_dir = os.homedir();
|
package/bin/helpers/fetcher.js
CHANGED
|
@@ -9,7 +9,7 @@ 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";
|
|
12
|
+
import { aniListEndpoint, handleRateLimitRetry } from "./workers.js";
|
|
13
13
|
/**
|
|
14
14
|
* Sends a GraphQL request to the AniList API.
|
|
15
15
|
*
|
|
@@ -28,9 +28,11 @@ function fetcher(query, variables) {
|
|
|
28
28
|
const headers = {
|
|
29
29
|
"content-type": "application/json",
|
|
30
30
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
const token = (yield Auth.isLoggedIn())
|
|
32
|
+
? yield Auth.RetriveAccessToken()
|
|
33
|
+
: null;
|
|
34
|
+
if (token)
|
|
35
|
+
headers["Authorization"] = `Bearer ${token}`;
|
|
34
36
|
const request = yield fetch(aniListEndpoint, {
|
|
35
37
|
method: "POST",
|
|
36
38
|
headers: headers,
|
|
@@ -41,9 +43,8 @@ function fetcher(query, variables) {
|
|
|
41
43
|
return response;
|
|
42
44
|
}
|
|
43
45
|
else if (request.status === 429) {
|
|
44
|
-
|
|
45
|
-
yield
|
|
46
|
-
return yield fetcher(query, variables); // Retry the request
|
|
46
|
+
yield handleRateLimitRetry(60);
|
|
47
|
+
return yield fetcher(query, variables);
|
|
47
48
|
}
|
|
48
49
|
else {
|
|
49
50
|
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"}.`);
|
package/bin/helpers/lists.js
CHANGED
|
@@ -19,7 +19,7 @@ import { animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserM
|
|
|
19
19
|
import { responsiveOutput } from "./truncate.js";
|
|
20
20
|
import { AniListMediaStatus, } from "./types.js";
|
|
21
21
|
import { Validate } from "./validation.js";
|
|
22
|
-
import { anidbToanilistMapper, formatDateObject, getDownloadFolderPath, getNextSeasonAndYear, getTitle, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, saveJSONasXML, selectFile, simpleDateFormat, timestampToTimeAgo, } from "./workers.js";
|
|
22
|
+
import { anidbToanilistMapper, formatDateObject, getDownloadFolderPath, getNextSeasonAndYear, getTitle, logUserDetails, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, saveJSONasXML, selectFile, simpleDateFormat, timestampToTimeAgo, } from "./workers.js";
|
|
23
23
|
class AniList {
|
|
24
24
|
static importAnime() {
|
|
25
25
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -36,8 +36,7 @@ class AniList {
|
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
38
|
let count = 0;
|
|
39
|
-
const batchSize = 1;
|
|
40
|
-
const delay = 1100; // delay to avoid rate-limiting
|
|
39
|
+
const batchSize = 1;
|
|
41
40
|
for (let i = 0; i < importedData.length; i += batchSize) {
|
|
42
41
|
const batch = importedData.slice(i, i + batchSize);
|
|
43
42
|
yield Promise.all(batch.map((anime) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -64,8 +63,6 @@ class AniList {
|
|
|
64
63
|
console.error(`\nError saving ${anime === null || anime === void 0 ? void 0 : anime.id}: ${error.message}`);
|
|
65
64
|
}
|
|
66
65
|
})));
|
|
67
|
-
// Avoid rate-limiting: Wait before sending the next batch
|
|
68
|
-
yield new Promise((resolve) => setTimeout(resolve, delay));
|
|
69
66
|
}
|
|
70
67
|
console.log(`\nTotal ${count} anime(s) imported successfully.`);
|
|
71
68
|
}
|
|
@@ -89,9 +86,7 @@ class AniList {
|
|
|
89
86
|
return;
|
|
90
87
|
}
|
|
91
88
|
let count = 0;
|
|
92
|
-
const batchSize = 1;
|
|
93
|
-
const delay = 1100; // 2 seconds delay to avoid rate-limit
|
|
94
|
-
// Process in batches
|
|
89
|
+
const batchSize = 1;
|
|
95
90
|
for (let i = 0; i < importedData.length; i += batchSize) {
|
|
96
91
|
const batch = importedData.slice(i, i + batchSize);
|
|
97
92
|
yield Promise.all(batch.map((manga) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -116,8 +111,6 @@ class AniList {
|
|
|
116
111
|
console.error(`\nError saving ${manga === null || manga === void 0 ? void 0 : manga.id}: ${err.message}`);
|
|
117
112
|
}
|
|
118
113
|
})));
|
|
119
|
-
// Avoid rate-limit by adding delay after processing each batch
|
|
120
|
-
yield new Promise((resolve) => setTimeout(resolve, delay));
|
|
121
114
|
}
|
|
122
115
|
console.log(`\nTotal ${count} manga(s) imported successfully.`);
|
|
123
116
|
}
|
|
@@ -621,7 +614,7 @@ class AniList {
|
|
|
621
614
|
}
|
|
622
615
|
static getUserByUsername(username) {
|
|
623
616
|
return __awaiter(this, void 0, void 0, function* () {
|
|
624
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m
|
|
617
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
625
618
|
try {
|
|
626
619
|
const response = yield fetcher(userQuery, { username });
|
|
627
620
|
if (!((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.User)) {
|
|
@@ -643,22 +636,7 @@ class AniList {
|
|
|
643
636
|
});
|
|
644
637
|
const followersCount = ((_j = (_h = (_g = req_followers === null || req_followers === void 0 ? void 0 : req_followers.data) === null || _g === void 0 ? void 0 : _g.Page) === null || _h === void 0 ? void 0 : _h.pageInfo) === null || _j === void 0 ? void 0 : _j.total) || 0;
|
|
645
638
|
const followingCount = ((_m = (_l = (_k = req_following === null || req_following === void 0 ? void 0 : req_following.data) === null || _k === void 0 ? void 0 : _k.Page) === null || _l === void 0 ? void 0 : _l.pageInfo) === null || _m === void 0 ? void 0 : _m.total) || 0;
|
|
646
|
-
|
|
647
|
-
console.log(`Name:\t\t${user.name}`);
|
|
648
|
-
console.log(`Site URL:\t${user.siteUrl}`);
|
|
649
|
-
console.log(`Donator Tier:\t${user.donatorTier}`);
|
|
650
|
-
console.log(`Donator Badge:\t${user.donatorBadge}`);
|
|
651
|
-
console.log(`Account Created:\t${user.createdAt ? new Date(user.createdAt * 1000).toUTCString() : "N/A"}`);
|
|
652
|
-
console.log(`Account Updated:\t${user.updatedAt ? new Date(user.updatedAt * 1000).toUTCString() : "N/A"}`);
|
|
653
|
-
console.log(`Blocked:\t${user.isBlocked}`);
|
|
654
|
-
console.log(`Follower:\t${user.isFollower}`);
|
|
655
|
-
console.log(`Following:\t${user.isFollowing}`);
|
|
656
|
-
console.log(`Profile Color:\t${(_o = user.options) === null || _o === void 0 ? void 0 : _o.profileColor}`);
|
|
657
|
-
console.log(`Timezone:\t${((_p = user.options) === null || _p === void 0 ? void 0 : _p.timezone) ? (_q = user.options) === null || _q === void 0 ? void 0 : _q.timezone : "N/A"}`);
|
|
658
|
-
console.log(`\nFollowers:\t${followersCount}`);
|
|
659
|
-
console.log(`Following:\t${followingCount}`);
|
|
660
|
-
console.log(`\nStatistics (Anime)\n\tCount: ${((_s = (_r = user.statistics) === null || _r === void 0 ? void 0 : _r.anime) === null || _s === void 0 ? void 0 : _s.count) || 0}\tEpisodes Watched: ${((_u = (_t = user.statistics) === null || _t === void 0 ? void 0 : _t.anime) === null || _u === void 0 ? void 0 : _u.episodesWatched) || 0}\tMinutes Watched: ${((_w = (_v = user.statistics) === null || _v === void 0 ? void 0 : _v.anime) === null || _w === void 0 ? void 0 : _w.minutesWatched) || 0}`);
|
|
661
|
-
console.log(`Statistics (Manga)\n\tCount: ${((_y = (_x = user.statistics) === null || _x === void 0 ? void 0 : _x.manga) === null || _y === void 0 ? void 0 : _y.count) || 0}\tChapters Read: ${((_0 = (_z = user.statistics) === null || _z === void 0 ? void 0 : _z.manga) === null || _0 === void 0 ? void 0 : _0.chaptersRead) || 0}\tVolumes Read: ${((_2 = (_1 = user.statistics) === null || _1 === void 0 ? void 0 : _1.manga) === null || _2 === void 0 ? void 0 : _2.volumesRead) || 0}`);
|
|
639
|
+
logUserDetails(user, followersCount, followingCount);
|
|
662
640
|
if (activities.length > 0) {
|
|
663
641
|
console.log(`\nRecent Activities:`);
|
|
664
642
|
activities.forEach(({ status, progress, media, createdAt }) => {
|
|
@@ -895,8 +873,6 @@ class MyAnimeList {
|
|
|
895
873
|
count++;
|
|
896
874
|
console.log(`[${count}] ${entryId} ā
`);
|
|
897
875
|
}
|
|
898
|
-
// Rate limit each API call to avoid server overload
|
|
899
|
-
yield new Promise((resolve) => setTimeout(resolve, 1100));
|
|
900
876
|
}
|
|
901
877
|
else {
|
|
902
878
|
console.error(`Could not retrieve AniList ID for MAL ID ${malId}`);
|
|
@@ -1122,8 +1098,6 @@ class AniDB {
|
|
|
1122
1098
|
count++;
|
|
1123
1099
|
responsiveOutput(`[${count}]\t${entryId} ā
\t${anidbId}\t${anilistId}\t(${ownEpisodes}/${totalEpisodes})\t${status}ā>${getStatus(status, ownEpisodes)}`);
|
|
1124
1100
|
}
|
|
1125
|
-
// Rate limit each API call to avoid server overload
|
|
1126
|
-
// await new Promise((resolve) => setTimeout(resolve, 1100))
|
|
1127
1101
|
}
|
|
1128
1102
|
catch (error) {
|
|
1129
1103
|
console.error(`Error processing AniDB ID ${anidbId}: ${error.message}`);
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
declare const addAnimeToListMutation = "\nmutation($mediaId: Int, $status: MediaListStatus) {\n SaveMediaListEntry(mediaId: $mediaId, status: $status) { id status }\n}\n";
|
|
2
|
-
declare const addMangaToListMutation = "\n mutation($mediaId: Int, $status: MediaListStatus) {\n SaveMediaListEntry(mediaId: $mediaId, status: $status) {\n id
|
|
3
|
-
declare const deleteActivityMutation = "\nmutation($id: Int!) {
|
|
4
|
-
declare const saveTextActivityMutation = "\nmutation SaveTextActivity($status: String!) {
|
|
2
|
+
declare const addMangaToListMutation = "\n mutation($mediaId: Int, $status: MediaListStatus) {\n SaveMediaListEntry(mediaId: $mediaId, status: $status) {\n id status media { id title { romaji english } }\n }\n }\n";
|
|
3
|
+
declare const deleteActivityMutation = "\nmutation($id: Int!) { DeleteActivity(id: $id) { deleted } }\n";
|
|
4
|
+
declare const saveTextActivityMutation = "\nmutation SaveTextActivity($status: String!) { SaveTextActivity(text: $status) { id text userId createdAt } }\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
|
-
|
|
7
|
+
declare const toggleFollowMutation = "mutation ($userId: Int!) { ToggleFollow(userId: $userId) { id name isFollower isFollowing } }";
|
|
8
|
+
declare const deleteMediaEntryMutation = "mutation($id: Int!) { DeleteMediaListEntry(id: $id) { deleted } }";
|
|
9
|
+
declare const deleteMangaEntryMutation = "mutation($id: Int) {\n DeleteMediaListEntry(id: $id) { deleted }\n}";
|
|
10
|
+
export { addAnimeToListMutation, addMangaToListMutation, deleteActivityMutation, deleteMangaEntryMutation, deleteMediaEntryMutation, saveAnimeWithProgressMutation, saveMangaWithProgressMutation, saveTextActivityMutation, toggleFollowMutation, };
|
package/bin/helpers/mutations.js
CHANGED
|
@@ -6,21 +6,15 @@ mutation($mediaId: Int, $status: MediaListStatus) {
|
|
|
6
6
|
const addMangaToListMutation = `
|
|
7
7
|
mutation($mediaId: Int, $status: MediaListStatus) {
|
|
8
8
|
SaveMediaListEntry(mediaId: $mediaId, status: $status) {
|
|
9
|
-
id
|
|
10
|
-
status
|
|
11
|
-
media { id title { romaji english } }
|
|
9
|
+
id status media { id title { romaji english } }
|
|
12
10
|
}
|
|
13
11
|
}
|
|
14
12
|
`;
|
|
15
13
|
const deleteActivityMutation = `
|
|
16
|
-
mutation($id: Int!) {
|
|
17
|
-
DeleteActivity(id: $id) { deleted }
|
|
18
|
-
}
|
|
14
|
+
mutation($id: Int!) { DeleteActivity(id: $id) { deleted } }
|
|
19
15
|
`;
|
|
20
16
|
const saveTextActivityMutation = `
|
|
21
|
-
mutation SaveTextActivity($status: String!) {
|
|
22
|
-
SaveTextActivity(text: $status) { id text userId createdAt }
|
|
23
|
-
}
|
|
17
|
+
mutation SaveTextActivity($status: String!) { SaveTextActivity(text: $status) { id text userId createdAt } }
|
|
24
18
|
`;
|
|
25
19
|
const saveAnimeWithProgressMutation = `
|
|
26
20
|
mutation ($mediaId: Int, $progress: Int, $status: MediaListStatus, $hiddenFromStatusLists: Boolean) {
|
|
@@ -35,4 +29,9 @@ mutation ($mediaId: Int, $progress: Int, $status: MediaListStatus, $hiddenFromSt
|
|
|
35
29
|
) { id progress hiddenFromStatusLists private }
|
|
36
30
|
}
|
|
37
31
|
`;
|
|
38
|
-
|
|
32
|
+
const toggleFollowMutation = `mutation ($userId: Int!) { ToggleFollow(userId: $userId) { id name isFollower isFollowing } }`;
|
|
33
|
+
const deleteMediaEntryMutation = `mutation($id: Int!) { DeleteMediaListEntry(id: $id) { deleted } }`;
|
|
34
|
+
const deleteMangaEntryMutation = `mutation($id: Int) {
|
|
35
|
+
DeleteMediaListEntry(id: $id) { deleted }
|
|
36
|
+
}`;
|
|
37
|
+
export { addAnimeToListMutation, addMangaToListMutation, deleteActivityMutation, deleteMangaEntryMutation, deleteMediaEntryMutation, saveAnimeWithProgressMutation, saveMangaWithProgressMutation, saveTextActivityMutation, toggleFollowMutation, };
|
package/bin/helpers/queries.d.ts
CHANGED
|
@@ -4,8 +4,6 @@ declare const popularQuery = "query ($page: Int, $perPage: Int) {\n Page(page:
|
|
|
4
4
|
declare const userQuery = "query ($username: String) {\n User(name: $username) {\n id name siteUrl donatorTier donatorBadge createdAt updatedAt previousNames { name createdAt updatedAt }\n isBlocked isFollower isFollowing options { profileColor timezone activityMergeTime }\n statistics { anime { count episodesWatched minutesWatched } manga { count chaptersRead volumesRead } }\n }\n}";
|
|
5
5
|
declare const currentUserAnimeList = "query ($id: Int) {\n MediaListCollection(userId: $id, type: ANIME) {\n lists { name entries { id progress hiddenFromStatusLists status media { id idMal title { romaji english native userPreferred } status episodes siteUrl format } } }\n }\n}\n";
|
|
6
6
|
declare const currentUserMangaList = "query ($id: Int) {\n MediaListCollection(userId: $id, type: MANGA) {\n lists { name entries { id progress hiddenFromStatusLists private status media { id idMal title { romaji english native userPreferred } status chapters } } }\n }\n}\n";
|
|
7
|
-
declare const deleteMediaEntryMutation = "mutation($id: Int!) {\n DeleteMediaListEntry(id: $id) { deleted }\n}";
|
|
8
|
-
declare const deleteMangaEntryMutation = "mutation($id: Int) {\n DeleteMediaListEntry(id: $id) { deleted }\n}";
|
|
9
7
|
declare const upcomingAnimesQuery = "query GetNextSeasonAnime($nextSeason: MediaSeason, $nextYear: Int, $perPage: Int) {\n Page(perPage: $perPage) {\n media(season: $nextSeason, seasonYear: $nextYear, type: ANIME, sort: POPULARITY_DESC) {\n id title { romaji english native userPreferred } season seasonYear startDate { year month day }\n episodes description genres\n }\n }\n}";
|
|
10
8
|
declare const animeDetailsQuery = "query ($id: Int) {\n Media(id: $id) {\n id idMal title { romaji english native userPreferred } episodes nextAiringEpisode { id }\n duration startDate { year month day } endDate { year month day } countryOfOrigin description isAdult status season format genres siteUrl\n stats { scoreDistribution { score amount } statusDistribution { status amount } }\n }\n}";
|
|
11
9
|
declare const userActivityQuery = "query ($id: Int, $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n activities(userId: $id, type_in: [ANIME_LIST, MANGA_LIST], sort: ID_DESC) {\n ... on ListActivity { id status progress createdAt media { id title { romaji english } } }\n }\n }\n}";
|
|
@@ -17,10 +15,9 @@ declare const activityMangaListQuery = "query ($userId: Int, $page: Int, $perPag
|
|
|
17
15
|
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
16
|
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
17
|
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) {
|
|
21
|
-
declare const malIdToAnilistMangaId = "query ($malId: Int) {\n Media(idMal: $malId, type: MANGA) {
|
|
18
|
+
declare const malIdToAnilistAnimeId = "query ($malId: Int) {\n Media(idMal: $malId, type: ANIME) { id title { romaji english } } }\n";
|
|
19
|
+
declare const malIdToAnilistMangaId = "query ($malId: Int) {\n Media(idMal: $malId, type: MANGA) { id title { romaji english } } }\n";
|
|
22
20
|
declare const userFollowingQuery = "query ($userId: Int!, $page: Int) {\n Page (page: $page) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n following(userId: $userId, sort: [USERNAME]) { id name avatar { large medium } bannerImage isFollowing isFollower }\n }\n}\n";
|
|
23
21
|
declare const userFollowersQuery = "query ($userId: Int!, $page: Int) {\n Page (page: $page) {\n pageInfo { total perPage currentPage lastPage hasNextPage }\n followers(userId: $userId, sort: [USERNAME]) { id name avatar { large medium } bannerImage isFollowing isFollower }\n }\n}\n";
|
|
24
|
-
declare const toggleFollowMutation = "mutation ($userId: Int!) {\n ToggleFollow(userId: $userId) { id name isFollower isFollowing }\n}\n";
|
|
25
22
|
declare const mangaDetailsQuery = "query ($id: Int) {\n Media(id: $id, type: MANGA) {\n id title { romaji english native userPreferred } coverImage { color medium large extraLarge } \n bannerImage description chapters volumes status genres\n startDate { year month day } endDate { year month day }\n }\n}\n";
|
|
26
|
-
export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery,
|
|
23
|
+
export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaDetailsQuery, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, };
|
package/bin/helpers/queries.js
CHANGED
|
@@ -36,12 +36,6 @@ const currentUserMangaList = `query ($id: Int) {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
`;
|
|
39
|
-
const deleteMediaEntryMutation = `mutation($id: Int!) {
|
|
40
|
-
DeleteMediaListEntry(id: $id) { deleted }
|
|
41
|
-
}`;
|
|
42
|
-
const deleteMangaEntryMutation = `mutation($id: Int) {
|
|
43
|
-
DeleteMediaListEntry(id: $id) { deleted }
|
|
44
|
-
}`;
|
|
45
39
|
const upcomingAnimesQuery = `query GetNextSeasonAnime($nextSeason: MediaSeason, $nextYear: Int, $perPage: Int) {
|
|
46
40
|
Page(perPage: $perPage) {
|
|
47
41
|
media(season: $nextSeason, seasonYear: $nextYear, type: ANIME, sort: POPULARITY_DESC) {
|
|
@@ -120,14 +114,10 @@ const activityMediaList = `query ($userId: Int, $page: Int, $perPage: Int, $type
|
|
|
120
114
|
}
|
|
121
115
|
}`;
|
|
122
116
|
const malIdToAnilistAnimeId = `query ($malId: Int) {
|
|
123
|
-
Media(idMal: $malId, type: ANIME) {
|
|
124
|
-
id title { romaji english } }
|
|
125
|
-
}
|
|
117
|
+
Media(idMal: $malId, type: ANIME) { id title { romaji english } } }
|
|
126
118
|
`;
|
|
127
119
|
const malIdToAnilistMangaId = `query ($malId: Int) {
|
|
128
|
-
Media(idMal: $malId, type: MANGA) {
|
|
129
|
-
id title { romaji english } }
|
|
130
|
-
}
|
|
120
|
+
Media(idMal: $malId, type: MANGA) { id title { romaji english } } }
|
|
131
121
|
`;
|
|
132
122
|
const userFollowingQuery = `query ($userId: Int!, $page: Int) {
|
|
133
123
|
Page (page: $page) {
|
|
@@ -143,10 +133,6 @@ const userFollowersQuery = `query ($userId: Int!, $page: Int) {
|
|
|
143
133
|
}
|
|
144
134
|
}
|
|
145
135
|
`;
|
|
146
|
-
const toggleFollowMutation = `mutation ($userId: Int!) {
|
|
147
|
-
ToggleFollow(userId: $userId) { id name isFollower isFollowing }
|
|
148
|
-
}
|
|
149
|
-
`;
|
|
150
136
|
const mangaDetailsQuery = `query ($id: Int) {
|
|
151
137
|
Media(id: $id, type: MANGA) {
|
|
152
138
|
id title { romaji english native userPreferred } coverImage { color medium large extraLarge }
|
|
@@ -155,4 +141,4 @@ const mangaDetailsQuery = `query ($id: Int) {
|
|
|
155
141
|
}
|
|
156
142
|
}
|
|
157
143
|
`;
|
|
158
|
-
export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery,
|
|
144
|
+
export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaDetailsQuery, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, };
|
package/bin/helpers/types.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
type Error = {
|
|
2
|
+
message: string;
|
|
3
|
+
}[];
|
|
1
4
|
interface DeleteMangaResponse {
|
|
2
5
|
data?: {
|
|
3
6
|
DeleteMediaListEntry?: {
|
|
4
7
|
deleted?: boolean;
|
|
5
8
|
};
|
|
6
9
|
};
|
|
7
|
-
errors?:
|
|
8
|
-
message: string;
|
|
9
|
-
}[];
|
|
10
|
+
errors?: Error;
|
|
10
11
|
}
|
|
11
12
|
declare enum AniListMediaStatus {
|
|
12
13
|
CURRENT = "CURRENT",
|
|
@@ -48,9 +49,7 @@ interface MalIdToAnilistIdResponse {
|
|
|
48
49
|
title: MediaTitle;
|
|
49
50
|
};
|
|
50
51
|
};
|
|
51
|
-
errors?:
|
|
52
|
-
message: string;
|
|
53
|
-
}[];
|
|
52
|
+
errors?: Error;
|
|
54
53
|
}
|
|
55
54
|
interface saveAnimeWithProgressResponse {
|
|
56
55
|
data?: {
|
|
@@ -60,9 +59,7 @@ interface saveAnimeWithProgressResponse {
|
|
|
60
59
|
hiddenFromStatusLists: boolean;
|
|
61
60
|
};
|
|
62
61
|
};
|
|
63
|
-
errors?:
|
|
64
|
-
message: string;
|
|
65
|
-
}[];
|
|
62
|
+
errors?: Error;
|
|
66
63
|
}
|
|
67
64
|
declare enum MALAnimeStatus {
|
|
68
65
|
ON_HOLD = "On-Hold",
|
|
@@ -84,9 +81,7 @@ interface AnimeList {
|
|
|
84
81
|
lists: MediaList[];
|
|
85
82
|
};
|
|
86
83
|
};
|
|
87
|
-
errors?:
|
|
88
|
-
message: string;
|
|
89
|
-
}[];
|
|
84
|
+
errors?: Error;
|
|
90
85
|
}
|
|
91
86
|
interface MediaWithProgress {
|
|
92
87
|
malId?: number;
|
|
@@ -125,9 +120,7 @@ interface SaveTextActivityResponse {
|
|
|
125
120
|
createdAt: number;
|
|
126
121
|
};
|
|
127
122
|
};
|
|
128
|
-
errors?:
|
|
129
|
-
message: string;
|
|
130
|
-
}[];
|
|
123
|
+
errors?: Error;
|
|
131
124
|
}
|
|
132
125
|
interface MediaListCollectionResponse {
|
|
133
126
|
data?: {
|
|
@@ -135,9 +128,7 @@ interface MediaListCollectionResponse {
|
|
|
135
128
|
lists: MediaList[];
|
|
136
129
|
};
|
|
137
130
|
};
|
|
138
|
-
errors?:
|
|
139
|
-
message: string;
|
|
140
|
-
}[];
|
|
131
|
+
errors?: Error;
|
|
141
132
|
}
|
|
142
133
|
interface List {
|
|
143
134
|
name: string;
|
|
@@ -151,39 +142,9 @@ interface MediaList {
|
|
|
151
142
|
}
|
|
152
143
|
interface Myself {
|
|
153
144
|
data?: {
|
|
154
|
-
Viewer:
|
|
155
|
-
id: number;
|
|
156
|
-
name: string;
|
|
157
|
-
siteUrl: string;
|
|
158
|
-
options: {
|
|
159
|
-
profileColor: string;
|
|
160
|
-
timezone: string;
|
|
161
|
-
activityMergeTime: string;
|
|
162
|
-
};
|
|
163
|
-
donatorTier: string;
|
|
164
|
-
donatorBadge: string;
|
|
165
|
-
unreadNotificationCount: number;
|
|
166
|
-
createdAt: number;
|
|
167
|
-
updatedAt: number;
|
|
168
|
-
statistics: {
|
|
169
|
-
anime: {
|
|
170
|
-
count: number;
|
|
171
|
-
meanScore: string;
|
|
172
|
-
minutesWatched: string;
|
|
173
|
-
episodesWatched: number;
|
|
174
|
-
};
|
|
175
|
-
manga: {
|
|
176
|
-
count: number;
|
|
177
|
-
meanScore: string;
|
|
178
|
-
chaptersRead: number;
|
|
179
|
-
volumesRead: number;
|
|
180
|
-
};
|
|
181
|
-
};
|
|
182
|
-
};
|
|
145
|
+
Viewer: User;
|
|
183
146
|
};
|
|
184
|
-
errors?:
|
|
185
|
-
message: string;
|
|
186
|
-
}[];
|
|
147
|
+
errors?: Error;
|
|
187
148
|
}
|
|
188
149
|
interface DateMonthYear {
|
|
189
150
|
day?: number | null;
|
|
@@ -208,9 +169,7 @@ interface AnimeDetails {
|
|
|
208
169
|
siteUrl: string;
|
|
209
170
|
};
|
|
210
171
|
};
|
|
211
|
-
errors?:
|
|
212
|
-
message: string;
|
|
213
|
-
}[];
|
|
172
|
+
errors?: Error;
|
|
214
173
|
}
|
|
215
174
|
interface SaveMediaListEntryResponse {
|
|
216
175
|
data?: {
|
|
@@ -219,9 +178,7 @@ interface SaveMediaListEntryResponse {
|
|
|
219
178
|
status: string;
|
|
220
179
|
};
|
|
221
180
|
};
|
|
222
|
-
errors?:
|
|
223
|
-
message: string;
|
|
224
|
-
}[];
|
|
181
|
+
errors?: Error;
|
|
225
182
|
}
|
|
226
183
|
interface MediaListEntry {
|
|
227
184
|
id?: number;
|
|
@@ -245,55 +202,51 @@ type UserActivitiesResponse = {
|
|
|
245
202
|
activities: Activity[];
|
|
246
203
|
};
|
|
247
204
|
};
|
|
248
|
-
errors?:
|
|
249
|
-
message: string;
|
|
250
|
-
}[];
|
|
205
|
+
errors?: Error;
|
|
251
206
|
};
|
|
252
207
|
type UserResponse = {
|
|
253
208
|
data?: {
|
|
254
|
-
User:
|
|
255
|
-
id: number;
|
|
256
|
-
name: string;
|
|
257
|
-
siteUrl: string;
|
|
258
|
-
donatorTier: string;
|
|
259
|
-
donatorBadge: string;
|
|
260
|
-
createdAt: number;
|
|
261
|
-
updatedAt: number;
|
|
262
|
-
isBlocked: boolean;
|
|
263
|
-
isFollower: boolean;
|
|
264
|
-
isFollowing: boolean;
|
|
265
|
-
options: {
|
|
266
|
-
profileColor: string;
|
|
267
|
-
timezone: string;
|
|
268
|
-
};
|
|
269
|
-
statistics: {
|
|
270
|
-
anime: {
|
|
271
|
-
count: number;
|
|
272
|
-
episodesWatched: number;
|
|
273
|
-
minutesWatched: number;
|
|
274
|
-
};
|
|
275
|
-
manga: {
|
|
276
|
-
count: number;
|
|
277
|
-
chaptersRead: number;
|
|
278
|
-
volumesRead: number;
|
|
279
|
-
};
|
|
280
|
-
};
|
|
281
|
-
};
|
|
209
|
+
User: User;
|
|
282
210
|
};
|
|
283
|
-
errors?:
|
|
284
|
-
|
|
285
|
-
|
|
211
|
+
errors?: Error;
|
|
212
|
+
};
|
|
213
|
+
type Avatar = {
|
|
214
|
+
large?: string;
|
|
215
|
+
medium?: string;
|
|
286
216
|
};
|
|
287
217
|
type User = {
|
|
288
218
|
id: number;
|
|
289
|
-
name
|
|
290
|
-
avatar
|
|
291
|
-
|
|
292
|
-
|
|
219
|
+
name?: string;
|
|
220
|
+
avatar?: Avatar;
|
|
221
|
+
bannerImage?: string;
|
|
222
|
+
isFollower?: boolean;
|
|
223
|
+
isFollowing?: boolean;
|
|
224
|
+
siteUrl?: string;
|
|
225
|
+
donatorTier?: string;
|
|
226
|
+
donatorBadge?: string;
|
|
227
|
+
createdAt?: number;
|
|
228
|
+
updatedAt?: number;
|
|
229
|
+
isBlocked?: boolean;
|
|
230
|
+
unreadNotificationCount?: number;
|
|
231
|
+
options?: {
|
|
232
|
+
profileColor?: string;
|
|
233
|
+
timezone?: string;
|
|
234
|
+
activityMergeTime?: number;
|
|
235
|
+
};
|
|
236
|
+
statistics?: {
|
|
237
|
+
anime?: {
|
|
238
|
+
count?: number;
|
|
239
|
+
episodesWatched?: number;
|
|
240
|
+
minutesWatched?: number;
|
|
241
|
+
meanScore?: number;
|
|
242
|
+
};
|
|
243
|
+
manga?: {
|
|
244
|
+
count?: number;
|
|
245
|
+
chaptersRead?: number;
|
|
246
|
+
volumesRead?: number;
|
|
247
|
+
meanScore?: number;
|
|
248
|
+
};
|
|
293
249
|
};
|
|
294
|
-
bannerImage: string;
|
|
295
|
-
isFollower: boolean;
|
|
296
|
-
isFollowing: boolean;
|
|
297
250
|
};
|
|
298
251
|
type UserFollower = {
|
|
299
252
|
data?: {
|
|
@@ -308,9 +261,7 @@ type UserFollower = {
|
|
|
308
261
|
followers: User[];
|
|
309
262
|
};
|
|
310
263
|
};
|
|
311
|
-
errors?:
|
|
312
|
-
message: string;
|
|
313
|
-
}[];
|
|
264
|
+
errors?: Error;
|
|
314
265
|
};
|
|
315
266
|
type UserFollowing = {
|
|
316
267
|
data?: {
|
|
@@ -325,9 +276,7 @@ type UserFollowing = {
|
|
|
325
276
|
following: User[];
|
|
326
277
|
};
|
|
327
278
|
};
|
|
328
|
-
errors?:
|
|
329
|
-
message: string;
|
|
330
|
-
}[];
|
|
279
|
+
errors?: Error;
|
|
331
280
|
};
|
|
332
281
|
type AnimeSearchResponse = {
|
|
333
282
|
data?: {
|
|
@@ -342,9 +291,7 @@ type AnimeSearchResponse = {
|
|
|
342
291
|
}[];
|
|
343
292
|
};
|
|
344
293
|
};
|
|
345
|
-
errors?:
|
|
346
|
-
message: string;
|
|
347
|
-
}[];
|
|
294
|
+
errors?: Error;
|
|
348
295
|
};
|
|
349
296
|
type ToggleFollowResponse = {
|
|
350
297
|
data?: {
|
|
@@ -355,9 +302,7 @@ type ToggleFollowResponse = {
|
|
|
355
302
|
isFollowing: boolean;
|
|
356
303
|
};
|
|
357
304
|
};
|
|
358
|
-
errors?:
|
|
359
|
-
message: string;
|
|
360
|
-
}[];
|
|
305
|
+
errors?: Error;
|
|
361
306
|
};
|
|
362
307
|
type DeleteMediaListResponse = {
|
|
363
308
|
data?: {
|
|
@@ -365,9 +310,7 @@ type DeleteMediaListResponse = {
|
|
|
365
310
|
deleted: boolean;
|
|
366
311
|
};
|
|
367
312
|
};
|
|
368
|
-
errors?:
|
|
369
|
-
message: string;
|
|
370
|
-
}[];
|
|
313
|
+
errors?: Error;
|
|
371
314
|
};
|
|
372
315
|
type Activity = {
|
|
373
316
|
id: number;
|
|
@@ -380,9 +323,6 @@ type Activity = {
|
|
|
380
323
|
};
|
|
381
324
|
createdAt: number;
|
|
382
325
|
};
|
|
383
|
-
type Error = {
|
|
384
|
-
message: string;
|
|
385
|
-
}[];
|
|
386
326
|
type CoverImage = {
|
|
387
327
|
color: string;
|
|
388
328
|
medium: string;
|
package/bin/helpers/workers.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DateMonthYear, MALAnimeStatus, MALMangaStatus, MediaWithProgress } from "./types.js";
|
|
1
|
+
import { DateMonthYear, MALAnimeStatus, MALMangaStatus, MediaWithProgress, User } from "./types.js";
|
|
2
2
|
declare const aniListEndpoint = "https://graphql.anilist.co";
|
|
3
3
|
declare const redirectUri = "https://anilist.co/api/v2/oauth/pin";
|
|
4
4
|
declare function getTitle(title: {
|
|
@@ -46,4 +46,6 @@ declare const anidbToanilistMapper: (romanjiName: string, year: number, englishN
|
|
|
46
46
|
*/
|
|
47
47
|
declare function saveToPath(data_type: string, file_format: string): Promise<string>;
|
|
48
48
|
declare function simpleDateFormat(date: DateMonthYear): string;
|
|
49
|
-
|
|
49
|
+
declare function handleRateLimitRetry(retryCount: number): Promise<void>;
|
|
50
|
+
declare function logUserDetails(user: User, followersCount: number, followingCount: number): void;
|
|
51
|
+
export { anidbToanilistMapper, aniListEndpoint, createAnimeListXML, createAnimeXML, createMangaListXML, createMangaXML, formatDateObject, getCurrentPackageVersion, getDownloadFolderPath, getFormattedDate, getNextSeasonAndYear, getTitle, handleRateLimitRetry, logUserDetails, redirectUri, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, saveJSONasXML, saveToPath, selectFile, simpleDateFormat, timestampToTimeAgo, };
|
package/bin/helpers/workers.js
CHANGED
|
@@ -27,12 +27,14 @@ import { homedir } from "os";
|
|
|
27
27
|
import Papa from "papaparse";
|
|
28
28
|
import { join } from "path";
|
|
29
29
|
import process from "process";
|
|
30
|
+
import Spinner from "tiny-spinner";
|
|
30
31
|
import { Auth } from "./auth.js";
|
|
31
32
|
import { fetcher } from "./fetcher.js";
|
|
32
33
|
import { animeSearchQuery } from "./queries.js";
|
|
33
34
|
import { MALAnimeStatus, MALMangaStatus, } from "./types.js";
|
|
34
35
|
const aniListEndpoint = `https://graphql.anilist.co`;
|
|
35
36
|
const redirectUri = "https://anilist.co/api/v2/oauth/pin";
|
|
37
|
+
const spinner = new Spinner();
|
|
36
38
|
function getTitle(title) {
|
|
37
39
|
return (title === null || title === void 0 ? void 0 : title.english) || (title === null || title === void 0 ? void 0 : title.romaji) || "???";
|
|
38
40
|
}
|
|
@@ -398,4 +400,57 @@ function simpleDateFormat(date) {
|
|
|
398
400
|
}
|
|
399
401
|
return `${date === null || date === void 0 ? void 0 : date.day}/${date === null || date === void 0 ? void 0 : date.month}/${date === null || date === void 0 ? void 0 : date.year}`;
|
|
400
402
|
}
|
|
401
|
-
|
|
403
|
+
function handleRateLimitRetry(retryCount) {
|
|
404
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
405
|
+
let seconds = Math.pow(2, retryCount) * 1000;
|
|
406
|
+
const maxWait = 60 * 1000;
|
|
407
|
+
seconds = Math.min(seconds, maxWait);
|
|
408
|
+
spinner.start(`Rate limit reached. Retrying in ${seconds / 1000} sec...`);
|
|
409
|
+
let remainingTime = seconds / 1000;
|
|
410
|
+
const interval = setInterval(() => {
|
|
411
|
+
remainingTime--;
|
|
412
|
+
spinner.update(`Rate limit reached. Retrying in ${remainingTime} sec...`);
|
|
413
|
+
if (remainingTime <= 0)
|
|
414
|
+
clearInterval(interval);
|
|
415
|
+
}, 1000);
|
|
416
|
+
yield new Promise((resolve) => setTimeout(resolve, seconds));
|
|
417
|
+
clearInterval(interval);
|
|
418
|
+
spinner.stop();
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
function formatDate(timestamp) {
|
|
422
|
+
return timestamp ? new Date(timestamp * 1000).toUTCString() : "N/A";
|
|
423
|
+
}
|
|
424
|
+
function logUserDetails(user, followersCount, followingCount) {
|
|
425
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
426
|
+
console.log("\nš User Information:");
|
|
427
|
+
console.table({
|
|
428
|
+
"ID": user.id,
|
|
429
|
+
"Name": user.name,
|
|
430
|
+
"Site URL": user.siteUrl,
|
|
431
|
+
"Donator Tier": user.donatorTier,
|
|
432
|
+
"Donator Badge": user.donatorBadge,
|
|
433
|
+
"Account Created": formatDate(user.createdAt),
|
|
434
|
+
"Account Updated": formatDate(user.updatedAt),
|
|
435
|
+
"Blocked": user.isBlocked,
|
|
436
|
+
"isFollower": user.isFollower,
|
|
437
|
+
"isFollowing": user.isFollowing,
|
|
438
|
+
"Profile Color": ((_a = user.options) === null || _a === void 0 ? void 0 : _a.profileColor) || "N/A",
|
|
439
|
+
"Timezone": ((_b = user.options) === null || _b === void 0 ? void 0 : _b.timezone) || "N/A",
|
|
440
|
+
"Followers": followersCount,
|
|
441
|
+
"Following": followingCount,
|
|
442
|
+
});
|
|
443
|
+
console.log("\nš Anime Statistics:");
|
|
444
|
+
console.table({
|
|
445
|
+
"Count": ((_d = (_c = user.statistics) === null || _c === void 0 ? void 0 : _c.anime) === null || _d === void 0 ? void 0 : _d.count) || 0,
|
|
446
|
+
"Episodes Watched": ((_f = (_e = user.statistics) === null || _e === void 0 ? void 0 : _e.anime) === null || _f === void 0 ? void 0 : _f.episodesWatched) || 0,
|
|
447
|
+
"Minutes Watched": ((_h = (_g = user.statistics) === null || _g === void 0 ? void 0 : _g.anime) === null || _h === void 0 ? void 0 : _h.minutesWatched) || 0,
|
|
448
|
+
});
|
|
449
|
+
console.log("\nš Manga Statistics:");
|
|
450
|
+
console.table({
|
|
451
|
+
"Count": ((_k = (_j = user.statistics) === null || _j === void 0 ? void 0 : _j.manga) === null || _k === void 0 ? void 0 : _k.count) || 0,
|
|
452
|
+
"Chapters Read": ((_m = (_l = user.statistics) === null || _l === void 0 ? void 0 : _l.manga) === null || _m === void 0 ? void 0 : _m.chaptersRead) || 0,
|
|
453
|
+
"Volumes Read": ((_p = (_o = user.statistics) === null || _o === void 0 ? void 0 : _o.manga) === null || _p === void 0 ? void 0 : _p.volumesRead) || 0,
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
export { anidbToanilistMapper, aniListEndpoint, createAnimeListXML, createAnimeXML, createMangaListXML, createMangaXML, formatDateObject, getCurrentPackageVersion, getDownloadFolderPath, getFormattedDate, getNextSeasonAndYear, getTitle, handleRateLimitRetry, logUserDetails, redirectUri, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, saveJSONasXML, saveToPath, selectFile, simpleDateFormat, timestampToTimeAgo, };
|
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.4.
|
|
5
|
+
"version": "1.4.8",
|
|
6
6
|
"main": "./bin/index.js",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"types": "./bin/index.d.ts",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"format:check": "prettier . --check",
|
|
20
20
|
"lint": "eslint ./dist",
|
|
21
21
|
"lint:fix": "eslint ./dist --fix",
|
|
22
|
-
"all": "npm run lint && npm run lint:fix && npm run format && npm test",
|
|
22
|
+
"all": "npm run build && npm run lint && npm run lint:fix && npm run format && npm test",
|
|
23
23
|
"test": "jest ./tests"
|
|
24
24
|
},
|
|
25
25
|
"keywords": [
|
|
@@ -57,21 +57,21 @@
|
|
|
57
57
|
"@babel/preset-env": "^7.26.9",
|
|
58
58
|
"@eslint/js": "^9.23.0",
|
|
59
59
|
"@types/jest": "^29.5.14",
|
|
60
|
-
"@types/node": "^22.13.
|
|
60
|
+
"@types/node": "^22.13.14",
|
|
61
61
|
"@types/papaparse": "^5.3.15",
|
|
62
62
|
"@types/xml2js": "^0.4.14",
|
|
63
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
63
|
+
"@typescript-eslint/eslint-plugin": "^8.28.0",
|
|
64
64
|
"eslint": "^9.23.0",
|
|
65
65
|
"globals": "^16.0.0",
|
|
66
66
|
"jest": "^29.7.0",
|
|
67
67
|
"prettier": "^3.5.3",
|
|
68
68
|
"prettier-plugin-organize-imports": "^4.1.0",
|
|
69
|
-
"ts-jest": "^29.
|
|
69
|
+
"ts-jest": "^29.3.0",
|
|
70
70
|
"ts-node": "^10.9.2",
|
|
71
71
|
"typescript": "^5.8.2"
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
|
-
"@irfanshadikrishad/cipher": "^1.0.
|
|
74
|
+
"@irfanshadikrishad/cipher": "^1.0.7",
|
|
75
75
|
"cli-truncate": "^4.0.0",
|
|
76
76
|
"commander": "^13.1.0",
|
|
77
77
|
"fast-xml-parser": "^5.0.9",
|