@irfanshadikrishad/anilist 1.2.4 → 1.2.6
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 +35 -20
- package/bin/helpers/auth.d.ts +13 -3
- package/bin/helpers/auth.js +297 -199
- package/bin/helpers/lists.d.ts +4 -1
- package/bin/helpers/lists.js +211 -114
- package/bin/helpers/queries.d.ts +5 -2
- package/bin/helpers/queries.js +20 -2
- package/bin/helpers/types.d.ts +179 -4
- package/bin/helpers/workers.d.ts +5 -4
- package/bin/helpers/workers.js +33 -2
- package/bin/index.js +25 -1
- package/package.json +7 -5
package/bin/helpers/lists.d.ts
CHANGED
package/bin/helpers/lists.js
CHANGED
|
@@ -10,13 +10,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { XMLParser } from "fast-xml-parser";
|
|
11
11
|
import { readFile, writeFile } from "fs/promises";
|
|
12
12
|
import inquirer from "inquirer";
|
|
13
|
+
import { jsonrepair } from "jsonrepair";
|
|
14
|
+
import open from "open";
|
|
13
15
|
import { join } from "path";
|
|
14
16
|
import { Auth } from "./auth.js";
|
|
15
17
|
import { fetcher } from "./fetcher.js";
|
|
16
18
|
import { addAnimeToListMutation, addMangaToListMutation, saveAnimeWithProgressMutation, saveMangaWithProgressMutation, } from "./mutations.js";
|
|
17
|
-
import { animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userQuery, } from "./queries.js";
|
|
19
|
+
import { animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, } from "./queries.js";
|
|
18
20
|
import { AniListMediaStatus, } from "./types.js";
|
|
19
|
-
import { createAnimeListXML, createMangaListXML, formatDateObject, getDownloadFolderPath, getFormattedDate, getNextSeasonAndYear, getTitle, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, selectFile, timestampToTimeAgo, } from "./workers.js";
|
|
21
|
+
import { anidbToanilistMapper, createAnimeListXML, createMangaListXML, formatDateObject, getDownloadFolderPath, getFormattedDate, getNextSeasonAndYear, getTitle, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, selectFile, timestampToTimeAgo, } from "./workers.js";
|
|
20
22
|
class AniList {
|
|
21
23
|
static importAnime() {
|
|
22
24
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -112,7 +114,78 @@ class AniList {
|
|
|
112
114
|
static exportAnime() {
|
|
113
115
|
return __awaiter(this, void 0, void 0, function* () {
|
|
114
116
|
var _a, _b, _c;
|
|
115
|
-
if (yield Auth.isLoggedIn()) {
|
|
117
|
+
if (!(yield Auth.isLoggedIn())) {
|
|
118
|
+
console.error(`\nMust login to use this feature.`);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const { exportType } = yield inquirer.prompt([
|
|
122
|
+
{
|
|
123
|
+
type: "list",
|
|
124
|
+
name: "exportType",
|
|
125
|
+
message: "Choose export type:",
|
|
126
|
+
choices: [
|
|
127
|
+
{ name: "CSV", value: 1 },
|
|
128
|
+
{ name: "JSON", value: 2 },
|
|
129
|
+
{ name: "XML (MyAnimeList/AniDB)", value: 3 },
|
|
130
|
+
],
|
|
131
|
+
pageSize: 10,
|
|
132
|
+
},
|
|
133
|
+
]);
|
|
134
|
+
const animeList = yield fetcher(currentUserAnimeList, {
|
|
135
|
+
id: yield Auth.MyUserId(),
|
|
136
|
+
});
|
|
137
|
+
if (animeList) {
|
|
138
|
+
const lists = (_c = (_b = (_a = animeList === null || animeList === void 0 ? void 0 : animeList.data) === null || _a === void 0 ? void 0 : _a.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists) !== null && _c !== void 0 ? _c : [];
|
|
139
|
+
const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
|
|
140
|
+
var _a, _b, _c, _d, _e;
|
|
141
|
+
return ({
|
|
142
|
+
id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
|
|
143
|
+
title: exportType === 1
|
|
144
|
+
? getTitle((_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.title)
|
|
145
|
+
: (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title,
|
|
146
|
+
episodes: (_d = entry === null || entry === void 0 ? void 0 : entry.media) === null || _d === void 0 ? void 0 : _d.episodes,
|
|
147
|
+
siteUrl: (_e = entry === null || entry === void 0 ? void 0 : entry.media) === null || _e === void 0 ? void 0 : _e.siteUrl,
|
|
148
|
+
progress: entry.progress,
|
|
149
|
+
status: entry === null || entry === void 0 ? void 0 : entry.status,
|
|
150
|
+
hiddenFromStatusLists: entry.hiddenFromStatusLists,
|
|
151
|
+
});
|
|
152
|
+
}));
|
|
153
|
+
switch (exportType) {
|
|
154
|
+
case 1:
|
|
155
|
+
yield saveJSONasCSV(mediaWithProgress, "anime");
|
|
156
|
+
break;
|
|
157
|
+
case 2:
|
|
158
|
+
yield saveJSONasJSON(mediaWithProgress, "anime");
|
|
159
|
+
break;
|
|
160
|
+
case 3:
|
|
161
|
+
yield MyAnimeList.exportAnime();
|
|
162
|
+
break;
|
|
163
|
+
default:
|
|
164
|
+
console.log(`\nInvalid export type. ${exportType}`);
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
console.error(`\nNo anime(s) found in your lists.`);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
static exportManga() {
|
|
174
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
175
|
+
var _a, _b;
|
|
176
|
+
if (!(yield Auth.isLoggedIn())) {
|
|
177
|
+
console.error(`\nPlease login to use this feature.`);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const mangaLists = yield fetcher(currentUserMangaList, {
|
|
181
|
+
id: yield Auth.MyUserId(),
|
|
182
|
+
});
|
|
183
|
+
if (!(mangaLists === null || mangaLists === void 0 ? void 0 : mangaLists.data)) {
|
|
184
|
+
console.error(`\nCould not get manga list.`);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const lists = ((_b = (_a = mangaLists === null || mangaLists === void 0 ? void 0 : mangaLists.data) === null || _a === void 0 ? void 0 : _a.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists) || [];
|
|
188
|
+
if (lists.length > 0) {
|
|
116
189
|
const { exportType } = yield inquirer.prompt([
|
|
117
190
|
{
|
|
118
191
|
type: "list",
|
|
@@ -126,111 +199,37 @@ class AniList {
|
|
|
126
199
|
pageSize: 10,
|
|
127
200
|
},
|
|
128
201
|
]);
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
yield MyAnimeList.exportAnime();
|
|
157
|
-
break;
|
|
158
|
-
default:
|
|
159
|
-
console.log(`\nInvalid export type. ${exportType}`);
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
else {
|
|
164
|
-
console.error(`\nNo anime(s) found in your lists.`);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
console.error(`\nMust login to use this feature.`);
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
static exportManga() {
|
|
173
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
174
|
-
var _a, _b;
|
|
175
|
-
if (yield Auth.isLoggedIn()) {
|
|
176
|
-
const mangaLists = yield fetcher(currentUserMangaList, {
|
|
177
|
-
id: yield Auth.MyUserId(),
|
|
178
|
-
});
|
|
179
|
-
if (mangaLists) {
|
|
180
|
-
const lists = ((_b = (_a = mangaLists === null || mangaLists === void 0 ? void 0 : mangaLists.data) === null || _a === void 0 ? void 0 : _a.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists) || [];
|
|
181
|
-
if (lists.length > 0) {
|
|
182
|
-
const { exportType } = yield inquirer.prompt([
|
|
183
|
-
{
|
|
184
|
-
type: "list",
|
|
185
|
-
name: "exportType",
|
|
186
|
-
message: "Choose export type:",
|
|
187
|
-
choices: [
|
|
188
|
-
{ name: "CSV", value: 1 },
|
|
189
|
-
{ name: "JSON", value: 2 },
|
|
190
|
-
{ name: "XML (MyAnimeList)", value: 3 },
|
|
191
|
-
],
|
|
192
|
-
pageSize: 10,
|
|
193
|
-
},
|
|
194
|
-
]);
|
|
195
|
-
const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
|
|
196
|
-
var _a, _b, _c;
|
|
197
|
-
return ({
|
|
198
|
-
id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
|
|
199
|
-
title: exportType === 1
|
|
200
|
-
? getTitle((_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.title)
|
|
201
|
-
: (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title,
|
|
202
|
-
private: entry.private,
|
|
203
|
-
chapters: entry.media.chapters,
|
|
204
|
-
progress: entry.progress,
|
|
205
|
-
status: entry === null || entry === void 0 ? void 0 : entry.status,
|
|
206
|
-
hiddenFromStatusLists: entry.hiddenFromStatusLists,
|
|
207
|
-
});
|
|
208
|
-
}));
|
|
209
|
-
switch (exportType) {
|
|
210
|
-
case 1:
|
|
211
|
-
yield saveJSONasCSV(mediaWithProgress, "manga");
|
|
212
|
-
break;
|
|
213
|
-
case 2:
|
|
214
|
-
yield saveJSONasJSON(mediaWithProgress, "manga");
|
|
215
|
-
break;
|
|
216
|
-
case 3:
|
|
217
|
-
yield MyAnimeList.exportManga();
|
|
218
|
-
break;
|
|
219
|
-
default:
|
|
220
|
-
console.log(`\nInvalid export type. ${exportType}`);
|
|
221
|
-
break;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
console.log(`\nList seems to be empty.`);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
console.error(`\nCould not get manga list.`);
|
|
202
|
+
const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
|
|
203
|
+
var _a, _b, _c;
|
|
204
|
+
return ({
|
|
205
|
+
id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
|
|
206
|
+
title: exportType === 1
|
|
207
|
+
? getTitle((_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.title)
|
|
208
|
+
: (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title,
|
|
209
|
+
private: entry.private,
|
|
210
|
+
chapters: entry.media.chapters,
|
|
211
|
+
progress: entry.progress,
|
|
212
|
+
status: entry === null || entry === void 0 ? void 0 : entry.status,
|
|
213
|
+
hiddenFromStatusLists: entry.hiddenFromStatusLists,
|
|
214
|
+
});
|
|
215
|
+
}));
|
|
216
|
+
switch (exportType) {
|
|
217
|
+
case 1:
|
|
218
|
+
yield saveJSONasCSV(mediaWithProgress, "manga");
|
|
219
|
+
break;
|
|
220
|
+
case 2:
|
|
221
|
+
yield saveJSONasJSON(mediaWithProgress, "manga");
|
|
222
|
+
break;
|
|
223
|
+
case 3:
|
|
224
|
+
yield MyAnimeList.exportManga();
|
|
225
|
+
break;
|
|
226
|
+
default:
|
|
227
|
+
console.log(`\nInvalid export type. ${exportType}`);
|
|
228
|
+
break;
|
|
230
229
|
}
|
|
231
230
|
}
|
|
232
231
|
else {
|
|
233
|
-
console.
|
|
232
|
+
console.log(`\nList seems to be empty.`);
|
|
234
233
|
}
|
|
235
234
|
});
|
|
236
235
|
}
|
|
@@ -241,11 +240,10 @@ class AniList {
|
|
|
241
240
|
if (!(yield Auth.isLoggedIn())) {
|
|
242
241
|
return console.error(`\nPlease log in first to access your lists.`);
|
|
243
242
|
}
|
|
244
|
-
|
|
245
|
-
if (!userId) {
|
|
243
|
+
if (!(yield Auth.MyUserId())) {
|
|
246
244
|
return console.log(`\nFailed getting current user Id.`);
|
|
247
245
|
}
|
|
248
|
-
const data = yield fetcher(currentUserAnimeList, { id:
|
|
246
|
+
const data = yield fetcher(currentUserAnimeList, { id: yield Auth.MyUserId() });
|
|
249
247
|
if (data === null || data === void 0 ? void 0 : data.errors) {
|
|
250
248
|
return console.log(`\nSomething went wrong. ${(_b = (_a = data === null || data === void 0 ? void 0 : data.errors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message}`);
|
|
251
249
|
}
|
|
@@ -612,7 +610,7 @@ class AniList {
|
|
|
612
610
|
}
|
|
613
611
|
static getUserByUsername(username) {
|
|
614
612
|
return __awaiter(this, void 0, void 0, function* () {
|
|
615
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
613
|
+
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;
|
|
616
614
|
try {
|
|
617
615
|
const response = yield fetcher(userQuery, { username });
|
|
618
616
|
if (!((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.User)) {
|
|
@@ -625,6 +623,15 @@ class AniList {
|
|
|
625
623
|
perPage: 10,
|
|
626
624
|
});
|
|
627
625
|
const activities = (_f = (_e = (_d = userActivityResponse === null || userActivityResponse === void 0 ? void 0 : userActivityResponse.data) === null || _d === void 0 ? void 0 : _d.Page) === null || _e === void 0 ? void 0 : _e.activities) !== null && _f !== void 0 ? _f : [];
|
|
626
|
+
// Get follower/following information
|
|
627
|
+
const req_followers = yield fetcher(userFollowersQuery, {
|
|
628
|
+
userId: user === null || user === void 0 ? void 0 : user.id,
|
|
629
|
+
});
|
|
630
|
+
const req_following = yield fetcher(userFollowingQuery, {
|
|
631
|
+
userId: user === null || user === void 0 ? void 0 : user.id,
|
|
632
|
+
});
|
|
633
|
+
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;
|
|
634
|
+
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;
|
|
628
635
|
console.log(`\nID:\t\t${user.id}`);
|
|
629
636
|
console.log(`Name:\t\t${user.name}`);
|
|
630
637
|
console.log(`Site URL:\t${user.siteUrl}`);
|
|
@@ -635,10 +642,12 @@ class AniList {
|
|
|
635
642
|
console.log(`Blocked:\t${user.isBlocked}`);
|
|
636
643
|
console.log(`Follower:\t${user.isFollower}`);
|
|
637
644
|
console.log(`Following:\t${user.isFollowing}`);
|
|
638
|
-
console.log(`Profile Color:\t${(
|
|
639
|
-
console.log(`Timezone:\t${(
|
|
640
|
-
console.log(`\
|
|
641
|
-
console.log(`
|
|
645
|
+
console.log(`Profile Color:\t${(_o = user.options) === null || _o === void 0 ? void 0 : _o.profileColor}`);
|
|
646
|
+
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"}`);
|
|
647
|
+
console.log(`\nFollowers:\t${followersCount}`);
|
|
648
|
+
console.log(`Following:\t${followingCount}`);
|
|
649
|
+
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}`);
|
|
650
|
+
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}`);
|
|
642
651
|
if (activities.length > 0) {
|
|
643
652
|
console.log(`\nRecent Activities:`);
|
|
644
653
|
activities.forEach(({ status, progress, media, createdAt }) => {
|
|
@@ -1008,4 +1017,92 @@ class MyAnimeList {
|
|
|
1008
1017
|
});
|
|
1009
1018
|
}
|
|
1010
1019
|
}
|
|
1011
|
-
|
|
1020
|
+
class AniDB {
|
|
1021
|
+
static importAnime() {
|
|
1022
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1023
|
+
var _a, _b;
|
|
1024
|
+
try {
|
|
1025
|
+
const filename = yield selectFile(".json");
|
|
1026
|
+
const filePath = join(getDownloadFolderPath(), filename);
|
|
1027
|
+
const fileContent = yield readFile(filePath, "utf8");
|
|
1028
|
+
const js0n_repaired = jsonrepair(fileContent);
|
|
1029
|
+
if (fileContent) {
|
|
1030
|
+
const obj3ct = yield JSON.parse(js0n_repaired);
|
|
1031
|
+
const animeList = obj3ct === null || obj3ct === void 0 ? void 0 : obj3ct.anime;
|
|
1032
|
+
if ((animeList === null || animeList === void 0 ? void 0 : animeList.length) > 0) {
|
|
1033
|
+
let count = 0;
|
|
1034
|
+
let iteration = 0;
|
|
1035
|
+
let missed = [];
|
|
1036
|
+
for (const anime of animeList) {
|
|
1037
|
+
iteration++;
|
|
1038
|
+
const anidbId = anime.id;
|
|
1039
|
+
const released = anime.broadcastDate; // DD-MM-YYYY (eg: "23.07.2016")
|
|
1040
|
+
const status = anime.status;
|
|
1041
|
+
// const type = anime.type
|
|
1042
|
+
const totalEpisodes = anime.totalEpisodes;
|
|
1043
|
+
const ownEpisodes = anime.ownEpisodes;
|
|
1044
|
+
const romanjiName = anime.romanjiName;
|
|
1045
|
+
const englishName = anime.englishName;
|
|
1046
|
+
function getStatus(anidbStatus, episodesSeen) {
|
|
1047
|
+
if (anidbStatus === "complete") {
|
|
1048
|
+
return AniListMediaStatus.COMPLETED;
|
|
1049
|
+
}
|
|
1050
|
+
else if (anidbStatus === "incomplete" &&
|
|
1051
|
+
Number(episodesSeen) > 0) {
|
|
1052
|
+
return AniListMediaStatus.CURRENT;
|
|
1053
|
+
}
|
|
1054
|
+
else {
|
|
1055
|
+
return AniListMediaStatus.PLANNING;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
let anilistId = yield anidbToanilistMapper(romanjiName, Number(released.split(".")[2]), englishName);
|
|
1059
|
+
if (anilistId) {
|
|
1060
|
+
try {
|
|
1061
|
+
const saveResponse = yield fetcher(saveAnimeWithProgressMutation, {
|
|
1062
|
+
mediaId: anilistId,
|
|
1063
|
+
progress: ownEpisodes - 2,
|
|
1064
|
+
status: getStatus(status, ownEpisodes),
|
|
1065
|
+
hiddenFromStatusLists: false,
|
|
1066
|
+
private: false,
|
|
1067
|
+
});
|
|
1068
|
+
const entryId = (_b = (_a = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _a === void 0 ? void 0 : _a.SaveMediaListEntry) === null || _b === void 0 ? void 0 : _b.id;
|
|
1069
|
+
if (entryId) {
|
|
1070
|
+
count++;
|
|
1071
|
+
console.log(`[${count}]\t${entryId} ✅\t${anidbId}\t${anilistId}\t(${ownEpisodes}/${totalEpisodes})\t${status}→${getStatus(status, ownEpisodes)}`);
|
|
1072
|
+
}
|
|
1073
|
+
// Rate limit each API call to avoid server overload
|
|
1074
|
+
// await new Promise((resolve) => setTimeout(resolve, 1100))
|
|
1075
|
+
}
|
|
1076
|
+
catch (error) {
|
|
1077
|
+
console.error(`Error processing AniDB ID ${anidbId}: ${error.message}`);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
else {
|
|
1081
|
+
missed.push({
|
|
1082
|
+
anidbId: anidbId,
|
|
1083
|
+
englishTitle: englishName,
|
|
1084
|
+
romajiTitle: romanjiName,
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
console.log(`\nAccuracy: ${(((animeList.length - missed.length) / animeList.length) * 100).toFixed(2)}%\tTotal Processed: ${iteration}\tMissed: ${missed.length}`);
|
|
1089
|
+
if (missed.length > 0) {
|
|
1090
|
+
console.log(`Exporting missed entries to JSON file, Please add them manually.`);
|
|
1091
|
+
yield saveJSONasJSON(missed, "anidb-missed");
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
else {
|
|
1095
|
+
console.log(`\nNo anime list found in the file.`);
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
else {
|
|
1099
|
+
console.log(`\nNo content found in the file or unable to read.`);
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
catch (error) {
|
|
1103
|
+
console.error(`\nError in AniDB import process: ${error.message}`);
|
|
1104
|
+
}
|
|
1105
|
+
});
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
export { AniDB, AniList, MyAnimeList };
|
package/bin/helpers/queries.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ declare const deleteMangaEntryMutation = "mutation($id: Int) {\n DeleteMediaLis
|
|
|
9
9
|
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
10
|
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
11
|
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}";
|
|
12
|
-
declare const animeSearchQuery = "query ($search: String, $perPage: Int) {\n Page(perPage: $perPage) {\n media(search: $search, type: ANIME) { id title { romaji english native userPreferred } episodes status description }\n }\n}";
|
|
12
|
+
declare const animeSearchQuery = "query ($search: String, $perPage: Int) {\n Page(perPage: $perPage) {\n media(search: $search, type: ANIME) { id title { romaji english native userPreferred } startDate { day month year } episodes status description }\n }\n}";
|
|
13
13
|
declare const mangaSearchQuery = "query ($search: String, $perPage: Int) {\n Page(perPage: $perPage) {\n media(search: $search, type: MANGA) { id title { romaji english native userPreferred } chapters status description }\n }\n}";
|
|
14
14
|
declare const activityTextQuery = "query ($userId: Int, $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n activities(userId: $userId, type: TEXT, sort: ID_DESC) {\n ... on TextActivity { id type text createdAt user { id name } }\n }\n }\n}";
|
|
15
15
|
declare const activityAnimeListQuery = "query ($userId: Int, $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n activities(userId: $userId, type: ANIME_LIST, sort: ID_DESC) {\n ... on ListActivity { id type status progress createdAt media { id title { romaji english native } } }\n }\n }\n}";
|
|
@@ -19,4 +19,7 @@ declare const activityAllQuery = "query ($userId: Int, $page: Int, $perPage: Int
|
|
|
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
20
|
declare const malIdToAnilistAnimeId = "query ($malId: Int) {\n Media(idMal: $malId, type: ANIME) {\n id title { romaji english } } \n}\n";
|
|
21
21
|
declare const malIdToAnilistMangaId = "query ($malId: Int) {\n Media(idMal: $malId, type: MANGA) {\n id title { romaji english } } \n}\n";
|
|
22
|
-
|
|
22
|
+
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
|
+
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
|
+
export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, toggleFollowMutation, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, };
|
package/bin/helpers/queries.js
CHANGED
|
@@ -66,7 +66,7 @@ const userActivityQuery = `query ($id: Int, $page: Int, $perPage: Int) {
|
|
|
66
66
|
}`;
|
|
67
67
|
const animeSearchQuery = `query ($search: String, $perPage: Int) {
|
|
68
68
|
Page(perPage: $perPage) {
|
|
69
|
-
media(search: $search, type: ANIME) { id title { romaji english native userPreferred } episodes status description }
|
|
69
|
+
media(search: $search, type: ANIME) { id title { romaji english native userPreferred } startDate { day month year } episodes status description }
|
|
70
70
|
}
|
|
71
71
|
}`;
|
|
72
72
|
const mangaSearchQuery = `query ($search: String, $perPage: Int) {
|
|
@@ -129,4 +129,22 @@ const malIdToAnilistMangaId = `query ($malId: Int) {
|
|
|
129
129
|
id title { romaji english } }
|
|
130
130
|
}
|
|
131
131
|
`;
|
|
132
|
-
|
|
132
|
+
const userFollowingQuery = `query ($userId: Int!, $page: Int) {
|
|
133
|
+
Page (page: $page) {
|
|
134
|
+
pageInfo { total perPage currentPage lastPage hasNextPage }
|
|
135
|
+
following(userId: $userId, sort: [USERNAME]) { id name avatar { large medium } bannerImage isFollowing isFollower }
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
`;
|
|
139
|
+
const userFollowersQuery = `query ($userId: Int!, $page: Int) {
|
|
140
|
+
Page (page: $page) {
|
|
141
|
+
pageInfo { total perPage currentPage lastPage hasNextPage }
|
|
142
|
+
followers(userId: $userId, sort: [USERNAME]) { id name avatar { large medium } bannerImage isFollowing isFollower }
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
`;
|
|
146
|
+
const toggleFollowMutation = `mutation ($userId: Int!) {
|
|
147
|
+
ToggleFollow(userId: $userId) { id name isFollower isFollowing }
|
|
148
|
+
}
|
|
149
|
+
`;
|
|
150
|
+
export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, toggleFollowMutation, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, };
|
package/bin/helpers/types.d.ts
CHANGED
|
@@ -121,6 +121,29 @@ interface MediaEntry {
|
|
|
121
121
|
status: string;
|
|
122
122
|
hiddenFromStatusLists: boolean;
|
|
123
123
|
}
|
|
124
|
+
interface SaveTextActivityResponse {
|
|
125
|
+
data?: {
|
|
126
|
+
SaveTextActivity: {
|
|
127
|
+
id: number;
|
|
128
|
+
userId: number;
|
|
129
|
+
text: string;
|
|
130
|
+
createdAt: number;
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
errors?: {
|
|
134
|
+
message: string;
|
|
135
|
+
}[];
|
|
136
|
+
}
|
|
137
|
+
interface MediaListCollectionResponse {
|
|
138
|
+
data?: {
|
|
139
|
+
MediaListCollection: {
|
|
140
|
+
lists: MediaList[];
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
errors?: {
|
|
144
|
+
message: string;
|
|
145
|
+
}[];
|
|
146
|
+
}
|
|
124
147
|
interface List {
|
|
125
148
|
name: string;
|
|
126
149
|
entries: MediaEntry[];
|
|
@@ -171,9 +194,9 @@ interface Myself {
|
|
|
171
194
|
}[];
|
|
172
195
|
}
|
|
173
196
|
interface DateMonthYear {
|
|
174
|
-
day?:
|
|
175
|
-
month?:
|
|
176
|
-
year?:
|
|
197
|
+
day?: number;
|
|
198
|
+
month?: number;
|
|
199
|
+
year?: number;
|
|
177
200
|
}
|
|
178
201
|
interface AnimeDetails {
|
|
179
202
|
data?: {
|
|
@@ -197,6 +220,17 @@ interface AnimeDetails {
|
|
|
197
220
|
message: string;
|
|
198
221
|
}[];
|
|
199
222
|
}
|
|
223
|
+
interface SaveMediaListEntryResponse {
|
|
224
|
+
data?: {
|
|
225
|
+
SaveMediaListEntry: {
|
|
226
|
+
id: number;
|
|
227
|
+
status: string;
|
|
228
|
+
};
|
|
229
|
+
};
|
|
230
|
+
errors?: {
|
|
231
|
+
message: string;
|
|
232
|
+
}[];
|
|
233
|
+
}
|
|
200
234
|
interface MediaListEntry {
|
|
201
235
|
id?: number;
|
|
202
236
|
media: {
|
|
@@ -212,4 +246,145 @@ interface MediaListEntry {
|
|
|
212
246
|
hiddenFromStatusLists?: boolean;
|
|
213
247
|
private?: boolean;
|
|
214
248
|
}
|
|
215
|
-
|
|
249
|
+
type UserActivitiesResponse = {
|
|
250
|
+
data?: {
|
|
251
|
+
Page: {
|
|
252
|
+
activities: Activity[];
|
|
253
|
+
};
|
|
254
|
+
};
|
|
255
|
+
errors?: {
|
|
256
|
+
message: string;
|
|
257
|
+
}[];
|
|
258
|
+
};
|
|
259
|
+
type UserResponse = {
|
|
260
|
+
data?: {
|
|
261
|
+
User: {
|
|
262
|
+
id: number;
|
|
263
|
+
name: string;
|
|
264
|
+
siteUrl: string;
|
|
265
|
+
donatorTier: string;
|
|
266
|
+
donatorBadge: string;
|
|
267
|
+
createdAt: number;
|
|
268
|
+
updatedAt: number;
|
|
269
|
+
isBlocked: boolean;
|
|
270
|
+
isFollower: boolean;
|
|
271
|
+
isFollowing: boolean;
|
|
272
|
+
options: {
|
|
273
|
+
profileColor: string;
|
|
274
|
+
timezone: string;
|
|
275
|
+
};
|
|
276
|
+
statistics: {
|
|
277
|
+
anime: {
|
|
278
|
+
count: number;
|
|
279
|
+
episodesWatched: number;
|
|
280
|
+
minutesWatched: number;
|
|
281
|
+
};
|
|
282
|
+
manga: {
|
|
283
|
+
count: number;
|
|
284
|
+
chaptersRead: number;
|
|
285
|
+
volumesRead: number;
|
|
286
|
+
};
|
|
287
|
+
};
|
|
288
|
+
};
|
|
289
|
+
};
|
|
290
|
+
errors?: {
|
|
291
|
+
message: string;
|
|
292
|
+
}[];
|
|
293
|
+
};
|
|
294
|
+
type User = {
|
|
295
|
+
id: number;
|
|
296
|
+
name: string;
|
|
297
|
+
avatar: {
|
|
298
|
+
large: string;
|
|
299
|
+
medium: string;
|
|
300
|
+
};
|
|
301
|
+
bannerImage: string;
|
|
302
|
+
isFollower: boolean;
|
|
303
|
+
isFollowing: boolean;
|
|
304
|
+
};
|
|
305
|
+
type UserFollower = {
|
|
306
|
+
data?: {
|
|
307
|
+
Page: {
|
|
308
|
+
pageInfo: {
|
|
309
|
+
total: number;
|
|
310
|
+
perPage: number;
|
|
311
|
+
currentPage: number;
|
|
312
|
+
lastPage: number;
|
|
313
|
+
hasNextPage: boolean;
|
|
314
|
+
};
|
|
315
|
+
followers: User[];
|
|
316
|
+
};
|
|
317
|
+
};
|
|
318
|
+
errors?: {
|
|
319
|
+
message: string;
|
|
320
|
+
}[];
|
|
321
|
+
};
|
|
322
|
+
type UserFollowing = {
|
|
323
|
+
data?: {
|
|
324
|
+
Page: {
|
|
325
|
+
pageInfo: {
|
|
326
|
+
total: number;
|
|
327
|
+
perPage: number;
|
|
328
|
+
currentPage: number;
|
|
329
|
+
lastPage: number;
|
|
330
|
+
hasNextPage: boolean;
|
|
331
|
+
};
|
|
332
|
+
following: User[];
|
|
333
|
+
};
|
|
334
|
+
};
|
|
335
|
+
errors?: {
|
|
336
|
+
message: string;
|
|
337
|
+
}[];
|
|
338
|
+
};
|
|
339
|
+
type AnimeSearchResponse = {
|
|
340
|
+
data?: {
|
|
341
|
+
Page: {
|
|
342
|
+
media: {
|
|
343
|
+
id: number;
|
|
344
|
+
title: MediaTitle;
|
|
345
|
+
startDate: DateMonthYear;
|
|
346
|
+
episodes: number;
|
|
347
|
+
status: string;
|
|
348
|
+
description: string;
|
|
349
|
+
}[];
|
|
350
|
+
};
|
|
351
|
+
};
|
|
352
|
+
errors?: {
|
|
353
|
+
message: string;
|
|
354
|
+
}[];
|
|
355
|
+
};
|
|
356
|
+
type ToggleFollowResponse = {
|
|
357
|
+
data?: {
|
|
358
|
+
ToggleFollow: {
|
|
359
|
+
id: number;
|
|
360
|
+
name: string;
|
|
361
|
+
isFollower: boolean;
|
|
362
|
+
isFollowing: boolean;
|
|
363
|
+
};
|
|
364
|
+
};
|
|
365
|
+
errors?: {
|
|
366
|
+
message: string;
|
|
367
|
+
}[];
|
|
368
|
+
};
|
|
369
|
+
type DeleteMediaListResponse = {
|
|
370
|
+
data?: {
|
|
371
|
+
DeleteMediaListEntry: {
|
|
372
|
+
deleted: boolean;
|
|
373
|
+
};
|
|
374
|
+
};
|
|
375
|
+
errors?: {
|
|
376
|
+
message: string;
|
|
377
|
+
}[];
|
|
378
|
+
};
|
|
379
|
+
type Activity = {
|
|
380
|
+
id: number;
|
|
381
|
+
type: string;
|
|
382
|
+
status: string;
|
|
383
|
+
progress: number | null;
|
|
384
|
+
media: {
|
|
385
|
+
id?: number;
|
|
386
|
+
title: MediaTitle;
|
|
387
|
+
};
|
|
388
|
+
createdAt: number;
|
|
389
|
+
};
|
|
390
|
+
export { Activity, AniListMediaStatus, AnimeDetails, AnimeList, AnimeSearchResponse, DateMonthYear, DeleteMangaResponse, DeleteMediaListResponse, List, MALAnimeStatus, MALAnimeXML, MALMangaStatus, MalIdToAnilistIdResponse, MediaEntry, MediaList, MediaListCollectionResponse, MediaListEntry, MediaTitle, MediaWithProgress, Myself, SaveMediaListEntryResponse, SaveTextActivityResponse, ToggleFollowResponse, User, UserActivitiesResponse, UserFollower, UserFollowing, UserResponse, saveAnimeWithProgressResponse, };
|