@irfanshadikrishad/anilist 1.3.3-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} +115 -124
- package/README.md +266 -243
- package/bin/helpers/auth.d.ts +13 -7
- package/bin/helpers/auth.js +255 -373
- package/bin/helpers/lists.d.ts +1 -0
- package/bin/helpers/lists.js +175 -127
- package/bin/helpers/mutations.d.ts +1 -2
- package/bin/helpers/mutations.js +1 -6
- package/bin/helpers/queries.d.ts +9 -10
- package/bin/helpers/queries.js +23 -40
- package/bin/helpers/truncate.d.ts +6 -0
- package/bin/helpers/truncate.js +9 -0
- package/bin/helpers/types.d.ts +119 -68
- package/bin/helpers/validation.d.ts +29 -0
- package/bin/helpers/validation.js +117 -0
- package/bin/helpers/workers.d.ts +15 -7
- package/bin/helpers/workers.js +67 -34
- package/bin/index.js +30 -6
- package/package.json +85 -81
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
|
}
|
package/bin/helpers/lists.js
CHANGED
|
@@ -8,25 +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
13
|
import { jsonrepair } from "jsonrepair";
|
|
14
|
-
import open from "open";
|
|
15
14
|
import { join } from "path";
|
|
16
15
|
import { Auth } from "./auth.js";
|
|
17
16
|
import { fetcher } from "./fetcher.js";
|
|
18
17
|
import { addAnimeToListMutation, addMangaToListMutation, saveAnimeWithProgressMutation, saveMangaWithProgressMutation, } from "./mutations.js";
|
|
19
|
-
import { animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, 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";
|
|
20
20
|
import { AniListMediaStatus, } from "./types.js";
|
|
21
|
-
import {
|
|
21
|
+
import { Validate } from "./validation.js";
|
|
22
|
+
import { anidbToanilistMapper, formatDateObject, getDownloadFolderPath, getNextSeasonAndYear, getTitle, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, saveJSONasXML, selectFile, simpleDateFormat, timestampToTimeAgo, } from "./workers.js";
|
|
22
23
|
class AniList {
|
|
23
24
|
static importAnime() {
|
|
24
25
|
return __awaiter(this, void 0, void 0, function* () {
|
|
25
26
|
try {
|
|
26
27
|
const filename = yield selectFile(".json");
|
|
28
|
+
if (!filename) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
27
31
|
const filePath = join(getDownloadFolderPath(), filename);
|
|
28
32
|
const fileContent = yield readFile(filePath, "utf8");
|
|
29
33
|
const importedData = JSON.parse(fileContent);
|
|
34
|
+
if (!Validate.Import_JSON(importedData)) {
|
|
35
|
+
console.error(`\nInvalid JSON file.`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
30
38
|
let count = 0;
|
|
31
39
|
const batchSize = 1; // Number of requests in each batch
|
|
32
40
|
const delay = 1100; // delay to avoid rate-limiting
|
|
@@ -70,9 +78,16 @@ class AniList {
|
|
|
70
78
|
return __awaiter(this, void 0, void 0, function* () {
|
|
71
79
|
try {
|
|
72
80
|
const filename = yield selectFile(".json");
|
|
81
|
+
if (!filename) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
73
84
|
const filePath = join(getDownloadFolderPath(), filename);
|
|
74
85
|
const fileContent = yield readFile(filePath, "utf8");
|
|
75
86
|
const importedData = JSON.parse(fileContent);
|
|
87
|
+
if (!Validate.Import_JSON(importedData)) {
|
|
88
|
+
console.error(`\nInvalid JSON file.`);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
76
91
|
let count = 0;
|
|
77
92
|
const batchSize = 1; // Adjust batch size as per rate-limit constraints
|
|
78
93
|
const delay = 1100; // 2 seconds delay to avoid rate-limit
|
|
@@ -114,7 +129,76 @@ class AniList {
|
|
|
114
129
|
static exportAnime() {
|
|
115
130
|
return __awaiter(this, void 0, void 0, function* () {
|
|
116
131
|
var _a, _b, _c;
|
|
117
|
-
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) {
|
|
118
202
|
const { exportType } = yield inquirer.prompt([
|
|
119
203
|
{
|
|
120
204
|
type: "list",
|
|
@@ -123,116 +207,40 @@ class AniList {
|
|
|
123
207
|
choices: [
|
|
124
208
|
{ name: "CSV", value: 1 },
|
|
125
209
|
{ name: "JSON", value: 2 },
|
|
126
|
-
{ name: "XML (MyAnimeList
|
|
210
|
+
{ name: "XML (MyAnimeList)", value: 3 },
|
|
127
211
|
],
|
|
128
212
|
pageSize: 10,
|
|
129
213
|
},
|
|
130
214
|
]);
|
|
131
|
-
const
|
|
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
|
-
break;
|
|
157
|
-
case 3:
|
|
158
|
-
yield MyAnimeList.exportAnime();
|
|
159
|
-
break;
|
|
160
|
-
default:
|
|
161
|
-
console.log(`\nInvalid export type. ${exportType}`);
|
|
162
|
-
break;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
console.error(`\nNo anime(s) found in your lists.`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
console.error(`\nMust login to use this feature.`);
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
static exportManga() {
|
|
175
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
176
|
-
var _a, _b;
|
|
177
|
-
if (yield Auth.isLoggedIn()) {
|
|
178
|
-
const mangaLists = yield fetcher(currentUserMangaList, {
|
|
179
|
-
id: yield Auth.MyUserId(),
|
|
180
|
-
});
|
|
181
|
-
if (mangaLists) {
|
|
182
|
-
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) || [];
|
|
183
|
-
if (lists.length > 0) {
|
|
184
|
-
const { exportType } = yield inquirer.prompt([
|
|
185
|
-
{
|
|
186
|
-
type: "list",
|
|
187
|
-
name: "exportType",
|
|
188
|
-
message: "Choose export type:",
|
|
189
|
-
choices: [
|
|
190
|
-
{ name: "CSV", value: 1 },
|
|
191
|
-
{ name: "JSON", value: 2 },
|
|
192
|
-
{ name: "XML (MyAnimeList)", value: 3 },
|
|
193
|
-
],
|
|
194
|
-
pageSize: 10,
|
|
195
|
-
},
|
|
196
|
-
]);
|
|
197
|
-
const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
|
|
198
|
-
var _a, _b, _c;
|
|
199
|
-
return ({
|
|
200
|
-
id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
|
|
201
|
-
title: exportType === 1
|
|
202
|
-
? getTitle((_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.title)
|
|
203
|
-
: (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title,
|
|
204
|
-
private: entry.private,
|
|
205
|
-
chapters: entry.media.chapters,
|
|
206
|
-
progress: entry.progress,
|
|
207
|
-
status: entry === null || entry === void 0 ? void 0 : entry.status,
|
|
208
|
-
hiddenFromStatusLists: entry.hiddenFromStatusLists,
|
|
209
|
-
});
|
|
210
|
-
}));
|
|
211
|
-
switch (exportType) {
|
|
212
|
-
case 1:
|
|
213
|
-
yield saveJSONasCSV(mediaWithProgress, "manga");
|
|
214
|
-
break;
|
|
215
|
-
case 2:
|
|
216
|
-
yield saveJSONasJSON(mediaWithProgress, "manga");
|
|
217
|
-
break;
|
|
218
|
-
case 3:
|
|
219
|
-
yield MyAnimeList.exportManga();
|
|
220
|
-
break;
|
|
221
|
-
default:
|
|
222
|
-
console.log(`\nInvalid export type. ${exportType}`);
|
|
223
|
-
break;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
else {
|
|
227
|
-
console.log(`\nList seems to be empty.`);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
else {
|
|
231
|
-
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;
|
|
232
240
|
}
|
|
233
241
|
}
|
|
234
242
|
else {
|
|
235
|
-
console.
|
|
243
|
+
console.log(`\nList seems to be empty.`);
|
|
236
244
|
}
|
|
237
245
|
});
|
|
238
246
|
}
|
|
@@ -243,11 +251,10 @@ class AniList {
|
|
|
243
251
|
if (!(yield Auth.isLoggedIn())) {
|
|
244
252
|
return console.error(`\nPlease log in first to access your lists.`);
|
|
245
253
|
}
|
|
246
|
-
|
|
247
|
-
if (!userId) {
|
|
254
|
+
if (!(yield Auth.MyUserId())) {
|
|
248
255
|
return console.log(`\nFailed getting current user Id.`);
|
|
249
256
|
}
|
|
250
|
-
const data = yield fetcher(currentUserAnimeList, { id:
|
|
257
|
+
const data = yield fetcher(currentUserAnimeList, { id: yield Auth.MyUserId() });
|
|
251
258
|
if (data === null || data === void 0 ? void 0 : data.errors) {
|
|
252
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}`);
|
|
253
260
|
}
|
|
@@ -655,7 +662,7 @@ class AniList {
|
|
|
655
662
|
if (activities.length > 0) {
|
|
656
663
|
console.log(`\nRecent Activities:`);
|
|
657
664
|
activities.forEach(({ status, progress, media, createdAt }) => {
|
|
658
|
-
|
|
665
|
+
responsiveOutput(`${timestampToTimeAgo(createdAt)}\t${status} ${progress ? `${progress} of ` : ""}${getTitle(media === null || media === void 0 ? void 0 : media.title)}`);
|
|
659
666
|
});
|
|
660
667
|
}
|
|
661
668
|
else {
|
|
@@ -691,6 +698,33 @@ class AniList {
|
|
|
691
698
|
}
|
|
692
699
|
});
|
|
693
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
|
+
}
|
|
694
728
|
static searchAnime(search, count) {
|
|
695
729
|
return __awaiter(this, void 0, void 0, function* () {
|
|
696
730
|
var _a, _b, _c;
|
|
@@ -817,8 +851,15 @@ class MyAnimeList {
|
|
|
817
851
|
var _a, _b, _c, _d, _e;
|
|
818
852
|
try {
|
|
819
853
|
const filename = yield selectFile(".xml");
|
|
854
|
+
if (!filename) {
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
820
857
|
const filePath = join(getDownloadFolderPath(), filename);
|
|
821
858
|
const fileContent = yield readFile(filePath, "utf8");
|
|
859
|
+
if (!(yield Validate.Import_AnimeXML(fileContent))) {
|
|
860
|
+
console.error(`\nInvalid XML file.`);
|
|
861
|
+
return;
|
|
862
|
+
}
|
|
822
863
|
const parser = new XMLParser();
|
|
823
864
|
if (fileContent) {
|
|
824
865
|
const XMLObject = parser.parse(fileContent);
|
|
@@ -882,8 +923,15 @@ class MyAnimeList {
|
|
|
882
923
|
var _a, _b, _c, _d, _e;
|
|
883
924
|
try {
|
|
884
925
|
const filename = yield selectFile(".xml");
|
|
926
|
+
if (!filename) {
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
885
929
|
const filePath = join(getDownloadFolderPath(), filename);
|
|
886
930
|
const fileContent = yield readFile(filePath, "utf8");
|
|
931
|
+
if (!(yield Validate.Import_MangaXML(fileContent))) {
|
|
932
|
+
console.error(`\nInvalid XML file.`);
|
|
933
|
+
return;
|
|
934
|
+
}
|
|
887
935
|
const parser = new XMLParser();
|
|
888
936
|
if (fileContent) {
|
|
889
937
|
const XMLObject = parser.parse(fileContent);
|
|
@@ -954,7 +1002,7 @@ class MyAnimeList {
|
|
|
954
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) {
|
|
955
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;
|
|
956
1004
|
const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
|
|
957
|
-
var _a, _b, _c, _d, _e;
|
|
1005
|
+
var _a, _b, _c, _d, _e, _f;
|
|
958
1006
|
return ({
|
|
959
1007
|
id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
|
|
960
1008
|
malId: (_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.idMal,
|
|
@@ -964,13 +1012,10 @@ class MyAnimeList {
|
|
|
964
1012
|
progress: entry.progress,
|
|
965
1013
|
status: entry === null || entry === void 0 ? void 0 : entry.status,
|
|
966
1014
|
hiddenFromStatusLists: false,
|
|
1015
|
+
format: (_f = entry === null || entry === void 0 ? void 0 : entry.media) === null || _f === void 0 ? void 0 : _f.format,
|
|
967
1016
|
});
|
|
968
1017
|
}));
|
|
969
|
-
|
|
970
|
-
const path = join(getDownloadFolderPath(), `${yield Auth.MyUserName()}@irfanshadikrishad-anilist-myanimelist(anime)-${getFormattedDate()}.xml`);
|
|
971
|
-
yield writeFile(path, yield xmlContent, "utf8");
|
|
972
|
-
console.log(`Generated XML for MyAnimeList.`);
|
|
973
|
-
open(getDownloadFolderPath());
|
|
1018
|
+
yield saveJSONasXML(mediaWithProgress, 0);
|
|
974
1019
|
}
|
|
975
1020
|
else {
|
|
976
1021
|
console.log(`\nHey, ${yield Auth.MyUserName()}. Your anime list seems to be empty.`);
|
|
@@ -1005,11 +1050,7 @@ class MyAnimeList {
|
|
|
1005
1050
|
status: entry.status,
|
|
1006
1051
|
hiddenFromStatusLists: entry.hiddenFromStatusLists,
|
|
1007
1052
|
})));
|
|
1008
|
-
|
|
1009
|
-
const path = join(getDownloadFolderPath(), `${yield Auth.MyUserName()}@irfanshadikrishad-anilist-myanimelist(manga)-${getFormattedDate()}.xml`);
|
|
1010
|
-
yield writeFile(path, yield XMLContent, "utf8");
|
|
1011
|
-
console.log(`Generated XML for MyAnimeList.`);
|
|
1012
|
-
open(getDownloadFolderPath());
|
|
1053
|
+
yield saveJSONasXML(mediaWithProgress, 1);
|
|
1013
1054
|
}
|
|
1014
1055
|
else {
|
|
1015
1056
|
console.log(`\nHey, ${yield Auth.MyUserName()}. Your anime list seems to be empty.`);
|
|
@@ -1027,10 +1068,17 @@ class AniDB {
|
|
|
1027
1068
|
var _a, _b;
|
|
1028
1069
|
try {
|
|
1029
1070
|
const filename = yield selectFile(".json");
|
|
1071
|
+
if (!filename) {
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1030
1074
|
const filePath = join(getDownloadFolderPath(), filename);
|
|
1031
1075
|
const fileContent = yield readFile(filePath, "utf8");
|
|
1032
1076
|
const js0n_repaired = jsonrepair(fileContent);
|
|
1033
|
-
if (
|
|
1077
|
+
if (!(yield Validate.Import_AniDBJSONLarge(js0n_repaired))) {
|
|
1078
|
+
console.error(`\nInvalid JSON Large file.`);
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
if (js0n_repaired) {
|
|
1034
1082
|
const obj3ct = yield JSON.parse(js0n_repaired);
|
|
1035
1083
|
const animeList = obj3ct === null || obj3ct === void 0 ? void 0 : obj3ct.anime;
|
|
1036
1084
|
if ((animeList === null || animeList === void 0 ? void 0 : animeList.length) > 0) {
|
|
@@ -1072,7 +1120,7 @@ class AniDB {
|
|
|
1072
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;
|
|
1073
1121
|
if (entryId) {
|
|
1074
1122
|
count++;
|
|
1075
|
-
|
|
1123
|
+
responsiveOutput(`[${count}]\t${entryId} ✅\t${anidbId}\t${anilistId}\t(${ownEpisodes}/${totalEpisodes})\t${status}–>${getStatus(status, ownEpisodes)}`);
|
|
1076
1124
|
}
|
|
1077
1125
|
// Rate limit each API call to avoid server overload
|
|
1078
1126
|
// await new Promise((resolve) => setTimeout(resolve, 1100))
|
|
@@ -1089,9 +1137,9 @@ class AniDB {
|
|
|
1089
1137
|
});
|
|
1090
1138
|
}
|
|
1091
1139
|
}
|
|
1092
|
-
|
|
1140
|
+
responsiveOutput(`\nAccuracy: ${(((animeList.length - missed.length) / animeList.length) * 100).toFixed(2)}%\tTotal Processed: ${iteration}\tMissed: ${missed.length}`);
|
|
1093
1141
|
if (missed.length > 0) {
|
|
1094
|
-
|
|
1142
|
+
responsiveOutput(`Exporting missed entries to JSON file, Please add them manually.`);
|
|
1095
1143
|
yield saveJSONasJSON(missed, "anidb-missed");
|
|
1096
1144
|
}
|
|
1097
1145
|
}
|
|
@@ -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
|
@@ -35,9 +35,4 @@ mutation ($mediaId: Int, $progress: Int, $status: MediaListStatus, $hiddenFromSt
|
|
|
35
35
|
) { id progress hiddenFromStatusLists private }
|
|
36
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, };
|
package/bin/helpers/queries.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ declare const currentUserQuery = "{\n Viewer {\n id name about bans siteUrl
|
|
|
2
2
|
declare const trendingQuery = "query ($page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n media(sort: TRENDING_DESC, type: ANIME) { id title { romaji english } }\n }\n}";
|
|
3
3
|
declare const popularQuery = "query ($page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n media(sort: POPULARITY_DESC, type: ANIME) { id title { romaji english } }\n }\n}";
|
|
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
|
-
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 } status episodes siteUrl } } }\n }\n}\n";
|
|
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 } status chapters } } }\n }\n}\n";
|
|
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
|
+
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
7
|
declare const deleteMediaEntryMutation = "mutation($id: Int!) {\n DeleteMediaListEntry(id: $id) { deleted }\n}";
|
|
8
8
|
declare const deleteMangaEntryMutation = "mutation($id: Int) {\n DeleteMediaListEntry(id: $id) { deleted }\n}";
|
|
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}";
|
|
@@ -17,11 +17,10 @@ declare const activityMangaListQuery = "query ($userId: Int, $page: Int, $perPag
|
|
|
17
17
|
declare const activityMessageQuery = "query ($userId: Int, $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n activities(userId: $userId, type: MESSAGE, sort: ID_DESC) {\n ... on MessageActivity { id type message recipient { id name } createdAt }\n }\n }\n}";
|
|
18
18
|
declare const activityAllQuery = "query ($userId: Int, $page: Int, $perPage: Int) {\n Page(page: $page, perPage: $perPage) {\n activities(userId: $userId, sort: ID_DESC) {\n ... on TextActivity { id type text createdAt user { id name } }\n ... on ListActivity { id type status progress createdAt media { id title { romaji english native } } }\n ... on MessageActivity { id type message recipient { id name } createdAt }\n }\n }\n}";
|
|
19
19
|
declare const activityMediaList = "query ($userId: Int, $page: Int, $perPage: Int, $type: ActivityType) {\n Page(page: $page, perPage: $perPage) {\n pageInfo { total currentPage lastPage hasNextPage perPage }\n activities(userId: $userId, type: $type, sort: ID_DESC) {\n ... on ListActivity { id type status progress media { id title { romaji english native } format } createdAt }\n }\n }\n}";
|
|
20
|
-
declare const malIdToAnilistAnimeId = "query ($malId: Int) {\n Media(idMal: $malId, type: ANIME) {
|
|
21
|
-
declare const malIdToAnilistMangaId = "query ($malId: Int) {\n Media(idMal: $malId, type: MANGA) {
|
|
22
|
-
declare const
|
|
23
|
-
declare const
|
|
24
|
-
declare const
|
|
25
|
-
declare const
|
|
26
|
-
|
|
27
|
-
export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, followingActivitiesQuery, globalActivitiesQuery, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, specificUserActivitiesQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, };
|
|
20
|
+
declare const malIdToAnilistAnimeId = "query ($malId: Int) {\n Media(idMal: $malId, type: ANIME) {\n id title { romaji english } } \n}\n";
|
|
21
|
+
declare const malIdToAnilistMangaId = "query ($malId: Int) {\n Media(idMal: $malId, type: MANGA) {\n id title { romaji english } } \n}\n";
|
|
22
|
+
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
|
+
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, deleteMangaEntryMutation, deleteMediaEntryMutation, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaDetailsQuery, mangaSearchQuery, popularQuery, toggleFollowMutation, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, };
|
package/bin/helpers/queries.js
CHANGED
|
@@ -26,13 +26,13 @@ const userQuery = `query ($username: String) {
|
|
|
26
26
|
}`;
|
|
27
27
|
const currentUserAnimeList = `query ($id: Int) {
|
|
28
28
|
MediaListCollection(userId: $id, type: ANIME) {
|
|
29
|
-
lists { name entries { id progress hiddenFromStatusLists status media { id idMal title { romaji english } status episodes siteUrl } } }
|
|
29
|
+
lists { name entries { id progress hiddenFromStatusLists status media { id idMal title { romaji english native userPreferred } status episodes siteUrl format } } }
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
`;
|
|
33
33
|
const currentUserMangaList = `query ($id: Int) {
|
|
34
34
|
MediaListCollection(userId: $id, type: MANGA) {
|
|
35
|
-
lists { name entries { id progress hiddenFromStatusLists private status media { id idMal title { romaji english } status chapters } } }
|
|
35
|
+
lists { name entries { id progress hiddenFromStatusLists private status media { id idMal title { romaji english native userPreferred } status chapters } } }
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
`;
|
|
@@ -120,56 +120,39 @@ const activityMediaList = `query ($userId: Int, $page: Int, $perPage: Int, $type
|
|
|
120
120
|
}
|
|
121
121
|
}`;
|
|
122
122
|
const malIdToAnilistAnimeId = `query ($malId: Int) {
|
|
123
|
-
Media(idMal: $malId, type: ANIME) {
|
|
123
|
+
Media(idMal: $malId, type: ANIME) {
|
|
124
|
+
id title { romaji english } }
|
|
125
|
+
}
|
|
124
126
|
`;
|
|
125
127
|
const malIdToAnilistMangaId = `query ($malId: Int) {
|
|
126
|
-
Media(idMal: $malId, type: MANGA) {
|
|
127
|
-
|
|
128
|
-
const followingActivitiesQuery = `
|
|
129
|
-
query ($page: Int, $perPage: Int) {
|
|
130
|
-
Page(page: $page, perPage: $perPage) {
|
|
131
|
-
activities(isFollowing: true, sort: ID_DESC) {
|
|
132
|
-
... on TextActivity { id type isLiked createdAt user { id name } }
|
|
133
|
-
... on ListActivity { id type isLiked status progress media { title { userPreferred } } createdAt user { id name } }
|
|
134
|
-
... on MessageActivity { id type isLiked message createdAt recipient { id name } }
|
|
135
|
-
}
|
|
136
|
-
}
|
|
128
|
+
Media(idMal: $malId, type: MANGA) {
|
|
129
|
+
id title { romaji english } }
|
|
137
130
|
}
|
|
138
131
|
`;
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
... on TextActivity { id type isLiked createdAt user { id name } }
|
|
144
|
-
... on ListActivity { id type isLiked status progress media { title { userPreferred } } createdAt user { id name } }
|
|
145
|
-
... on MessageActivity { id type isLiked message createdAt recipient { id name } }
|
|
146
|
-
}
|
|
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 }
|
|
147
136
|
}
|
|
148
137
|
}
|
|
149
138
|
`;
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
... on TextActivity { id type isLiked createdAt user { id name } }
|
|
155
|
-
... on ListActivity { id type isLiked status progress media { title { userPreferred } } createdAt user { id name } }
|
|
156
|
-
... on MessageActivity { messenger { name } id type isLiked message createdAt recipient { id name } }
|
|
157
|
-
}
|
|
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 }
|
|
158
143
|
}
|
|
159
144
|
}
|
|
160
145
|
`;
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
pageInfo { total perPage currentPage lastPage hasNextPage }
|
|
164
|
-
following(userId: $userId, sort: [USERNAME]) { id name avatar { large medium } bannerImage }
|
|
165
|
-
}
|
|
146
|
+
const toggleFollowMutation = `mutation ($userId: Int!) {
|
|
147
|
+
ToggleFollow(userId: $userId) { id name isFollower isFollowing }
|
|
166
148
|
}
|
|
167
149
|
`;
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
150
|
+
const mangaDetailsQuery = `query ($id: Int) {
|
|
151
|
+
Media(id: $id, type: MANGA) {
|
|
152
|
+
id title { romaji english native userPreferred } coverImage { color medium large extraLarge }
|
|
153
|
+
bannerImage description chapters volumes status genres
|
|
154
|
+
startDate { year month day } endDate { year month day }
|
|
172
155
|
}
|
|
173
156
|
}
|
|
174
157
|
`;
|
|
175
|
-
export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation,
|
|
158
|
+
export { activityAllQuery, activityAnimeListQuery, activityMangaListQuery, activityMediaList, activityMessageQuery, activityTextQuery, animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, currentUserQuery, deleteMangaEntryMutation, deleteMediaEntryMutation, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaDetailsQuery, mangaSearchQuery, popularQuery, toggleFollowMutation, trendingQuery, upcomingAnimesQuery, userActivityQuery, userFollowersQuery, userFollowingQuery, userQuery, };
|