@irfanshadikrishad/anilist 1.3.2-forbidden.1 → 1.4.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.
- package/{LICENSE.md → LICENSE} +373 -382
- package/README.md +79 -53
- package/bin/helpers/auth.d.ts +13 -7
- package/bin/helpers/auth.js +297 -399
- package/bin/helpers/lists.d.ts +5 -1
- package/bin/helpers/lists.js +276 -127
- package/bin/helpers/mutations.d.ts +1 -2
- package/bin/helpers/mutations.js +32 -37
- package/bin/helpers/queries.d.ts +10 -9
- package/bin/helpers/queries.js +151 -154
- package/bin/helpers/truncate.d.ts +6 -0
- package/bin/helpers/truncate.js +9 -0
- package/bin/helpers/types.d.ts +206 -36
- package/bin/helpers/validation.d.ts +29 -0
- package/bin/helpers/validation.js +117 -0
- package/bin/helpers/workers.d.ts +19 -10
- package/bin/helpers/workers.js +157 -93
- package/bin/index.js +30 -6
- package/package.json +22 -17
package/bin/helpers/lists.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ declare class AniList {
|
|
|
10
10
|
static getUpcomingAnime(count: number): Promise<void>;
|
|
11
11
|
static getUserByUsername(username: string): Promise<void>;
|
|
12
12
|
static getAnimeDetailsByID(anilistID: number): Promise<void>;
|
|
13
|
+
static getMangaDetailsByID(mangaID: number): Promise<void>;
|
|
13
14
|
static searchAnime(search: string, count: number): Promise<void>;
|
|
14
15
|
static searchManga(search: string, count: number): Promise<void>;
|
|
15
16
|
}
|
|
@@ -19,4 +20,7 @@ declare class MyAnimeList {
|
|
|
19
20
|
static exportAnime(): Promise<void>;
|
|
20
21
|
static exportManga(): Promise<void>;
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
+
declare class AniDB {
|
|
24
|
+
static importAnime(): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export { AniDB, AniList, MyAnimeList };
|
package/bin/helpers/lists.js
CHANGED
|
@@ -8,23 +8,33 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { XMLParser } from "fast-xml-parser";
|
|
11
|
-
import { readFile
|
|
11
|
+
import { readFile } from "fs/promises";
|
|
12
12
|
import inquirer from "inquirer";
|
|
13
|
+
import { jsonrepair } from "jsonrepair";
|
|
13
14
|
import { join } from "path";
|
|
14
15
|
import { Auth } from "./auth.js";
|
|
15
16
|
import { fetcher } from "./fetcher.js";
|
|
16
17
|
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";
|
|
18
|
+
import { animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaDetailsQuery, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, } from "./queries.js";
|
|
19
|
+
import { responsiveOutput } from "./truncate.js";
|
|
18
20
|
import { AniListMediaStatus, } from "./types.js";
|
|
19
|
-
import {
|
|
21
|
+
import { Validate } from "./validation.js";
|
|
22
|
+
import { anidbToanilistMapper, formatDateObject, getDownloadFolderPath, getNextSeasonAndYear, getTitle, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, saveJSONasXML, selectFile, simpleDateFormat, timestampToTimeAgo, } from "./workers.js";
|
|
20
23
|
class AniList {
|
|
21
24
|
static importAnime() {
|
|
22
25
|
return __awaiter(this, void 0, void 0, function* () {
|
|
23
26
|
try {
|
|
24
27
|
const filename = yield selectFile(".json");
|
|
28
|
+
if (!filename) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
25
31
|
const filePath = join(getDownloadFolderPath(), filename);
|
|
26
32
|
const fileContent = yield readFile(filePath, "utf8");
|
|
27
33
|
const importedData = JSON.parse(fileContent);
|
|
34
|
+
if (!Validate.Import_JSON(importedData)) {
|
|
35
|
+
console.error(`\nInvalid JSON file.`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
28
38
|
let count = 0;
|
|
29
39
|
const batchSize = 1; // Number of requests in each batch
|
|
30
40
|
const delay = 1100; // delay to avoid rate-limiting
|
|
@@ -68,9 +78,16 @@ class AniList {
|
|
|
68
78
|
return __awaiter(this, void 0, void 0, function* () {
|
|
69
79
|
try {
|
|
70
80
|
const filename = yield selectFile(".json");
|
|
81
|
+
if (!filename) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
71
84
|
const filePath = join(getDownloadFolderPath(), filename);
|
|
72
85
|
const fileContent = yield readFile(filePath, "utf8");
|
|
73
86
|
const importedData = JSON.parse(fileContent);
|
|
87
|
+
if (!Validate.Import_JSON(importedData)) {
|
|
88
|
+
console.error(`\nInvalid JSON file.`);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
74
91
|
let count = 0;
|
|
75
92
|
const batchSize = 1; // Adjust batch size as per rate-limit constraints
|
|
76
93
|
const delay = 1100; // 2 seconds delay to avoid rate-limit
|
|
@@ -112,7 +129,76 @@ class AniList {
|
|
|
112
129
|
static exportAnime() {
|
|
113
130
|
return __awaiter(this, void 0, void 0, function* () {
|
|
114
131
|
var _a, _b, _c;
|
|
115
|
-
if (yield Auth.isLoggedIn()) {
|
|
132
|
+
if (!(yield Auth.isLoggedIn())) {
|
|
133
|
+
console.error(`\nMust login to use this feature.`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const { exportType } = yield inquirer.prompt([
|
|
137
|
+
{
|
|
138
|
+
type: "list",
|
|
139
|
+
name: "exportType",
|
|
140
|
+
message: "Choose export type:",
|
|
141
|
+
choices: [
|
|
142
|
+
{ name: "CSV", value: 1 },
|
|
143
|
+
{ name: "JSON", value: 2 },
|
|
144
|
+
{ name: "XML (MyAnimeList/AniDB)", value: 3 },
|
|
145
|
+
],
|
|
146
|
+
pageSize: 10,
|
|
147
|
+
},
|
|
148
|
+
]);
|
|
149
|
+
const animeList = yield fetcher(currentUserAnimeList, {
|
|
150
|
+
id: yield Auth.MyUserId(),
|
|
151
|
+
});
|
|
152
|
+
if (animeList) {
|
|
153
|
+
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 : [];
|
|
154
|
+
const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
|
|
155
|
+
var _a, _b, _c, _d;
|
|
156
|
+
return ({
|
|
157
|
+
id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
|
|
158
|
+
title: (_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.title,
|
|
159
|
+
episodes: (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.episodes,
|
|
160
|
+
siteUrl: (_d = entry === null || entry === void 0 ? void 0 : entry.media) === null || _d === void 0 ? void 0 : _d.siteUrl,
|
|
161
|
+
progress: entry.progress,
|
|
162
|
+
status: entry === null || entry === void 0 ? void 0 : entry.status,
|
|
163
|
+
hiddenFromStatusLists: entry.hiddenFromStatusLists,
|
|
164
|
+
});
|
|
165
|
+
}));
|
|
166
|
+
switch (exportType) {
|
|
167
|
+
case 1:
|
|
168
|
+
yield saveJSONasCSV(mediaWithProgress, "anime");
|
|
169
|
+
break;
|
|
170
|
+
case 2:
|
|
171
|
+
yield saveJSONasJSON(mediaWithProgress, "anime");
|
|
172
|
+
break;
|
|
173
|
+
case 3:
|
|
174
|
+
yield MyAnimeList.exportAnime();
|
|
175
|
+
break;
|
|
176
|
+
default:
|
|
177
|
+
console.log(`\nInvalid export type. ${exportType}`);
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
console.error(`\nNo anime(s) found in your lists.`);
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
static exportManga() {
|
|
187
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
var _a, _b;
|
|
189
|
+
if (!(yield Auth.isLoggedIn())) {
|
|
190
|
+
console.error(`\nPlease login to use this feature.`);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const mangaLists = yield fetcher(currentUserMangaList, {
|
|
194
|
+
id: yield Auth.MyUserId(),
|
|
195
|
+
});
|
|
196
|
+
if (!(mangaLists === null || mangaLists === void 0 ? void 0 : mangaLists.data)) {
|
|
197
|
+
console.error(`\nCould not get manga list.`);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
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) || [];
|
|
201
|
+
if (lists.length > 0) {
|
|
116
202
|
const { exportType } = yield inquirer.prompt([
|
|
117
203
|
{
|
|
118
204
|
type: "list",
|
|
@@ -126,111 +212,35 @@ class AniList {
|
|
|
126
212
|
pageSize: 10,
|
|
127
213
|
},
|
|
128
214
|
]);
|
|
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
|
-
break;
|
|
155
|
-
case 3:
|
|
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.`);
|
|
215
|
+
const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
|
|
216
|
+
var _a, _b;
|
|
217
|
+
return ({
|
|
218
|
+
id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
|
|
219
|
+
title: (_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.title,
|
|
220
|
+
private: entry.private,
|
|
221
|
+
chapters: entry.media.chapters,
|
|
222
|
+
progress: entry.progress,
|
|
223
|
+
status: entry === null || entry === void 0 ? void 0 : entry.status,
|
|
224
|
+
hiddenFromStatusLists: entry.hiddenFromStatusLists,
|
|
225
|
+
});
|
|
226
|
+
}));
|
|
227
|
+
switch (exportType) {
|
|
228
|
+
case 1:
|
|
229
|
+
yield saveJSONasCSV(mediaWithProgress, "manga");
|
|
230
|
+
break;
|
|
231
|
+
case 2:
|
|
232
|
+
yield saveJSONasJSON(mediaWithProgress, "manga");
|
|
233
|
+
break;
|
|
234
|
+
case 3:
|
|
235
|
+
yield MyAnimeList.exportManga();
|
|
236
|
+
break;
|
|
237
|
+
default:
|
|
238
|
+
console.log(`\nInvalid export type. ${exportType}`);
|
|
239
|
+
break;
|
|
230
240
|
}
|
|
231
241
|
}
|
|
232
242
|
else {
|
|
233
|
-
console.
|
|
243
|
+
console.log(`\nList seems to be empty.`);
|
|
234
244
|
}
|
|
235
245
|
});
|
|
236
246
|
}
|
|
@@ -241,11 +251,10 @@ class AniList {
|
|
|
241
251
|
if (!(yield Auth.isLoggedIn())) {
|
|
242
252
|
return console.error(`\nPlease log in first to access your lists.`);
|
|
243
253
|
}
|
|
244
|
-
|
|
245
|
-
if (!userId) {
|
|
254
|
+
if (!(yield Auth.MyUserId())) {
|
|
246
255
|
return console.log(`\nFailed getting current user Id.`);
|
|
247
256
|
}
|
|
248
|
-
const data = yield fetcher(currentUserAnimeList, { id:
|
|
257
|
+
const data = yield fetcher(currentUserAnimeList, { id: yield Auth.MyUserId() });
|
|
249
258
|
if (data === null || data === void 0 ? void 0 : data.errors) {
|
|
250
259
|
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
260
|
}
|
|
@@ -612,7 +621,7 @@ class AniList {
|
|
|
612
621
|
}
|
|
613
622
|
static getUserByUsername(username) {
|
|
614
623
|
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;
|
|
624
|
+
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
625
|
try {
|
|
617
626
|
const response = yield fetcher(userQuery, { username });
|
|
618
627
|
if (!((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.User)) {
|
|
@@ -625,6 +634,15 @@ class AniList {
|
|
|
625
634
|
perPage: 10,
|
|
626
635
|
});
|
|
627
636
|
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 : [];
|
|
637
|
+
// Get follower/following information
|
|
638
|
+
const req_followers = yield fetcher(userFollowersQuery, {
|
|
639
|
+
userId: user === null || user === void 0 ? void 0 : user.id,
|
|
640
|
+
});
|
|
641
|
+
const req_following = yield fetcher(userFollowingQuery, {
|
|
642
|
+
userId: user === null || user === void 0 ? void 0 : user.id,
|
|
643
|
+
});
|
|
644
|
+
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
|
+
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
646
|
console.log(`\nID:\t\t${user.id}`);
|
|
629
647
|
console.log(`Name:\t\t${user.name}`);
|
|
630
648
|
console.log(`Site URL:\t${user.siteUrl}`);
|
|
@@ -635,14 +653,16 @@ class AniList {
|
|
|
635
653
|
console.log(`Blocked:\t${user.isBlocked}`);
|
|
636
654
|
console.log(`Follower:\t${user.isFollower}`);
|
|
637
655
|
console.log(`Following:\t${user.isFollowing}`);
|
|
638
|
-
console.log(`Profile Color:\t${(
|
|
639
|
-
console.log(`Timezone:\t${(
|
|
640
|
-
console.log(`\
|
|
641
|
-
console.log(`
|
|
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}`);
|
|
642
662
|
if (activities.length > 0) {
|
|
643
663
|
console.log(`\nRecent Activities:`);
|
|
644
664
|
activities.forEach(({ status, progress, media, createdAt }) => {
|
|
645
|
-
|
|
665
|
+
responsiveOutput(`${timestampToTimeAgo(createdAt)}\t${status} ${progress ? `${progress} of ` : ""}${getTitle(media === null || media === void 0 ? void 0 : media.title)}`);
|
|
646
666
|
});
|
|
647
667
|
}
|
|
648
668
|
else {
|
|
@@ -678,6 +698,33 @@ class AniList {
|
|
|
678
698
|
}
|
|
679
699
|
});
|
|
680
700
|
}
|
|
701
|
+
static getMangaDetailsByID(mangaID) {
|
|
702
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
703
|
+
var _a;
|
|
704
|
+
try {
|
|
705
|
+
const response = yield fetcher(mangaDetailsQuery, {
|
|
706
|
+
id: mangaID,
|
|
707
|
+
});
|
|
708
|
+
if (response === null || response === void 0 ? void 0 : response.errors) {
|
|
709
|
+
console.error(`${response.errors[0].message}`);
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
const manga = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.Media;
|
|
713
|
+
if (manga) {
|
|
714
|
+
console.log(`\n[${getTitle(manga.title)}]`);
|
|
715
|
+
console.log(`${manga.description}`);
|
|
716
|
+
console.log(`Chapters: ${manga.chapters}\t Volumes: ${manga.volumes}`);
|
|
717
|
+
console.log(`Status:\t${manga.status}`);
|
|
718
|
+
console.log(`Genres:\t${manga.genres.join(", ")}`);
|
|
719
|
+
console.log(`Start:\t${simpleDateFormat(manga.startDate)}`);
|
|
720
|
+
console.log(`End:\t${simpleDateFormat(manga.endDate)}`);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
catch (error) {
|
|
724
|
+
console.error(`${error.message}`);
|
|
725
|
+
}
|
|
726
|
+
});
|
|
727
|
+
}
|
|
681
728
|
static searchAnime(search, count) {
|
|
682
729
|
return __awaiter(this, void 0, void 0, function* () {
|
|
683
730
|
var _a, _b, _c;
|
|
@@ -804,8 +851,15 @@ class MyAnimeList {
|
|
|
804
851
|
var _a, _b, _c, _d, _e;
|
|
805
852
|
try {
|
|
806
853
|
const filename = yield selectFile(".xml");
|
|
854
|
+
if (!filename) {
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
807
857
|
const filePath = join(getDownloadFolderPath(), filename);
|
|
808
858
|
const fileContent = yield readFile(filePath, "utf8");
|
|
859
|
+
if (!(yield Validate.Import_AnimeXML(fileContent))) {
|
|
860
|
+
console.error(`\nInvalid XML file.`);
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
809
863
|
const parser = new XMLParser();
|
|
810
864
|
if (fileContent) {
|
|
811
865
|
const XMLObject = parser.parse(fileContent);
|
|
@@ -869,8 +923,15 @@ class MyAnimeList {
|
|
|
869
923
|
var _a, _b, _c, _d, _e;
|
|
870
924
|
try {
|
|
871
925
|
const filename = yield selectFile(".xml");
|
|
926
|
+
if (!filename) {
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
872
929
|
const filePath = join(getDownloadFolderPath(), filename);
|
|
873
930
|
const fileContent = yield readFile(filePath, "utf8");
|
|
931
|
+
if (!(yield Validate.Import_MangaXML(fileContent))) {
|
|
932
|
+
console.error(`\nInvalid XML file.`);
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
874
935
|
const parser = new XMLParser();
|
|
875
936
|
if (fileContent) {
|
|
876
937
|
const XMLObject = parser.parse(fileContent);
|
|
@@ -941,7 +1002,7 @@ class MyAnimeList {
|
|
|
941
1002
|
if (((_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.length) > 0) {
|
|
942
1003
|
const lists = (_d = (_c = animeList === null || animeList === void 0 ? void 0 : animeList.data) === null || _c === void 0 ? void 0 : _c.MediaListCollection) === null || _d === void 0 ? void 0 : _d.lists;
|
|
943
1004
|
const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
|
|
944
|
-
var _a, _b, _c, _d, _e;
|
|
1005
|
+
var _a, _b, _c, _d, _e, _f;
|
|
945
1006
|
return ({
|
|
946
1007
|
id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
|
|
947
1008
|
malId: (_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.idMal,
|
|
@@ -951,13 +1012,10 @@ class MyAnimeList {
|
|
|
951
1012
|
progress: entry.progress,
|
|
952
1013
|
status: entry === null || entry === void 0 ? void 0 : entry.status,
|
|
953
1014
|
hiddenFromStatusLists: false,
|
|
1015
|
+
format: (_f = entry === null || entry === void 0 ? void 0 : entry.media) === null || _f === void 0 ? void 0 : _f.format,
|
|
954
1016
|
});
|
|
955
1017
|
}));
|
|
956
|
-
|
|
957
|
-
const path = join(getDownloadFolderPath(), `${yield Auth.MyUserName()}@irfanshadikrishad-anilist-myanimelist(anime)-${getFormattedDate()}.xml`);
|
|
958
|
-
yield writeFile(path, yield xmlContent, "utf8");
|
|
959
|
-
console.log(`Generated XML for MyAnimeList.`);
|
|
960
|
-
open(getDownloadFolderPath());
|
|
1018
|
+
yield saveJSONasXML(mediaWithProgress, 0);
|
|
961
1019
|
}
|
|
962
1020
|
else {
|
|
963
1021
|
console.log(`\nHey, ${yield Auth.MyUserName()}. Your anime list seems to be empty.`);
|
|
@@ -992,11 +1050,7 @@ class MyAnimeList {
|
|
|
992
1050
|
status: entry.status,
|
|
993
1051
|
hiddenFromStatusLists: entry.hiddenFromStatusLists,
|
|
994
1052
|
})));
|
|
995
|
-
|
|
996
|
-
const path = join(getDownloadFolderPath(), `${yield Auth.MyUserName()}@irfanshadikrishad-anilist-myanimelist(manga)-${getFormattedDate()}.xml`);
|
|
997
|
-
yield writeFile(path, yield XMLContent, "utf8");
|
|
998
|
-
console.log(`Generated XML for MyAnimeList.`);
|
|
999
|
-
open(getDownloadFolderPath());
|
|
1053
|
+
yield saveJSONasXML(mediaWithProgress, 1);
|
|
1000
1054
|
}
|
|
1001
1055
|
else {
|
|
1002
1056
|
console.log(`\nHey, ${yield Auth.MyUserName()}. Your anime list seems to be empty.`);
|
|
@@ -1008,4 +1062,99 @@ class MyAnimeList {
|
|
|
1008
1062
|
});
|
|
1009
1063
|
}
|
|
1010
1064
|
}
|
|
1011
|
-
|
|
1065
|
+
class AniDB {
|
|
1066
|
+
static importAnime() {
|
|
1067
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1068
|
+
var _a, _b;
|
|
1069
|
+
try {
|
|
1070
|
+
const filename = yield selectFile(".json");
|
|
1071
|
+
if (!filename) {
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1074
|
+
const filePath = join(getDownloadFolderPath(), filename);
|
|
1075
|
+
const fileContent = yield readFile(filePath, "utf8");
|
|
1076
|
+
const js0n_repaired = jsonrepair(fileContent);
|
|
1077
|
+
if (!(yield Validate.Import_AniDBJSONLarge(js0n_repaired))) {
|
|
1078
|
+
console.error(`\nInvalid JSON Large file.`);
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
if (js0n_repaired) {
|
|
1082
|
+
const obj3ct = yield JSON.parse(js0n_repaired);
|
|
1083
|
+
const animeList = obj3ct === null || obj3ct === void 0 ? void 0 : obj3ct.anime;
|
|
1084
|
+
if ((animeList === null || animeList === void 0 ? void 0 : animeList.length) > 0) {
|
|
1085
|
+
let count = 0;
|
|
1086
|
+
let iteration = 0;
|
|
1087
|
+
let missed = [];
|
|
1088
|
+
for (const anime of animeList) {
|
|
1089
|
+
iteration++;
|
|
1090
|
+
const anidbId = anime.id;
|
|
1091
|
+
const released = anime.broadcastDate; // DD-MM-YYYY (eg: "23.07.2016")
|
|
1092
|
+
const status = anime.status;
|
|
1093
|
+
// const type = anime.type
|
|
1094
|
+
const totalEpisodes = anime.totalEpisodes;
|
|
1095
|
+
const ownEpisodes = anime.ownEpisodes;
|
|
1096
|
+
const romanjiName = anime.romanjiName;
|
|
1097
|
+
const englishName = anime.englishName;
|
|
1098
|
+
function getStatus(anidbStatus, episodesSeen) {
|
|
1099
|
+
if (anidbStatus === "complete") {
|
|
1100
|
+
return AniListMediaStatus.COMPLETED;
|
|
1101
|
+
}
|
|
1102
|
+
else if (anidbStatus === "incomplete" &&
|
|
1103
|
+
Number(episodesSeen) > 0) {
|
|
1104
|
+
return AniListMediaStatus.CURRENT;
|
|
1105
|
+
}
|
|
1106
|
+
else {
|
|
1107
|
+
return AniListMediaStatus.PLANNING;
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
let anilistId = yield anidbToanilistMapper(romanjiName, Number(released.split(".")[2]), englishName);
|
|
1111
|
+
if (anilistId) {
|
|
1112
|
+
try {
|
|
1113
|
+
const saveResponse = yield fetcher(saveAnimeWithProgressMutation, {
|
|
1114
|
+
mediaId: anilistId,
|
|
1115
|
+
progress: ownEpisodes - 2,
|
|
1116
|
+
status: getStatus(status, ownEpisodes),
|
|
1117
|
+
hiddenFromStatusLists: false,
|
|
1118
|
+
private: false,
|
|
1119
|
+
});
|
|
1120
|
+
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;
|
|
1121
|
+
if (entryId) {
|
|
1122
|
+
count++;
|
|
1123
|
+
responsiveOutput(`[${count}]\t${entryId} ✅\t${anidbId}\t${anilistId}\t(${ownEpisodes}/${totalEpisodes})\t${status}–>${getStatus(status, ownEpisodes)}`);
|
|
1124
|
+
}
|
|
1125
|
+
// Rate limit each API call to avoid server overload
|
|
1126
|
+
// await new Promise((resolve) => setTimeout(resolve, 1100))
|
|
1127
|
+
}
|
|
1128
|
+
catch (error) {
|
|
1129
|
+
console.error(`Error processing AniDB ID ${anidbId}: ${error.message}`);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
else {
|
|
1133
|
+
missed.push({
|
|
1134
|
+
anidbId: anidbId,
|
|
1135
|
+
englishTitle: englishName,
|
|
1136
|
+
romajiTitle: romanjiName,
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
responsiveOutput(`\nAccuracy: ${(((animeList.length - missed.length) / animeList.length) * 100).toFixed(2)}%\tTotal Processed: ${iteration}\tMissed: ${missed.length}`);
|
|
1141
|
+
if (missed.length > 0) {
|
|
1142
|
+
responsiveOutput(`Exporting missed entries to JSON file, Please add them manually.`);
|
|
1143
|
+
yield saveJSONasJSON(missed, "anidb-missed");
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
else {
|
|
1147
|
+
console.log(`\nNo anime list found in the file.`);
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
else {
|
|
1151
|
+
console.log(`\nNo content found in the file or unable to read.`);
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
catch (error) {
|
|
1155
|
+
console.error(`\nError in AniDB import process: ${error.message}`);
|
|
1156
|
+
}
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
export { AniDB, AniList, MyAnimeList };
|
|
@@ -4,5 +4,4 @@ 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
|
-
|
|
8
|
-
export { addAnimeToListMutation, addMangaToListMutation, deleteActivityMutation, likeActivityMutation, saveAnimeWithProgressMutation, saveMangaWithProgressMutation, saveTextActivityMutation, };
|
|
7
|
+
export { addAnimeToListMutation, addMangaToListMutation, deleteActivityMutation, saveAnimeWithProgressMutation, saveMangaWithProgressMutation, saveTextActivityMutation, };
|
package/bin/helpers/mutations.js
CHANGED
|
@@ -1,43 +1,38 @@
|
|
|
1
|
-
const addAnimeToListMutation = `
|
|
2
|
-
mutation($mediaId: Int, $status: MediaListStatus) {
|
|
3
|
-
SaveMediaListEntry(mediaId: $mediaId, status: $status) { id status }
|
|
4
|
-
}
|
|
1
|
+
const addAnimeToListMutation = `
|
|
2
|
+
mutation($mediaId: Int, $status: MediaListStatus) {
|
|
3
|
+
SaveMediaListEntry(mediaId: $mediaId, status: $status) { id status }
|
|
4
|
+
}
|
|
5
5
|
`;
|
|
6
|
-
const addMangaToListMutation = `
|
|
7
|
-
mutation($mediaId: Int, $status: MediaListStatus) {
|
|
8
|
-
SaveMediaListEntry(mediaId: $mediaId, status: $status) {
|
|
9
|
-
id
|
|
10
|
-
status
|
|
11
|
-
media { id title { romaji english } }
|
|
12
|
-
}
|
|
13
|
-
}
|
|
6
|
+
const addMangaToListMutation = `
|
|
7
|
+
mutation($mediaId: Int, $status: MediaListStatus) {
|
|
8
|
+
SaveMediaListEntry(mediaId: $mediaId, status: $status) {
|
|
9
|
+
id
|
|
10
|
+
status
|
|
11
|
+
media { id title { romaji english } }
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
14
|
`;
|
|
15
|
-
const deleteActivityMutation = `
|
|
16
|
-
mutation($id: Int!) {
|
|
17
|
-
DeleteActivity(id: $id) { deleted }
|
|
18
|
-
}
|
|
15
|
+
const deleteActivityMutation = `
|
|
16
|
+
mutation($id: Int!) {
|
|
17
|
+
DeleteActivity(id: $id) { deleted }
|
|
18
|
+
}
|
|
19
19
|
`;
|
|
20
|
-
const saveTextActivityMutation = `
|
|
21
|
-
mutation SaveTextActivity($status: String!) {
|
|
22
|
-
SaveTextActivity(text: $status) { id text userId createdAt }
|
|
23
|
-
}
|
|
20
|
+
const saveTextActivityMutation = `
|
|
21
|
+
mutation SaveTextActivity($status: String!) {
|
|
22
|
+
SaveTextActivity(text: $status) { id text userId createdAt }
|
|
23
|
+
}
|
|
24
24
|
`;
|
|
25
|
-
const saveAnimeWithProgressMutation = `
|
|
26
|
-
mutation ($mediaId: Int, $progress: Int, $status: MediaListStatus, $hiddenFromStatusLists: Boolean) {
|
|
27
|
-
SaveMediaListEntry(mediaId: $mediaId, progress: $progress, status: $status, hiddenFromStatusLists: $hiddenFromStatusLists) {
|
|
28
|
-
id progress hiddenFromStatusLists
|
|
29
|
-
}
|
|
30
|
-
}
|
|
25
|
+
const saveAnimeWithProgressMutation = `
|
|
26
|
+
mutation ($mediaId: Int, $progress: Int, $status: MediaListStatus, $hiddenFromStatusLists: Boolean) {
|
|
27
|
+
SaveMediaListEntry(mediaId: $mediaId, progress: $progress, status: $status, hiddenFromStatusLists: $hiddenFromStatusLists) {
|
|
28
|
+
id progress hiddenFromStatusLists
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
31
|
`;
|
|
32
|
-
const saveMangaWithProgressMutation = `
|
|
33
|
-
mutation ($mediaId: Int, $progress: Int, $status: MediaListStatus, $hiddenFromStatusLists: Boolean, $private: Boolean) {
|
|
34
|
-
SaveMediaListEntry( mediaId: $mediaId, progress: $progress, status: $status, hiddenFromStatusLists: $hiddenFromStatusLists, private: $private
|
|
35
|
-
) { id progress hiddenFromStatusLists private }
|
|
36
|
-
}
|
|
32
|
+
const saveMangaWithProgressMutation = `
|
|
33
|
+
mutation ($mediaId: Int, $progress: Int, $status: MediaListStatus, $hiddenFromStatusLists: Boolean, $private: Boolean) {
|
|
34
|
+
SaveMediaListEntry( mediaId: $mediaId, progress: $progress, status: $status, hiddenFromStatusLists: $hiddenFromStatusLists, private: $private
|
|
35
|
+
) { id progress hiddenFromStatusLists private }
|
|
36
|
+
}
|
|
37
37
|
`;
|
|
38
|
-
|
|
39
|
-
mutation($activityId: Int!) {
|
|
40
|
-
ToggleLike(id: $activityId, type: ACTIVITY) { id }
|
|
41
|
-
}
|
|
42
|
-
`;
|
|
43
|
-
export { addAnimeToListMutation, addMangaToListMutation, deleteActivityMutation, likeActivityMutation, saveAnimeWithProgressMutation, saveMangaWithProgressMutation, saveTextActivityMutation, };
|
|
38
|
+
export { addAnimeToListMutation, addMangaToListMutation, deleteActivityMutation, saveAnimeWithProgressMutation, saveMangaWithProgressMutation, saveTextActivityMutation, };
|