@irfanshadikrishad/anilist 1.0.7 → 1.0.9
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 +232 -232
- package/bin/helpers/auth.d.ts +23 -10
- package/bin/helpers/auth.js +597 -196
- package/bin/helpers/fetcher.js +3 -3
- package/bin/helpers/lists.d.ts +22 -8
- package/bin/helpers/lists.js +916 -538
- package/bin/helpers/mutations.d.ts +1 -1
- package/bin/helpers/mutations.js +1 -1
- package/bin/helpers/queries.d.ts +5 -3
- package/bin/helpers/queries.js +13 -3
- package/bin/helpers/types.d.ts +101 -1
- package/bin/helpers/types.js +26 -1
- package/bin/helpers/workers.d.ts +9 -3
- package/bin/helpers/workers.js +125 -99
- package/bin/index.js +24 -25
- package/package.json +7 -3
- package/CHANGELOG.md +0 -18
- package/CODE_OF_CONDUCT.md +0 -43
- package/CONTRIBUTING.md +0 -75
- package/bin/helpers/more.d.ts +0 -11
- package/bin/helpers/more.js +0 -474
package/bin/helpers/lists.js
CHANGED
|
@@ -7,120 +7,710 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import
|
|
10
|
+
import { XMLParser } from "fast-xml-parser";
|
|
11
|
+
import { readFile, writeFile } from "fs/promises";
|
|
11
12
|
import inquirer from "inquirer";
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { isLoggedIn, currentUsersId, retriveAccessToken } from "./auth.js";
|
|
16
|
-
import { addAnimeToListMutation, addMangaToListMutation } from "./mutations.js";
|
|
13
|
+
import fetch from "node-fetch";
|
|
14
|
+
import { join } from "path";
|
|
15
|
+
import { Auth } from "./auth.js";
|
|
17
16
|
import { fetcher } from "./fetcher.js";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
type: "list",
|
|
39
|
-
name: "selectedAnime",
|
|
40
|
-
message: "Select anime to add to the list:",
|
|
41
|
-
choices: media.map((upx, idx) => ({
|
|
42
|
-
name: `[${idx + 1}] ${getTitle(upx === null || upx === void 0 ? void 0 : upx.title)}`,
|
|
43
|
-
value: upx === null || upx === void 0 ? void 0 : upx.id,
|
|
44
|
-
})),
|
|
45
|
-
pageSize: 10,
|
|
46
|
-
},
|
|
47
|
-
]);
|
|
48
|
-
// Where to save
|
|
49
|
-
const { selectedListType } = yield inquirer.prompt([
|
|
50
|
-
{
|
|
51
|
-
type: "list",
|
|
52
|
-
name: "selectedListType",
|
|
53
|
-
message: "Select the list where you want to save this anime:",
|
|
54
|
-
choices: [
|
|
55
|
-
{ name: "Planning", value: "PLANNING" },
|
|
56
|
-
{ name: "Watching", value: "CURRENT" },
|
|
57
|
-
{ name: "Completed", value: "COMPLETED" },
|
|
58
|
-
{ name: "Paused", value: "PAUSED" },
|
|
59
|
-
{ name: "Dropped", value: "DROPPED" },
|
|
60
|
-
],
|
|
61
|
-
},
|
|
62
|
-
]);
|
|
63
|
-
// Lets save to the list now
|
|
64
|
-
if (yield isLoggedIn()) {
|
|
65
|
-
const query = addAnimeToListMutation;
|
|
17
|
+
import { addAnimeToListMutation, addMangaToListMutation, saveAnimeWithProgressMutation, saveMangaWithProgressMutation, } from "./mutations.js";
|
|
18
|
+
import { animeDetailsQuery, animeSearchQuery, currentUserAnimeList, currentUserMangaList, malIdToAnilistAnimeId, malIdToAnilistMangaId, mangaSearchQuery, popularQuery, trendingQuery, upcomingAnimesQuery, userActivityQuery, userQuery, } from "./queries.js";
|
|
19
|
+
import { AniListMediaStatus, } from "./types.js";
|
|
20
|
+
import { aniListEndpoint, createAnimeListXML, createMangaListXML, formatDateObject, getDownloadFolderPath, getFormattedDate, getNextSeasonAndYear, getTitle, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, selectFile, } from "./workers.js";
|
|
21
|
+
class AniList {
|
|
22
|
+
static importAnime() {
|
|
23
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
try {
|
|
25
|
+
const filename = yield selectFile(".json");
|
|
26
|
+
const filePath = join(getDownloadFolderPath(), filename);
|
|
27
|
+
const fileContent = yield readFile(filePath, "utf8");
|
|
28
|
+
const importedData = JSON.parse(fileContent);
|
|
29
|
+
let count = 0;
|
|
30
|
+
const batchSize = 1; // Number of requests in each batch
|
|
31
|
+
const delay = 1100; // delay to avoid rate-limiting
|
|
32
|
+
for (let i = 0; i < importedData.length; i += batchSize) {
|
|
33
|
+
const batch = importedData.slice(i, i + batchSize);
|
|
34
|
+
yield Promise.all(batch.map((anime) => __awaiter(this, void 0, void 0, function* () {
|
|
35
|
+
var _a, _b;
|
|
36
|
+
const query = saveAnimeWithProgressMutation;
|
|
66
37
|
const variables = {
|
|
67
|
-
mediaId:
|
|
68
|
-
|
|
38
|
+
mediaId: anime === null || anime === void 0 ? void 0 : anime.id,
|
|
39
|
+
progress: anime === null || anime === void 0 ? void 0 : anime.progress,
|
|
40
|
+
status: anime === null || anime === void 0 ? void 0 : anime.status,
|
|
41
|
+
hiddenFromStatusLists: false,
|
|
69
42
|
};
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
43
|
+
try {
|
|
44
|
+
const save = yield fetcher(query, variables);
|
|
45
|
+
if (save) {
|
|
46
|
+
const id = (_b = (_a = save === null || save === void 0 ? void 0 : save.data) === null || _a === void 0 ? void 0 : _a.SaveMediaListEntry) === null || _b === void 0 ? void 0 : _b.id;
|
|
47
|
+
count++;
|
|
48
|
+
console.log(`[${count}] ${anime === null || anime === void 0 ? void 0 : anime.id}-${id} ✅`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.error(`\nError saving ${anime === null || anime === void 0 ? void 0 : anime.id}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
console.error(`\nError saving ${anime === null || anime === void 0 ? void 0 : anime.id}: ${error.message}`);
|
|
56
|
+
}
|
|
57
|
+
})));
|
|
58
|
+
// Avoid rate-limiting: Wait before sending the next batch
|
|
59
|
+
yield new Promise((resolve) => setTimeout(resolve, delay));
|
|
60
|
+
}
|
|
61
|
+
console.log(`\nTotal ${count} anime(s) imported successfully.`);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
console.error(`\n${error.message}`);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
static importManga() {
|
|
69
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
70
|
+
try {
|
|
71
|
+
const filename = yield selectFile(".json");
|
|
72
|
+
const filePath = join(getDownloadFolderPath(), filename);
|
|
73
|
+
const fileContent = yield readFile(filePath, "utf8");
|
|
74
|
+
const importedData = JSON.parse(fileContent);
|
|
75
|
+
let count = 0;
|
|
76
|
+
const batchSize = 1; // Adjust batch size as per rate-limit constraints
|
|
77
|
+
const delay = 1100; // 2 seconds delay to avoid rate-limit
|
|
78
|
+
// Process in batches
|
|
79
|
+
for (let i = 0; i < importedData.length; i += batchSize) {
|
|
80
|
+
const batch = importedData.slice(i, i + batchSize);
|
|
81
|
+
yield Promise.all(batch.map((manga) => __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
var _a, _b;
|
|
83
|
+
const query = saveMangaWithProgressMutation;
|
|
84
|
+
const variables = {
|
|
85
|
+
mediaId: manga === null || manga === void 0 ? void 0 : manga.id,
|
|
86
|
+
progress: manga === null || manga === void 0 ? void 0 : manga.progress,
|
|
87
|
+
status: manga === null || manga === void 0 ? void 0 : manga.status,
|
|
88
|
+
hiddenFromStatusLists: false,
|
|
89
|
+
private: manga === null || manga === void 0 ? void 0 : manga.private,
|
|
90
|
+
};
|
|
91
|
+
try {
|
|
92
|
+
const save = yield fetcher(query, variables);
|
|
93
|
+
if (save) {
|
|
94
|
+
const id = (_b = (_a = save === null || save === void 0 ? void 0 : save.data) === null || _a === void 0 ? void 0 : _a.SaveMediaListEntry) === null || _b === void 0 ? void 0 : _b.id;
|
|
95
|
+
count++;
|
|
96
|
+
console.log(`[${count}] ${manga === null || manga === void 0 ? void 0 : manga.id}-${id} ✅`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
console.error(`\nError saving ${manga === null || manga === void 0 ? void 0 : manga.id}: ${err.message}`);
|
|
101
|
+
}
|
|
102
|
+
})));
|
|
103
|
+
// Avoid rate-limit by adding delay after processing each batch
|
|
104
|
+
yield new Promise((resolve) => setTimeout(resolve, delay));
|
|
105
|
+
}
|
|
106
|
+
console.log(`\nTotal ${count} manga(s) imported successfully.`);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
console.error(`\nError: ${error.message}`);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
static exportAnime() {
|
|
114
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
115
|
+
var _a, _b, _c;
|
|
116
|
+
if (yield Auth.isLoggedIn()) {
|
|
117
|
+
const { exportType } = yield inquirer.prompt([
|
|
118
|
+
{
|
|
119
|
+
type: "list",
|
|
120
|
+
name: "exportType",
|
|
121
|
+
message: "Choose export type:",
|
|
122
|
+
choices: [
|
|
123
|
+
{ name: "CSV", value: 1 },
|
|
124
|
+
{ name: "JSON", value: 2 },
|
|
125
|
+
{ name: "XML (MyAnimeList)", value: 3 },
|
|
126
|
+
],
|
|
127
|
+
pageSize: 10,
|
|
128
|
+
},
|
|
129
|
+
]);
|
|
130
|
+
const animeList = yield fetcher(currentUserAnimeList, {
|
|
131
|
+
id: yield Auth.MyUserId(),
|
|
132
|
+
});
|
|
133
|
+
if (animeList) {
|
|
134
|
+
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 : [];
|
|
135
|
+
const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
|
|
136
|
+
var _a, _b, _c, _d, _e;
|
|
137
|
+
return ({
|
|
138
|
+
id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
|
|
139
|
+
title: exportType === 1
|
|
140
|
+
? getTitle((_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.title)
|
|
141
|
+
: (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title,
|
|
142
|
+
episodes: (_d = entry === null || entry === void 0 ? void 0 : entry.media) === null || _d === void 0 ? void 0 : _d.episodes,
|
|
143
|
+
siteUrl: (_e = entry === null || entry === void 0 ? void 0 : entry.media) === null || _e === void 0 ? void 0 : _e.siteUrl,
|
|
144
|
+
progress: entry.progress,
|
|
145
|
+
status: entry === null || entry === void 0 ? void 0 : entry.status,
|
|
146
|
+
hiddenFromStatusLists: entry.hiddenFromStatusLists,
|
|
147
|
+
});
|
|
148
|
+
}));
|
|
149
|
+
switch (exportType) {
|
|
150
|
+
case 1:
|
|
151
|
+
yield saveJSONasCSV(mediaWithProgress, "anime");
|
|
152
|
+
break;
|
|
153
|
+
case 2:
|
|
154
|
+
yield saveJSONasJSON(mediaWithProgress, "anime");
|
|
155
|
+
break;
|
|
156
|
+
case 3:
|
|
157
|
+
yield MyAnimeList.exportAnime();
|
|
158
|
+
break;
|
|
159
|
+
default:
|
|
160
|
+
console.log(`\nInvalid export type. ${exportType}`);
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
console.error(`\nNo anime(s) found in your lists.`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
console.error(`\nMust login to use this feature.`);
|
|
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
|
+
const mangaLists = yield fetcher(currentUserMangaList, {
|
|
178
|
+
id: yield Auth.MyUserId(),
|
|
179
|
+
});
|
|
180
|
+
if (mangaLists) {
|
|
181
|
+
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) || [];
|
|
182
|
+
if (lists.length > 0) {
|
|
183
|
+
const { exportType } = yield inquirer.prompt([
|
|
184
|
+
{
|
|
185
|
+
type: "list",
|
|
186
|
+
name: "exportType",
|
|
187
|
+
message: "Choose export type:",
|
|
188
|
+
choices: [
|
|
189
|
+
{ name: "CSV", value: 1 },
|
|
190
|
+
{ name: "JSON", value: 2 },
|
|
191
|
+
{ name: "XML (MyAnimeList)", value: 3 },
|
|
192
|
+
],
|
|
193
|
+
pageSize: 10,
|
|
194
|
+
},
|
|
195
|
+
]);
|
|
196
|
+
const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
|
|
197
|
+
var _a, _b, _c;
|
|
198
|
+
return ({
|
|
199
|
+
id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
|
|
200
|
+
title: exportType === 1
|
|
201
|
+
? getTitle((_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.title)
|
|
202
|
+
: (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title,
|
|
203
|
+
private: entry.private,
|
|
204
|
+
chapters: entry.media.chapters,
|
|
205
|
+
progress: entry.progress,
|
|
206
|
+
status: entry === null || entry === void 0 ? void 0 : entry.status,
|
|
207
|
+
hiddenFromStatusLists: entry.hiddenFromStatusLists,
|
|
208
|
+
});
|
|
209
|
+
}));
|
|
210
|
+
switch (exportType) {
|
|
211
|
+
case 1:
|
|
212
|
+
yield saveJSONasCSV(mediaWithProgress, "manga");
|
|
213
|
+
break;
|
|
214
|
+
case 2:
|
|
215
|
+
yield saveJSONasJSON(mediaWithProgress, "manga");
|
|
216
|
+
break;
|
|
217
|
+
case 3:
|
|
218
|
+
yield MyAnimeList.exportManga();
|
|
219
|
+
break;
|
|
220
|
+
default:
|
|
221
|
+
console.log(`\nInvalid export type. ${exportType}`);
|
|
222
|
+
break;
|
|
74
223
|
}
|
|
75
224
|
}
|
|
76
225
|
else {
|
|
77
|
-
console.
|
|
226
|
+
console.log(`\nList seems to be empty.`);
|
|
78
227
|
}
|
|
79
228
|
}
|
|
80
229
|
else {
|
|
81
|
-
console.
|
|
230
|
+
console.error(`\nCould not get manga list.`);
|
|
82
231
|
}
|
|
83
232
|
}
|
|
84
233
|
else {
|
|
85
|
-
console.
|
|
234
|
+
console.error(`\nPlease login to use this feature.`);
|
|
86
235
|
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
static MyAnime() {
|
|
239
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
240
|
+
var _a, _b, _c;
|
|
241
|
+
try {
|
|
242
|
+
if (!(yield Auth.isLoggedIn())) {
|
|
243
|
+
return console.error(`\nPlease log in first to access your lists.`);
|
|
244
|
+
}
|
|
245
|
+
const userId = yield Auth.MyUserId();
|
|
246
|
+
if (!userId) {
|
|
247
|
+
return console.log(`\nFailed getting current user Id.`);
|
|
248
|
+
}
|
|
249
|
+
const request = yield fetch(aniListEndpoint, {
|
|
250
|
+
method: "POST",
|
|
251
|
+
headers: {
|
|
252
|
+
"content-type": "application/json",
|
|
253
|
+
"Authorization": `Bearer ${yield Auth.RetriveAccessToken()}`,
|
|
254
|
+
},
|
|
255
|
+
body: JSON.stringify({
|
|
256
|
+
query: currentUserAnimeList,
|
|
257
|
+
variables: { id: userId },
|
|
258
|
+
}),
|
|
259
|
+
});
|
|
260
|
+
const { data, errors } = yield request.json();
|
|
261
|
+
if (request.status !== 200 || errors) {
|
|
262
|
+
return console.log(`\nSomething went wrong. ${(_a = errors === null || errors === void 0 ? void 0 : errors[0]) === null || _a === void 0 ? void 0 : _a.message}`);
|
|
263
|
+
}
|
|
264
|
+
const lists = (_b = data === null || data === void 0 ? void 0 : data.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists;
|
|
265
|
+
if (!lists || lists.length === 0) {
|
|
266
|
+
return console.log(`\nYou seem to have no anime(s) in your lists.`);
|
|
267
|
+
}
|
|
268
|
+
const { selectedList } = yield inquirer.prompt([
|
|
269
|
+
{
|
|
270
|
+
type: "list",
|
|
271
|
+
name: "selectedList",
|
|
272
|
+
message: "Select an anime list:",
|
|
273
|
+
choices: lists.map((list) => list.name),
|
|
274
|
+
},
|
|
275
|
+
]);
|
|
276
|
+
const selectedEntries = lists.find((list) => list.name === selectedList);
|
|
277
|
+
if (!selectedEntries || !selectedEntries.entries.length) {
|
|
278
|
+
return console.log(`\nNo entries found or not available at this moment.`);
|
|
279
|
+
}
|
|
280
|
+
console.log(`\nEntries for '${selectedEntries.name}':`);
|
|
281
|
+
const { selectedAnime } = yield inquirer.prompt([
|
|
282
|
+
{
|
|
283
|
+
type: "list",
|
|
284
|
+
name: "selectedAnime",
|
|
285
|
+
message: "Select anime to add to the list:",
|
|
286
|
+
choices: selectedEntries.entries.map((entry, idx) => ({
|
|
287
|
+
name: `[${idx + 1}] ${getTitle(entry.media.title)}`,
|
|
288
|
+
value: entry.media.id,
|
|
289
|
+
})),
|
|
290
|
+
pageSize: 10,
|
|
291
|
+
},
|
|
292
|
+
]);
|
|
293
|
+
const { selectedListType } = yield inquirer.prompt([
|
|
294
|
+
{
|
|
295
|
+
type: "list",
|
|
296
|
+
name: "selectedListType",
|
|
297
|
+
message: "Select the list where you want to save this anime:",
|
|
298
|
+
choices: [
|
|
299
|
+
{ name: "Planning", value: "PLANNING" },
|
|
300
|
+
{ name: "Watching", value: "CURRENT" },
|
|
301
|
+
{ name: "Completed", value: "COMPLETED" },
|
|
302
|
+
{ name: "Paused", value: "PAUSED" },
|
|
303
|
+
{ name: "Dropped", value: "DROPPED" },
|
|
304
|
+
],
|
|
305
|
+
},
|
|
306
|
+
]);
|
|
307
|
+
const query = addAnimeToListMutation;
|
|
308
|
+
const variables = { mediaId: selectedAnime, status: selectedListType };
|
|
309
|
+
const saveResponse = yield fetcher(query, variables);
|
|
310
|
+
if (saveResponse) {
|
|
311
|
+
const savedEntry = (_c = saveResponse.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
|
|
312
|
+
console.log(`\nEntry ${savedEntry === null || savedEntry === void 0 ? void 0 : savedEntry.id}. Saved as ${savedEntry === null || savedEntry === void 0 ? void 0 : savedEntry.status}.`);
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
console.error(`\nPlease log in first to use this feature.`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
catch (error) {
|
|
319
|
+
console.log(`\nSomething went wrong. ${error.message}`);
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
static MyManga() {
|
|
324
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
325
|
+
var _a, _b, _c, _d, _e;
|
|
326
|
+
try {
|
|
327
|
+
if (!(yield Auth.isLoggedIn())) {
|
|
328
|
+
return console.error(`\nPlease log in first to access your lists.`);
|
|
329
|
+
}
|
|
330
|
+
const userId = yield Auth.MyUserId();
|
|
331
|
+
if (!userId) {
|
|
332
|
+
return console.error(`\nFailed to get the current user ID.`);
|
|
333
|
+
}
|
|
334
|
+
const token = yield Auth.RetriveAccessToken();
|
|
335
|
+
const request = yield fetch(aniListEndpoint, {
|
|
336
|
+
method: "POST",
|
|
337
|
+
headers: {
|
|
338
|
+
"Content-Type": "application/json",
|
|
339
|
+
"Authorization": `Bearer ${token}`,
|
|
340
|
+
},
|
|
341
|
+
body: JSON.stringify({
|
|
342
|
+
query: currentUserMangaList,
|
|
343
|
+
variables: { id: userId },
|
|
344
|
+
}),
|
|
345
|
+
});
|
|
346
|
+
const { data, errors } = yield request.json();
|
|
347
|
+
if (request.status !== 200 || errors) {
|
|
348
|
+
return console.error(`\nFailed to fetch manga lists. ${((_a = errors === null || errors === void 0 ? void 0 : errors[0]) === null || _a === void 0 ? void 0 : _a.message) || "Unknown error"}`);
|
|
349
|
+
}
|
|
350
|
+
const lists = (_b = data === null || data === void 0 ? void 0 : data.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists;
|
|
351
|
+
if (!lists || lists.length === 0) {
|
|
352
|
+
return console.log("\nYou don't seem to have any manga in your lists.");
|
|
353
|
+
}
|
|
354
|
+
const { selectedList } = yield inquirer.prompt([
|
|
355
|
+
{
|
|
356
|
+
type: "list",
|
|
357
|
+
name: "selectedList",
|
|
358
|
+
message: "Select a manga list:",
|
|
359
|
+
choices: lists.map((list) => list.name),
|
|
360
|
+
},
|
|
361
|
+
]);
|
|
362
|
+
const selectedEntries = lists.find((list) => list.name === selectedList);
|
|
363
|
+
if (!selectedEntries || selectedEntries.entries.length === 0) {
|
|
364
|
+
return console.log("\nNo manga entries found in the selected list.");
|
|
365
|
+
}
|
|
366
|
+
console.log(`\nEntries for '${selectedEntries.name}':`);
|
|
367
|
+
const { selectedManga } = yield inquirer.prompt([
|
|
368
|
+
{
|
|
369
|
+
type: "list",
|
|
370
|
+
name: "selectedManga",
|
|
371
|
+
message: "Select a manga to add to the list:",
|
|
372
|
+
choices: selectedEntries.entries.map((entry, idx) => {
|
|
373
|
+
var _a;
|
|
374
|
+
return ({
|
|
375
|
+
name: `[${idx + 1}] ${getTitle(entry.media.title)}`,
|
|
376
|
+
value: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
|
|
377
|
+
});
|
|
378
|
+
}),
|
|
379
|
+
pageSize: 10,
|
|
380
|
+
},
|
|
381
|
+
]);
|
|
382
|
+
const { selectedListType } = yield inquirer.prompt([
|
|
383
|
+
{
|
|
384
|
+
type: "list",
|
|
385
|
+
name: "selectedListType",
|
|
386
|
+
message: "Select the list where you want to save this manga:",
|
|
387
|
+
choices: [
|
|
388
|
+
{ name: "Planning", value: "PLANNING" },
|
|
389
|
+
{ name: "Reading", value: "CURRENT" },
|
|
390
|
+
{ name: "Completed", value: "COMPLETED" },
|
|
391
|
+
{ name: "Paused", value: "PAUSED" },
|
|
392
|
+
{ name: "Dropped", value: "DROPPED" },
|
|
393
|
+
],
|
|
394
|
+
},
|
|
395
|
+
]);
|
|
396
|
+
const saveRequest = yield fetch(aniListEndpoint, {
|
|
397
|
+
method: "POST",
|
|
398
|
+
headers: {
|
|
399
|
+
"Content-Type": "application/json",
|
|
400
|
+
"Authorization": `Bearer ${token}`,
|
|
401
|
+
},
|
|
402
|
+
body: JSON.stringify({
|
|
403
|
+
query: addMangaToListMutation,
|
|
404
|
+
variables: { mediaId: selectedManga, status: selectedListType },
|
|
405
|
+
}),
|
|
406
|
+
});
|
|
407
|
+
const saveResponse = yield saveRequest.json();
|
|
408
|
+
const saved = (_c = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
|
|
409
|
+
if (saved) {
|
|
410
|
+
console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
413
|
+
console.error(`\nFailed to save the manga. ${((_e = (_d = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.errors) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.message) || "Unknown error"}`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
catch (error) {
|
|
417
|
+
console.error(`\nSomething went wrong. ${error.message}`);
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
static getTrendingAnime(count) {
|
|
422
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
423
|
+
var _a, _b, _c, _d, _e;
|
|
424
|
+
try {
|
|
425
|
+
const request = yield fetch(aniListEndpoint, {
|
|
426
|
+
method: "POST",
|
|
427
|
+
headers: {
|
|
428
|
+
"Content-Type": "application/json",
|
|
429
|
+
},
|
|
430
|
+
body: JSON.stringify({
|
|
431
|
+
query: trendingQuery,
|
|
432
|
+
variables: { page: 1, perPage: count },
|
|
433
|
+
}),
|
|
434
|
+
});
|
|
435
|
+
const { data, errors } = yield request.json();
|
|
436
|
+
if (request.status !== 200 || errors) {
|
|
437
|
+
return console.log(`\nSomething went wrong. ${((_a = errors === null || errors === void 0 ? void 0 : errors[0]) === null || _a === void 0 ? void 0 : _a.message) || "Unknown error"}`);
|
|
438
|
+
}
|
|
439
|
+
const media = (_b = data === null || data === void 0 ? void 0 : data.Page) === null || _b === void 0 ? void 0 : _b.media;
|
|
440
|
+
if (!media || media.length === 0) {
|
|
441
|
+
return console.log(`\nNo trending available at the moment.`);
|
|
442
|
+
}
|
|
443
|
+
const { selectedAnime } = yield inquirer.prompt([
|
|
444
|
+
{
|
|
445
|
+
type: "list",
|
|
446
|
+
name: "selectedAnime",
|
|
447
|
+
message: "Select anime to add to the list:",
|
|
448
|
+
choices: media.map((anime, idx) => ({
|
|
449
|
+
name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
|
|
450
|
+
value: anime === null || anime === void 0 ? void 0 : anime.id,
|
|
451
|
+
})),
|
|
452
|
+
pageSize: 10,
|
|
453
|
+
},
|
|
454
|
+
]);
|
|
455
|
+
const { selectedListType } = yield inquirer.prompt([
|
|
456
|
+
{
|
|
457
|
+
type: "list",
|
|
458
|
+
name: "selectedListType",
|
|
459
|
+
message: "Select the list where you want to save this anime:",
|
|
460
|
+
choices: [
|
|
461
|
+
{ name: "Planning", value: "PLANNING" },
|
|
462
|
+
{ name: "Watching", value: "CURRENT" },
|
|
463
|
+
{ name: "Completed", value: "COMPLETED" },
|
|
464
|
+
{ name: "Paused", value: "PAUSED" },
|
|
465
|
+
{ name: "Dropped", value: "DROPPED" },
|
|
466
|
+
],
|
|
467
|
+
},
|
|
468
|
+
]);
|
|
469
|
+
if (!(yield Auth.isLoggedIn())) {
|
|
470
|
+
return console.error(`\nPlease log in first to use this feature.`);
|
|
471
|
+
}
|
|
472
|
+
const variables = { mediaId: selectedAnime, status: selectedListType };
|
|
473
|
+
const saveResponse = yield fetcher(addAnimeToListMutation, variables);
|
|
474
|
+
const saved = (_c = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
|
|
475
|
+
if (saved) {
|
|
476
|
+
console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
console.error(`\nFailed to save the anime. ${((_e = (_d = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.errors) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.message) || "Unknown error"}`);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
catch (error) {
|
|
483
|
+
console.error(`\nSomething went wrong. ${error.message}`);
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
static getPopularAnime(count) {
|
|
488
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
489
|
+
var _a, _b, _c, _d, _e;
|
|
490
|
+
try {
|
|
491
|
+
const request = yield fetch(aniListEndpoint, {
|
|
492
|
+
method: "POST",
|
|
493
|
+
headers: {
|
|
494
|
+
"Content-Type": "application/json",
|
|
495
|
+
},
|
|
496
|
+
body: JSON.stringify({
|
|
497
|
+
query: popularQuery,
|
|
498
|
+
variables: { page: 1, perPage: count },
|
|
499
|
+
}),
|
|
500
|
+
});
|
|
501
|
+
const { data, errors } = yield request.json();
|
|
502
|
+
if (request.status !== 200 || errors) {
|
|
503
|
+
return console.log(`\nSomething went wrong. ${((_a = errors === null || errors === void 0 ? void 0 : errors[0]) === null || _a === void 0 ? void 0 : _a.message) || "Unknown error"}`);
|
|
504
|
+
}
|
|
505
|
+
const media = (_b = data === null || data === void 0 ? void 0 : data.Page) === null || _b === void 0 ? void 0 : _b.media;
|
|
506
|
+
if (!media || media.length === 0) {
|
|
507
|
+
return console.log(`\nNo popular anime available at the moment.`);
|
|
508
|
+
}
|
|
509
|
+
const { selectedAnime } = yield inquirer.prompt([
|
|
510
|
+
{
|
|
511
|
+
type: "list",
|
|
512
|
+
name: "selectedAnime",
|
|
513
|
+
message: "Select anime to add to the list:",
|
|
514
|
+
choices: media.map((anime, idx) => ({
|
|
515
|
+
name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
|
|
516
|
+
value: anime === null || anime === void 0 ? void 0 : anime.id,
|
|
517
|
+
})),
|
|
518
|
+
pageSize: 10,
|
|
519
|
+
},
|
|
520
|
+
]);
|
|
521
|
+
const { selectedListType } = yield inquirer.prompt([
|
|
522
|
+
{
|
|
523
|
+
type: "list",
|
|
524
|
+
name: "selectedListType",
|
|
525
|
+
message: "Select the list where you want to save this anime:",
|
|
526
|
+
choices: [
|
|
527
|
+
{ name: "Planning", value: "PLANNING" },
|
|
528
|
+
{ name: "Watching", value: "CURRENT" },
|
|
529
|
+
{ name: "Completed", value: "COMPLETED" },
|
|
530
|
+
{ name: "Paused", value: "PAUSED" },
|
|
531
|
+
{ name: "Dropped", value: "DROPPED" },
|
|
532
|
+
],
|
|
533
|
+
},
|
|
534
|
+
]);
|
|
535
|
+
if (!(yield Auth.isLoggedIn())) {
|
|
536
|
+
return console.error(`\nPlease log in first to use this feature.`);
|
|
537
|
+
}
|
|
538
|
+
const variables = { mediaId: selectedAnime, status: selectedListType };
|
|
539
|
+
const saveResponse = yield fetcher(addAnimeToListMutation, variables);
|
|
540
|
+
const saved = (_c = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
|
|
541
|
+
if (saved) {
|
|
542
|
+
console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
|
|
543
|
+
}
|
|
544
|
+
else {
|
|
545
|
+
console.error(`\nFailed to save the anime. ${((_e = (_d = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.errors) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.message) || "Unknown error"}`);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
catch (error) {
|
|
549
|
+
console.error(`\nSomething went wrong. ${error.message}`);
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
static getUpcomingAnime(count) {
|
|
554
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
555
|
+
var _a, _b, _c, _d, _e, _f;
|
|
556
|
+
try {
|
|
557
|
+
const { nextSeason, nextYear } = getNextSeasonAndYear();
|
|
558
|
+
const request = yield fetcher(upcomingAnimesQuery, {
|
|
559
|
+
nextSeason,
|
|
560
|
+
nextYear,
|
|
561
|
+
perPage: count,
|
|
562
|
+
});
|
|
563
|
+
if (!request || !request.data) {
|
|
564
|
+
return console.error(`\nSomething went wrong. ${((_b = (_a = request === null || request === void 0 ? void 0 : request.errors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.message) || "Unknown error"}`);
|
|
565
|
+
}
|
|
566
|
+
const upcoming = (_c = request.data.Page.media) !== null && _c !== void 0 ? _c : [];
|
|
567
|
+
if (upcoming.length === 0) {
|
|
568
|
+
return console.log(`\nNo upcoming anime available.`);
|
|
569
|
+
}
|
|
570
|
+
const { selectedAnime } = yield inquirer.prompt([
|
|
571
|
+
{
|
|
572
|
+
type: "list",
|
|
573
|
+
name: "selectedAnime",
|
|
574
|
+
message: "Select anime to add to the list:",
|
|
575
|
+
choices: upcoming.map((anime, idx) => ({
|
|
576
|
+
name: `[${idx + 1}] ${getTitle(anime === null || anime === void 0 ? void 0 : anime.title)}`,
|
|
577
|
+
value: anime === null || anime === void 0 ? void 0 : anime.id,
|
|
578
|
+
})),
|
|
579
|
+
pageSize: 10,
|
|
580
|
+
},
|
|
581
|
+
]);
|
|
582
|
+
const { selectedListType } = yield inquirer.prompt([
|
|
583
|
+
{
|
|
584
|
+
type: "list",
|
|
585
|
+
name: "selectedListType",
|
|
586
|
+
message: "Select the list where you want to save this anime:",
|
|
587
|
+
choices: [
|
|
588
|
+
{ name: "Planning", value: "PLANNING" },
|
|
589
|
+
{ name: "Watching", value: "CURRENT" },
|
|
590
|
+
{ name: "Completed", value: "COMPLETED" },
|
|
591
|
+
{ name: "Paused", value: "PAUSED" },
|
|
592
|
+
{ name: "Dropped", value: "DROPPED" },
|
|
593
|
+
],
|
|
594
|
+
},
|
|
595
|
+
]);
|
|
596
|
+
if (!(yield Auth.isLoggedIn())) {
|
|
597
|
+
return console.error(`\nPlease log in first to use this feature.`);
|
|
598
|
+
}
|
|
599
|
+
const variables = { mediaId: selectedAnime, status: selectedListType };
|
|
600
|
+
const saveResponse = yield fetcher(addAnimeToListMutation, variables);
|
|
601
|
+
const saved = (_d = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _d === void 0 ? void 0 : _d.SaveMediaListEntry;
|
|
602
|
+
if (saved) {
|
|
603
|
+
console.log(`\nEntry ${saved.id}. Saved as ${saved.status}.`);
|
|
604
|
+
}
|
|
605
|
+
else {
|
|
606
|
+
console.error(`\nFailed to save the anime. ${((_f = (_e = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.errors) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.message) || "Unknown error"}`);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
catch (error) {
|
|
610
|
+
console.error(`\nError getting upcoming animes. ${error.message}`);
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
static getUserByUsername(username) {
|
|
615
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
616
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
617
|
+
try {
|
|
618
|
+
const headers = {
|
|
619
|
+
"Content-Type": "application/json",
|
|
620
|
+
};
|
|
621
|
+
if (yield Auth.isLoggedIn()) {
|
|
622
|
+
headers["Authorization"] = `Bearer ${yield Auth.RetriveAccessToken()}`;
|
|
623
|
+
}
|
|
624
|
+
const request = yield fetch(aniListEndpoint, {
|
|
625
|
+
method: "POST",
|
|
626
|
+
headers,
|
|
627
|
+
body: JSON.stringify({ query: userQuery, variables: { username } }),
|
|
628
|
+
});
|
|
629
|
+
const response = yield request.json();
|
|
630
|
+
if (request.status !== 200 || !((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.User)) {
|
|
631
|
+
return console.error(`\n${request.status} ${((_c = (_b = response === null || response === void 0 ? void 0 : response.errors) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.message) || "Unknown error"}`);
|
|
632
|
+
}
|
|
633
|
+
const user = response.data.User;
|
|
634
|
+
const userActivityResponse = yield fetcher(userActivityQuery, {
|
|
635
|
+
id: user.id,
|
|
636
|
+
page: 1,
|
|
637
|
+
perPage: 10,
|
|
638
|
+
});
|
|
639
|
+
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 : [];
|
|
640
|
+
console.log(`\nID:\t\t${user.id}`);
|
|
641
|
+
console.log(`Name:\t\t${user.name}`);
|
|
642
|
+
console.log(`Site URL:\t${user.siteUrl}`);
|
|
643
|
+
console.log(`Donator Tier:\t${user.donatorTier}`);
|
|
644
|
+
console.log(`Donator Badge:\t${user.donatorBadge}`);
|
|
645
|
+
console.log(`Account Created:\t${user.createdAt ? new Date(user.createdAt * 1000).toUTCString() : "N/A"}`);
|
|
646
|
+
console.log(`Account Updated:\t${user.updatedAt ? new Date(user.updatedAt * 1000).toUTCString() : "N/A"}`);
|
|
647
|
+
console.log(`Blocked:\t${user.isBlocked}`);
|
|
648
|
+
console.log(`Follower:\t${user.isFollower}`);
|
|
649
|
+
console.log(`Following:\t${user.isFollowing}`);
|
|
650
|
+
console.log(`Profile Color:\t${(_g = user.options) === null || _g === void 0 ? void 0 : _g.profileColor}`);
|
|
651
|
+
console.log(`Timezone:\t${(_h = user.options) === null || _h === void 0 ? void 0 : _h.timezone}`);
|
|
652
|
+
console.log(`\nStatistics (Anime)\nCount: ${((_k = (_j = user.statistics) === null || _j === void 0 ? void 0 : _j.anime) === null || _k === void 0 ? void 0 : _k.count) || 0} Episodes Watched: ${((_m = (_l = user.statistics) === null || _l === void 0 ? void 0 : _l.anime) === null || _m === void 0 ? void 0 : _m.episodesWatched) || 0} Minutes Watched: ${((_p = (_o = user.statistics) === null || _o === void 0 ? void 0 : _o.anime) === null || _p === void 0 ? void 0 : _p.minutesWatched) || 0}`);
|
|
653
|
+
console.log(`Statistics (Manga)\nCount: ${((_r = (_q = user.statistics) === null || _q === void 0 ? void 0 : _q.manga) === null || _r === void 0 ? void 0 : _r.count) || 0} Chapters Read: ${((_t = (_s = user.statistics) === null || _s === void 0 ? void 0 : _s.manga) === null || _t === void 0 ? void 0 : _t.chaptersRead) || 0} Volumes Read: ${((_v = (_u = user.statistics) === null || _u === void 0 ? void 0 : _u.manga) === null || _v === void 0 ? void 0 : _v.volumesRead) || 0}`);
|
|
654
|
+
if (activities.length > 0) {
|
|
655
|
+
console.log(`\nRecent Activities:`);
|
|
656
|
+
activities.forEach(({ status, progress, media }) => {
|
|
657
|
+
console.log(`${status} ${progress ? `${progress} of ` : ""}${getTitle(media === null || media === void 0 ? void 0 : media.title)}`);
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
else {
|
|
661
|
+
console.log("\nNo recent activities.");
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
catch (error) {
|
|
665
|
+
console.error(`\nSomething went wrong. ${error.message}`);
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
static getAnimeDetailsByID(anilistID) {
|
|
670
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
671
|
+
var _a;
|
|
672
|
+
const query = animeDetailsQuery;
|
|
673
|
+
const variables = { id: anilistID };
|
|
674
|
+
const details = yield fetcher(query, variables);
|
|
675
|
+
if ((_a = details === null || details === void 0 ? void 0 : details.data) === null || _a === void 0 ? void 0 : _a.Media) {
|
|
676
|
+
const { id, title, description, duration, startDate, endDate, countryOfOrigin, isAdult, status, season, format, genres, siteUrl, } = details.data.Media;
|
|
677
|
+
console.log(`\nID: ${id}`);
|
|
678
|
+
console.log(`Title: ${(title === null || title === void 0 ? void 0 : title.userPreferred) || getTitle(title)}`);
|
|
679
|
+
console.log(`Description: ${removeHtmlAndMarkdown(description)}`);
|
|
680
|
+
console.log(`Episode Duration: ${duration || "Unknown"} min`);
|
|
681
|
+
console.log(`Origin: ${countryOfOrigin || "N/A"}`);
|
|
682
|
+
console.log(`Status: ${status || "N/A"}`);
|
|
683
|
+
console.log(`Format: ${format || "N/A"}`);
|
|
684
|
+
console.log(`Genres: ${genres.length ? genres.join(", ") : "N/A"}`);
|
|
685
|
+
console.log(`Season: ${season || "N/A"}`);
|
|
686
|
+
console.log(`Url: ${siteUrl || "N/A"}`);
|
|
687
|
+
console.log(`isAdult: ${isAdult ? "Yes" : "No"}`);
|
|
688
|
+
console.log(`Released: ${formatDateObject(startDate) || "Unknown"}`);
|
|
689
|
+
console.log(`Finished: ${formatDateObject(endDate) || "Ongoing"}`);
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
}
|
|
693
|
+
static searchAnime(search, count) {
|
|
694
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
695
|
+
var _a, _b, _c;
|
|
696
|
+
const query = animeSearchQuery;
|
|
697
|
+
const variables = { search, page: 1, perPage: count };
|
|
698
|
+
const searchResults = yield fetcher(query, variables);
|
|
699
|
+
if (searchResults) {
|
|
700
|
+
const results = (_b = (_a = searchResults === null || searchResults === void 0 ? void 0 : searchResults.data) === null || _a === void 0 ? void 0 : _a.Page) === null || _b === void 0 ? void 0 : _b.media;
|
|
701
|
+
if (results.length > 0) {
|
|
111
702
|
const { selectedAnime } = yield inquirer.prompt([
|
|
112
703
|
{
|
|
113
704
|
type: "list",
|
|
114
705
|
name: "selectedAnime",
|
|
115
|
-
message: "Select anime to add to
|
|
116
|
-
choices:
|
|
117
|
-
name: `[${idx + 1}] ${getTitle(
|
|
118
|
-
value:
|
|
706
|
+
message: "Select anime to add to your list:",
|
|
707
|
+
choices: results.map((res, idx) => ({
|
|
708
|
+
name: `[${idx + 1}] ${getTitle(res === null || res === void 0 ? void 0 : res.title)}`,
|
|
709
|
+
value: res === null || res === void 0 ? void 0 : res.id,
|
|
119
710
|
})),
|
|
120
711
|
pageSize: 10,
|
|
121
712
|
},
|
|
122
713
|
]);
|
|
123
|
-
// Where to save
|
|
124
714
|
const { selectedListType } = yield inquirer.prompt([
|
|
125
715
|
{
|
|
126
716
|
type: "list",
|
|
@@ -135,14 +725,14 @@ function getPopular(count) {
|
|
|
135
725
|
],
|
|
136
726
|
},
|
|
137
727
|
]);
|
|
138
|
-
//
|
|
139
|
-
if (yield isLoggedIn()) {
|
|
140
|
-
const
|
|
141
|
-
const
|
|
728
|
+
// Save selected anime to chosen list type
|
|
729
|
+
if (yield Auth.isLoggedIn()) {
|
|
730
|
+
const saveQuery = addAnimeToListMutation;
|
|
731
|
+
const saveVariables = {
|
|
142
732
|
mediaId: selectedAnime,
|
|
143
733
|
status: selectedListType,
|
|
144
734
|
};
|
|
145
|
-
const response = yield fetcher(
|
|
735
|
+
const response = yield fetcher(saveQuery, saveVariables);
|
|
146
736
|
if (response) {
|
|
147
737
|
const saved = (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
|
|
148
738
|
console.log(`\nEntry ${saved === null || saved === void 0 ? void 0 : saved.id}. Saved as ${saved === null || saved === void 0 ? void 0 : saved.status}.`);
|
|
@@ -153,493 +743,281 @@ function getPopular(count) {
|
|
|
153
743
|
}
|
|
154
744
|
}
|
|
155
745
|
else {
|
|
156
|
-
console.log(`\nNo
|
|
746
|
+
console.log(`\nNo search results found.`);
|
|
157
747
|
}
|
|
158
748
|
}
|
|
159
749
|
else {
|
|
160
|
-
console.
|
|
750
|
+
console.error(`\nSomething went wrong.`);
|
|
161
751
|
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
return ({
|
|
209
|
-
name: `[${idx + 1}] ${getTitle((_a = upx === null || upx === void 0 ? void 0 : upx.media) === null || _a === void 0 ? void 0 : _a.title)}`,
|
|
210
|
-
value: (_b = upx === null || upx === void 0 ? void 0 : upx.media) === null || _b === void 0 ? void 0 : _b.id,
|
|
211
|
-
});
|
|
212
|
-
}),
|
|
213
|
-
pageSize: 10,
|
|
214
|
-
},
|
|
215
|
-
]);
|
|
216
|
-
// Where to save
|
|
217
|
-
const { selectedListType } = yield inquirer.prompt([
|
|
218
|
-
{
|
|
219
|
-
type: "list",
|
|
220
|
-
name: "selectedListType",
|
|
221
|
-
message: "Select the list where you want to save this anime:",
|
|
222
|
-
choices: [
|
|
223
|
-
{ name: "Planning", value: "PLANNING" },
|
|
224
|
-
{ name: "Watching", value: "CURRENT" },
|
|
225
|
-
{ name: "Completed", value: "COMPLETED" },
|
|
226
|
-
{ name: "Paused", value: "PAUSED" },
|
|
227
|
-
{ name: "Dropped", value: "DROPPED" },
|
|
228
|
-
],
|
|
229
|
-
},
|
|
230
|
-
]);
|
|
231
|
-
// Lets save to the list now
|
|
232
|
-
if (yield isLoggedIn()) {
|
|
233
|
-
const query = addAnimeToListMutation;
|
|
234
|
-
const variables = {
|
|
235
|
-
mediaId: selectedAnime,
|
|
236
|
-
status: selectedListType,
|
|
237
|
-
};
|
|
238
|
-
const response = yield fetcher(query, variables);
|
|
239
|
-
if (response) {
|
|
240
|
-
const saved = (_d = response === null || response === void 0 ? void 0 : response.data) === null || _d === void 0 ? void 0 : _d.SaveMediaListEntry;
|
|
241
|
-
console.log(`\nEntry ${saved === null || saved === void 0 ? void 0 : saved.id}. Saved as ${saved === null || saved === void 0 ? void 0 : saved.status}.`);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
console.error(`\nPlease log in first to use this feature.`);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
console.log(`\nNot available at this moment.`);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
else {
|
|
253
|
-
console.log("\nNo entries found.");
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
else {
|
|
257
|
-
console.log(`\nYou seems to have no anime(s) in your lists.`);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
else {
|
|
261
|
-
console.log(`\nSomething went wrong. ${(_e = response === null || response === void 0 ? void 0 : response.errors[0]) === null || _e === void 0 ? void 0 : _e.message}`);
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
static searchManga(search, count) {
|
|
755
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
756
|
+
var _a, _b, _c;
|
|
757
|
+
const query = mangaSearchQuery;
|
|
758
|
+
const variables = { search, page: 1, perPage: count };
|
|
759
|
+
const mangaSearchResult = yield fetcher(query, variables);
|
|
760
|
+
if (mangaSearchResult) {
|
|
761
|
+
const results = (_b = (_a = mangaSearchResult === null || mangaSearchResult === void 0 ? void 0 : mangaSearchResult.data) === null || _a === void 0 ? void 0 : _a.Page) === null || _b === void 0 ? void 0 : _b.media;
|
|
762
|
+
// List of manga search results
|
|
763
|
+
const { selectedMangaId } = yield inquirer.prompt([
|
|
764
|
+
{
|
|
765
|
+
type: "list",
|
|
766
|
+
name: "selectedMangaId",
|
|
767
|
+
message: "Select manga to add to your list:",
|
|
768
|
+
choices: results.map((res, idx) => ({
|
|
769
|
+
name: `[${idx + 1}] ${getTitle(res === null || res === void 0 ? void 0 : res.title)}`,
|
|
770
|
+
value: res === null || res === void 0 ? void 0 : res.id,
|
|
771
|
+
})),
|
|
772
|
+
pageSize: 10,
|
|
773
|
+
},
|
|
774
|
+
]);
|
|
775
|
+
// Options to save to the list
|
|
776
|
+
const { selectedListType } = yield inquirer.prompt([
|
|
777
|
+
{
|
|
778
|
+
type: "list",
|
|
779
|
+
name: "selectedListType",
|
|
780
|
+
message: "Select the list where you want to save this manga:",
|
|
781
|
+
choices: [
|
|
782
|
+
{ name: "Planning", value: "PLANNING" },
|
|
783
|
+
{ name: "Reading", value: "CURRENT" },
|
|
784
|
+
{ name: "Completed", value: "COMPLETED" },
|
|
785
|
+
{ name: "Paused", value: "PAUSED" },
|
|
786
|
+
{ name: "Dropped", value: "DROPPED" },
|
|
787
|
+
],
|
|
788
|
+
},
|
|
789
|
+
]);
|
|
790
|
+
// If logged in save to the list
|
|
791
|
+
if (yield Auth.isLoggedIn()) {
|
|
792
|
+
const mutation = addMangaToListMutation;
|
|
793
|
+
const variables = { mediaId: selectedMangaId, status: selectedListType };
|
|
794
|
+
const response = yield fetcher(mutation, variables);
|
|
795
|
+
if (response) {
|
|
796
|
+
const saved = (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.SaveMediaListEntry;
|
|
797
|
+
console.log(`\nEntry ${saved === null || saved === void 0 ? void 0 : saved.id}. Saved as ${saved === null || saved === void 0 ? void 0 : saved.status}.`);
|
|
262
798
|
}
|
|
263
799
|
}
|
|
264
800
|
else {
|
|
265
|
-
console.
|
|
801
|
+
console.error(`\nPlease log in first to use this feature.`);
|
|
266
802
|
}
|
|
267
803
|
}
|
|
268
804
|
else {
|
|
269
|
-
console.error(`\
|
|
805
|
+
console.error(`\nSomething went wrong.`);
|
|
270
806
|
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
console.log(`\nSomething went wrong. ${error.message}`);
|
|
274
|
-
}
|
|
275
|
-
});
|
|
807
|
+
});
|
|
808
|
+
}
|
|
276
809
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
message: "Select a manga to add to the list:",
|
|
315
|
-
choices: selectedEntries.entries.map((entry, idx) => {
|
|
316
|
-
var _a;
|
|
317
|
-
return ({
|
|
318
|
-
name: `[${idx + 1}] ${getTitle(entry.media.title)}`,
|
|
319
|
-
value: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
|
|
320
|
-
});
|
|
321
|
-
}),
|
|
322
|
-
pageSize: 10,
|
|
323
|
-
},
|
|
324
|
-
]);
|
|
325
|
-
// Prompt user to select list type to save to
|
|
326
|
-
const { selectedListType } = yield inquirer.prompt([
|
|
327
|
-
{
|
|
328
|
-
type: "list",
|
|
329
|
-
name: "selectedListType",
|
|
330
|
-
message: "Select the list where you want to save this manga:",
|
|
331
|
-
choices: [
|
|
332
|
-
{ name: "Planning", value: "PLANNING" },
|
|
333
|
-
{ name: "Reading", value: "CURRENT" },
|
|
334
|
-
{ name: "Completed", value: "COMPLETED" },
|
|
335
|
-
{ name: "Paused", value: "PAUSED" },
|
|
336
|
-
{ name: "Dropped", value: "DROPPED" },
|
|
337
|
-
],
|
|
338
|
-
},
|
|
339
|
-
]);
|
|
340
|
-
// Save the selected manga to the selected list type
|
|
341
|
-
if (yield isLoggedIn()) {
|
|
342
|
-
const query = addMangaToListMutation;
|
|
343
|
-
const variables = {
|
|
344
|
-
mediaId: selectedManga,
|
|
345
|
-
status: selectedListType,
|
|
346
|
-
};
|
|
347
|
-
const saveRequest = yield fetch(aniListEndpoint, {
|
|
348
|
-
method: "POST",
|
|
349
|
-
headers: {
|
|
350
|
-
"Content-Type": "application/json",
|
|
351
|
-
Authorization: `Bearer ${yield retriveAccessToken()}`,
|
|
352
|
-
},
|
|
353
|
-
body: JSON.stringify({ query, variables }),
|
|
810
|
+
class MyAnimeList {
|
|
811
|
+
static importAnime() {
|
|
812
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
813
|
+
var _a, _b, _c, _d, _e;
|
|
814
|
+
try {
|
|
815
|
+
const filename = yield selectFile(".xml");
|
|
816
|
+
const filePath = join(getDownloadFolderPath(), filename);
|
|
817
|
+
const fileContent = yield readFile(filePath, "utf8");
|
|
818
|
+
const parser = new XMLParser();
|
|
819
|
+
if (fileContent) {
|
|
820
|
+
const XMLObject = parser.parse(fileContent);
|
|
821
|
+
const animeList = (_a = XMLObject === null || XMLObject === void 0 ? void 0 : XMLObject.myanimelist) === null || _a === void 0 ? void 0 : _a.anime;
|
|
822
|
+
if ((animeList === null || animeList === void 0 ? void 0 : animeList.length) > 0) {
|
|
823
|
+
let count = 0;
|
|
824
|
+
const statusMap = {
|
|
825
|
+
"On-Hold": AniListMediaStatus.PAUSED,
|
|
826
|
+
"Dropped": AniListMediaStatus.DROPPED,
|
|
827
|
+
"Completed": AniListMediaStatus.COMPLETED,
|
|
828
|
+
"Watching": AniListMediaStatus.CURRENT,
|
|
829
|
+
"Plan to Watch": AniListMediaStatus.PLANNING,
|
|
830
|
+
};
|
|
831
|
+
for (const anime of animeList) {
|
|
832
|
+
const malId = anime.series_animedb_id;
|
|
833
|
+
const progress = anime.my_watched_episodes;
|
|
834
|
+
const status = statusMap[anime.my_status];
|
|
835
|
+
try {
|
|
836
|
+
// Fetch AniList ID using MAL ID
|
|
837
|
+
const anilistResponse = yield fetcher(malIdToAnilistAnimeId, { malId });
|
|
838
|
+
const anilistId = (_c = (_b = anilistResponse === null || anilistResponse === void 0 ? void 0 : anilistResponse.data) === null || _b === void 0 ? void 0 : _b.Media) === null || _c === void 0 ? void 0 : _c.id;
|
|
839
|
+
if (anilistId) {
|
|
840
|
+
// Save anime entry with progress
|
|
841
|
+
const saveResponse = yield fetcher(saveAnimeWithProgressMutation, {
|
|
842
|
+
mediaId: anilistId,
|
|
843
|
+
progress,
|
|
844
|
+
status,
|
|
845
|
+
hiddenFromStatusLists: false,
|
|
846
|
+
private: false,
|
|
354
847
|
});
|
|
355
|
-
const
|
|
356
|
-
if (
|
|
357
|
-
|
|
358
|
-
console.log(
|
|
359
|
-
}
|
|
360
|
-
else {
|
|
361
|
-
console.error(`\nFailed to save the manga. ${((_d = (_c = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.errors) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.message) || "Unknown error"}`);
|
|
848
|
+
const entryId = (_e = (_d = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _d === void 0 ? void 0 : _d.SaveMediaListEntry) === null || _e === void 0 ? void 0 : _e.id;
|
|
849
|
+
if (entryId) {
|
|
850
|
+
count++;
|
|
851
|
+
console.log(`[${count}] ${entryId} ✅`);
|
|
362
852
|
}
|
|
853
|
+
// Rate limit each API call to avoid server overload
|
|
854
|
+
yield new Promise((resolve) => setTimeout(resolve, 1100));
|
|
363
855
|
}
|
|
364
856
|
else {
|
|
365
|
-
console.error(
|
|
857
|
+
console.error(`Could not retrieve AniList ID for MAL ID ${malId}`);
|
|
366
858
|
}
|
|
367
859
|
}
|
|
368
|
-
|
|
369
|
-
console.
|
|
860
|
+
catch (error) {
|
|
861
|
+
console.error(`Error processing MAL ID ${malId}: ${error.message}`);
|
|
370
862
|
}
|
|
371
863
|
}
|
|
372
|
-
|
|
373
|
-
console.log("\nYou don't seem to have any manga in your lists.");
|
|
374
|
-
}
|
|
864
|
+
console.log(`\nTotal Entries Processed: ${count}`);
|
|
375
865
|
}
|
|
376
866
|
else {
|
|
377
|
-
console.
|
|
867
|
+
console.log(`\nNo anime list found in the file.`);
|
|
378
868
|
}
|
|
379
869
|
}
|
|
380
|
-
else {
|
|
381
|
-
console.error(`\nFailed to get the current user ID.`);
|
|
382
|
-
}
|
|
383
870
|
}
|
|
384
|
-
|
|
385
|
-
console.error(`\
|
|
871
|
+
catch (error) {
|
|
872
|
+
console.error(`\nError in MAL import process: ${error.message}`);
|
|
386
873
|
}
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
static importManga() {
|
|
877
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
878
|
+
var _a, _b, _c, _d, _e;
|
|
879
|
+
try {
|
|
880
|
+
const filename = yield selectFile(".xml");
|
|
881
|
+
const filePath = join(getDownloadFolderPath(), filename);
|
|
882
|
+
const fileContent = yield readFile(filePath, "utf8");
|
|
883
|
+
const parser = new XMLParser();
|
|
884
|
+
if (fileContent) {
|
|
885
|
+
const XMLObject = parser.parse(fileContent);
|
|
886
|
+
const mangas = (_a = XMLObject === null || XMLObject === void 0 ? void 0 : XMLObject.myanimelist) === null || _a === void 0 ? void 0 : _a.manga;
|
|
887
|
+
if ((mangas === null || mangas === void 0 ? void 0 : mangas.length) > 0) {
|
|
888
|
+
let count = 0;
|
|
889
|
+
const statusMap = {
|
|
890
|
+
"On-Hold": AniListMediaStatus.PAUSED,
|
|
891
|
+
"Dropped": AniListMediaStatus.DROPPED,
|
|
892
|
+
"Completed": AniListMediaStatus.COMPLETED,
|
|
893
|
+
"Reading": AniListMediaStatus.CURRENT,
|
|
894
|
+
"Plan to Read": AniListMediaStatus.PLANNING,
|
|
895
|
+
};
|
|
896
|
+
for (const manga of mangas) {
|
|
897
|
+
const malId = manga.manga_mangadb_id;
|
|
898
|
+
const progress = manga.my_read_chapters;
|
|
899
|
+
const status = statusMap[manga.my_status];
|
|
900
|
+
try {
|
|
901
|
+
// Fetch AniList ID using MAL ID
|
|
902
|
+
const anilistResponse = yield fetcher(malIdToAnilistMangaId, { malId });
|
|
903
|
+
const anilistId = (_c = (_b = anilistResponse === null || anilistResponse === void 0 ? void 0 : anilistResponse.data) === null || _b === void 0 ? void 0 : _b.Media) === null || _c === void 0 ? void 0 : _c.id;
|
|
904
|
+
if (anilistId) {
|
|
905
|
+
// Save manga entry with progress
|
|
906
|
+
const saveResponse = yield fetcher(saveMangaWithProgressMutation, {
|
|
907
|
+
mediaId: anilistId,
|
|
908
|
+
progress,
|
|
909
|
+
status,
|
|
910
|
+
hiddenFromStatusLists: false,
|
|
911
|
+
private: false,
|
|
912
|
+
});
|
|
913
|
+
const entryId = (_e = (_d = saveResponse === null || saveResponse === void 0 ? void 0 : saveResponse.data) === null || _d === void 0 ? void 0 : _d.SaveMediaListEntry) === null || _e === void 0 ? void 0 : _e.id;
|
|
914
|
+
if (entryId) {
|
|
915
|
+
count++;
|
|
916
|
+
console.log(`[${count}] ${entryId} ✅`);
|
|
917
|
+
}
|
|
918
|
+
else {
|
|
919
|
+
console.error(`Failed to save entry for ${malId}`);
|
|
920
|
+
}
|
|
430
921
|
}
|
|
431
922
|
else {
|
|
432
|
-
console.
|
|
433
|
-
console.log(entry);
|
|
923
|
+
console.error(`Could not retrieve AniList ID for MAL ID ${malId}`);
|
|
434
924
|
}
|
|
435
925
|
}
|
|
926
|
+
catch (error) {
|
|
927
|
+
console.error(`Error processing MAL ID ${malId}: ${error.message}`);
|
|
928
|
+
}
|
|
436
929
|
}
|
|
437
|
-
|
|
438
|
-
console.log("No entries found.");
|
|
439
|
-
}
|
|
930
|
+
console.log(`\nTotal Entries Processed: ${count}`);
|
|
440
931
|
}
|
|
441
932
|
else {
|
|
442
|
-
console.log(`\nNo
|
|
933
|
+
console.log(`\nNo manga list seems to be found.`);
|
|
443
934
|
}
|
|
444
935
|
}
|
|
445
|
-
else {
|
|
446
|
-
console.log(`\nSomething went wrong. ${(_d = response === null || response === void 0 ? void 0 : response.errors[0]) === null || _d === void 0 ? void 0 : _d.message}`);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
else {
|
|
450
|
-
console.log(`\nFailed getting current user Id.`);
|
|
451
936
|
}
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
console.error(`\nPlease log in first to delete your lists.`);
|
|
455
|
-
}
|
|
456
|
-
});
|
|
457
|
-
}
|
|
458
|
-
function deleteAnimeByAnimeId(id, title) {
|
|
459
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
460
|
-
var _a, _b, _c;
|
|
461
|
-
try {
|
|
462
|
-
const request = yield fetch(aniListEndpoint, {
|
|
463
|
-
method: "POST",
|
|
464
|
-
headers: {
|
|
465
|
-
"content-type": "application/json",
|
|
466
|
-
Authorization: `Bearer ${yield retriveAccessToken()}`,
|
|
467
|
-
},
|
|
468
|
-
body: JSON.stringify({
|
|
469
|
-
query: deleteMediaEntryMutation,
|
|
470
|
-
variables: { id },
|
|
471
|
-
}),
|
|
472
|
-
});
|
|
473
|
-
const response = yield request.json();
|
|
474
|
-
if (request.status === 200) {
|
|
475
|
-
const deleted = (_b = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.DeleteMediaListEntry) === null || _b === void 0 ? void 0 : _b.deleted;
|
|
476
|
-
console.log(`del ${title ? getTitle(title) : ""} ${deleted ? "✅" : "❌"}`);
|
|
477
|
-
}
|
|
478
|
-
else {
|
|
479
|
-
console.log(`\nError deleting anime. ${(_c = response === null || response === void 0 ? void 0 : response.errors[0]) === null || _c === void 0 ? void 0 : _c.message}`);
|
|
480
|
-
console.log(response);
|
|
937
|
+
catch (error) {
|
|
938
|
+
console.error(`\nError from MAL import: ${error.message}`);
|
|
481
939
|
}
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
name: "selectedList",
|
|
513
|
-
message: "Select a manga list:",
|
|
514
|
-
choices: lists.map((list) => list.name),
|
|
515
|
-
pageSize: 10,
|
|
516
|
-
},
|
|
517
|
-
]);
|
|
518
|
-
const selectedEntries = lists.find((list) => list.name === selectedList);
|
|
519
|
-
if (selectedEntries) {
|
|
520
|
-
console.log(`\nDeleting entries of '${selectedEntries.name}':`);
|
|
521
|
-
for (const [_, entry] of selectedEntries.entries.entries()) {
|
|
522
|
-
if (entry === null || entry === void 0 ? void 0 : entry.id) {
|
|
523
|
-
yield deleteMangaByMangaId(entry === null || entry === void 0 ? void 0 : entry.id, (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title);
|
|
524
|
-
yield new Promise((resolve) => setTimeout(resolve, 2000));
|
|
525
|
-
}
|
|
526
|
-
else {
|
|
527
|
-
console.log(`No id in entry.`);
|
|
528
|
-
console.log(entry);
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
else {
|
|
533
|
-
console.error("\nNo entries found.");
|
|
534
|
-
}
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
static exportAnime() {
|
|
943
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
944
|
+
var _a, _b, _c, _d;
|
|
945
|
+
try {
|
|
946
|
+
if (yield Auth.isLoggedIn()) {
|
|
947
|
+
const animeList = yield fetcher(currentUserAnimeList, {
|
|
948
|
+
id: yield Auth.MyUserId(),
|
|
949
|
+
});
|
|
950
|
+
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) {
|
|
951
|
+
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;
|
|
952
|
+
const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
|
|
953
|
+
var _a, _b, _c, _d, _e;
|
|
954
|
+
return ({
|
|
955
|
+
id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
|
|
956
|
+
malId: (_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.idMal,
|
|
957
|
+
title: (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title,
|
|
958
|
+
episodes: (_d = entry === null || entry === void 0 ? void 0 : entry.media) === null || _d === void 0 ? void 0 : _d.episodes,
|
|
959
|
+
siteUrl: (_e = entry === null || entry === void 0 ? void 0 : entry.media) === null || _e === void 0 ? void 0 : _e.siteUrl,
|
|
960
|
+
progress: entry.progress,
|
|
961
|
+
status: entry === null || entry === void 0 ? void 0 : entry.status,
|
|
962
|
+
hiddenFromStatusLists: false,
|
|
963
|
+
});
|
|
964
|
+
}));
|
|
965
|
+
const xmlContent = createAnimeListXML(mediaWithProgress);
|
|
966
|
+
const path = join(getDownloadFolderPath(), `${yield Auth.MyUserName()}@irfanshadikrishad-anilist-myanimelist(anime)-${getFormattedDate()}.xml`);
|
|
967
|
+
yield writeFile(path, yield xmlContent, "utf8");
|
|
968
|
+
console.log(`Generated XML for MyAnimeList.`);
|
|
969
|
+
open(getDownloadFolderPath());
|
|
535
970
|
}
|
|
536
971
|
else {
|
|
537
|
-
console.
|
|
972
|
+
console.log(`\nHey, ${yield Auth.MyUserName()}. Your anime list seems to be empty.`);
|
|
538
973
|
}
|
|
539
974
|
}
|
|
540
|
-
else {
|
|
541
|
-
console.error(`\nSomething went wrong. ${(_d = response === null || response === void 0 ? void 0 : response.errors[0]) === null || _d === void 0 ? void 0 : _d.message}`);
|
|
542
|
-
}
|
|
543
975
|
}
|
|
544
|
-
|
|
545
|
-
console.error(`\
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
else {
|
|
549
|
-
console.error(`\nPlease log in first to delete your lists.`);
|
|
550
|
-
}
|
|
551
|
-
});
|
|
552
|
-
}
|
|
553
|
-
function deleteMangaByMangaId(id, title) {
|
|
554
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
555
|
-
var _a, _b;
|
|
556
|
-
try {
|
|
557
|
-
const request = yield fetch(aniListEndpoint, {
|
|
558
|
-
method: "POST",
|
|
559
|
-
headers: {
|
|
560
|
-
"Content-Type": "application/json",
|
|
561
|
-
Authorization: `Bearer ${yield retriveAccessToken()}`,
|
|
562
|
-
},
|
|
563
|
-
body: JSON.stringify({
|
|
564
|
-
query: deleteMangaEntryMutation,
|
|
565
|
-
variables: { id },
|
|
566
|
-
}),
|
|
567
|
-
});
|
|
568
|
-
const { data, errors } = yield request.json();
|
|
569
|
-
const statusMessage = title ? getTitle(title) : "";
|
|
570
|
-
if (request.ok) {
|
|
571
|
-
const deleted = (_a = data === null || data === void 0 ? void 0 : data.DeleteMediaListEntry) === null || _a === void 0 ? void 0 : _a.deleted;
|
|
572
|
-
console.log(`del ${statusMessage} ${deleted ? "✅" : "❌"}`);
|
|
573
|
-
}
|
|
574
|
-
else {
|
|
575
|
-
console.error(`Error deleting manga. ${(_b = errors === null || errors === void 0 ? void 0 : errors[0]) === null || _b === void 0 ? void 0 : _b.message}`);
|
|
976
|
+
catch (error) {
|
|
977
|
+
console.error(`\nError from MALexport. ${error.message}`);
|
|
576
978
|
}
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
})
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
type: "list",
|
|
611
|
-
name: "selectedListType",
|
|
612
|
-
message: "Select the list where you want to save this anime:",
|
|
613
|
-
choices: [
|
|
614
|
-
{ name: "Planning", value: "PLANNING" },
|
|
615
|
-
{ name: "Watching", value: "CURRENT" },
|
|
616
|
-
{ name: "Completed", value: "COMPLETED" },
|
|
617
|
-
{ name: "Paused", value: "PAUSED" },
|
|
618
|
-
{ name: "Dropped", value: "DROPPED" },
|
|
619
|
-
],
|
|
620
|
-
},
|
|
621
|
-
]);
|
|
622
|
-
// Lets save to the list now
|
|
623
|
-
if (yield isLoggedIn()) {
|
|
624
|
-
const query = addAnimeToListMutation;
|
|
625
|
-
const variables = { mediaId: selectedAnime, status: selectedListType };
|
|
626
|
-
const response = yield fetcher(query, variables);
|
|
627
|
-
if (response) {
|
|
628
|
-
const saved = (_d = response === null || response === void 0 ? void 0 : response.data) === null || _d === void 0 ? void 0 : _d.SaveMediaListEntry;
|
|
629
|
-
console.log(`\nEntry ${saved === null || saved === void 0 ? void 0 : saved.id}. Saved as ${saved === null || saved === void 0 ? void 0 : saved.status}.`);
|
|
630
|
-
}
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
static exportManga() {
|
|
982
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
983
|
+
var _a, _b, _c, _d;
|
|
984
|
+
try {
|
|
985
|
+
if (!(yield Auth.isLoggedIn())) {
|
|
986
|
+
console.log(`\nPlease login to use this feature.`);
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
const mangaList = yield fetcher(currentUserMangaList, {
|
|
990
|
+
id: yield Auth.MyUserId(),
|
|
991
|
+
});
|
|
992
|
+
if (mangaList && ((_b = (_a = mangaList === null || mangaList === void 0 ? void 0 : mangaList.data) === null || _a === void 0 ? void 0 : _a.MediaListCollection) === null || _b === void 0 ? void 0 : _b.lists.length) > 0) {
|
|
993
|
+
const lists = (_d = (_c = mangaList === null || mangaList === void 0 ? void 0 : mangaList.data) === null || _c === void 0 ? void 0 : _c.MediaListCollection) === null || _d === void 0 ? void 0 : _d.lists;
|
|
994
|
+
const mediaWithProgress = lists.flatMap((list) => list.entries.map((entry) => {
|
|
995
|
+
var _a, _b, _c;
|
|
996
|
+
return ({
|
|
997
|
+
id: (_a = entry === null || entry === void 0 ? void 0 : entry.media) === null || _a === void 0 ? void 0 : _a.id,
|
|
998
|
+
malId: (_b = entry === null || entry === void 0 ? void 0 : entry.media) === null || _b === void 0 ? void 0 : _b.idMal,
|
|
999
|
+
title: (_c = entry === null || entry === void 0 ? void 0 : entry.media) === null || _c === void 0 ? void 0 : _c.title,
|
|
1000
|
+
private: entry.private,
|
|
1001
|
+
chapters: entry.media.chapters,
|
|
1002
|
+
progress: entry.progress,
|
|
1003
|
+
status: entry === null || entry === void 0 ? void 0 : entry.status,
|
|
1004
|
+
hiddenFromStatusLists: entry.hiddenFromStatusLists,
|
|
1005
|
+
});
|
|
1006
|
+
}));
|
|
1007
|
+
const XMLContent = createMangaListXML(mediaWithProgress);
|
|
1008
|
+
const path = join(getDownloadFolderPath(), `${yield Auth.MyUserName()}@irfanshadikrishad-anilist-myanimelist(manga)-${getFormattedDate()}.xml`);
|
|
1009
|
+
yield writeFile(path, yield XMLContent, "utf8");
|
|
1010
|
+
console.log(`Generated XML for MyAnimeList.`);
|
|
1011
|
+
open(getDownloadFolderPath());
|
|
631
1012
|
}
|
|
632
1013
|
else {
|
|
633
|
-
console.
|
|
1014
|
+
console.log(`\nHey, ${yield Auth.MyUserName()}. Your anime list seems to be empty.`);
|
|
634
1015
|
}
|
|
635
1016
|
}
|
|
636
|
-
|
|
637
|
-
console.error(`\
|
|
1017
|
+
catch (error) {
|
|
1018
|
+
console.error(`\nError from MALexport. ${error.message}`);
|
|
638
1019
|
}
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
console.error(`\nError getting upcoming animes. ${error.message}`);
|
|
642
|
-
}
|
|
643
|
-
});
|
|
1020
|
+
});
|
|
1021
|
+
}
|
|
644
1022
|
}
|
|
645
|
-
export {
|
|
1023
|
+
export { AniList, MyAnimeList };
|