@irfanshadikrishad/anilist 1.0.0 → 1.0.1-forbidden.2
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 +165 -26
- package/bin/helpers/auth.d.ts +67 -9
- package/bin/helpers/auth.js +943 -141
- package/bin/helpers/fetcher.d.ts +13 -0
- package/bin/helpers/fetcher.js +59 -0
- package/bin/helpers/lists.d.ts +25 -7
- package/bin/helpers/lists.js +1023 -293
- package/bin/helpers/mutations.d.ts +8 -0
- package/bin/helpers/mutations.js +43 -0
- package/bin/helpers/queries.d.ts +28 -9
- package/bin/helpers/queries.js +150 -154
- package/bin/helpers/types.d.ts +452 -0
- package/bin/helpers/types.js +26 -0
- package/bin/helpers/workers.d.ts +35 -1
- package/bin/helpers/workers.js +360 -6
- package/bin/index.js +169 -24
- package/package.json +51 -9
- package/bin/helpers/more.d.ts +0 -2
- package/bin/helpers/more.js +0 -60
- /package/{LICENSE → LICENSE.md} +0 -0
package/bin/helpers/workers.js
CHANGED
|
@@ -1,14 +1,368 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import fs from "fs";
|
|
11
|
+
import { readdir, writeFile } from "fs/promises";
|
|
12
|
+
import inquirer from "inquirer";
|
|
13
|
+
import { parse } from "json2csv";
|
|
14
|
+
import { createRequire } from "module";
|
|
15
|
+
import open from "open";
|
|
16
|
+
import { homedir } from "os";
|
|
17
|
+
import { join } from "path";
|
|
18
|
+
import process from "process";
|
|
19
|
+
import { Auth } from "./auth.js";
|
|
20
|
+
import { fetcher } from "./fetcher.js";
|
|
21
|
+
import { animeSearchQuery } from "./queries.js";
|
|
22
|
+
import { MALAnimeStatus, MALMangaStatus, } from "./types.js";
|
|
1
23
|
const aniListEndpoint = `https://graphql.anilist.co`;
|
|
2
24
|
const redirectUri = "https://anilist.co/api/v2/oauth/pin";
|
|
3
25
|
function getTitle(title) {
|
|
4
|
-
|
|
5
|
-
|
|
26
|
+
return (title === null || title === void 0 ? void 0 : title.english) || (title === null || title === void 0 ? void 0 : title.romaji) || "???";
|
|
27
|
+
}
|
|
28
|
+
function formatDateObject(dateObj) {
|
|
29
|
+
if (!dateObj)
|
|
30
|
+
return "null";
|
|
31
|
+
return ([dateObj.day, dateObj.month, dateObj.year].filter(Boolean).join("/") ||
|
|
32
|
+
"null");
|
|
33
|
+
}
|
|
34
|
+
function getNextSeasonAndYear() {
|
|
35
|
+
const currentMonth = new Date().getMonth() + 1;
|
|
36
|
+
const currentYear = new Date().getFullYear();
|
|
37
|
+
let nextSeason;
|
|
38
|
+
let nextYear;
|
|
39
|
+
// Determine the current season
|
|
40
|
+
if (currentMonth >= 12 || currentMonth <= 2) {
|
|
41
|
+
nextSeason = "SPRING";
|
|
42
|
+
nextYear = currentMonth === 12 ? currentYear + 1 : currentYear;
|
|
43
|
+
}
|
|
44
|
+
else if (currentMonth >= 3 && currentMonth <= 5) {
|
|
45
|
+
nextSeason = "SUMMER";
|
|
46
|
+
nextYear = currentYear;
|
|
47
|
+
}
|
|
48
|
+
else if (currentMonth >= 6 && currentMonth <= 8) {
|
|
49
|
+
nextSeason = "FALL";
|
|
50
|
+
nextYear = currentYear;
|
|
51
|
+
}
|
|
52
|
+
else if (currentMonth >= 9 && currentMonth <= 11) {
|
|
53
|
+
nextSeason = "WINTER";
|
|
54
|
+
nextYear = currentYear + 1;
|
|
55
|
+
}
|
|
56
|
+
return { nextSeason, nextYear };
|
|
57
|
+
}
|
|
58
|
+
function removeHtmlAndMarkdown(input) {
|
|
59
|
+
if (input) {
|
|
60
|
+
input = input.replace(/<\/?[^>]+(>|$)/g, "");
|
|
61
|
+
input = input.replace(/(^|\n)#{1,6}\s+(.+?)(\n|$)/g, "$2 ");
|
|
62
|
+
input = input.replace(/(\*\*|__)(.*?)\1/g, "$2");
|
|
63
|
+
input = input.replace(/(\*|_)(.*?)\1/g, "$2");
|
|
64
|
+
input = input.replace(/`(.+?)`/g, "$1");
|
|
65
|
+
input = input.replace(/\[(.*?)\]\(.*?\)/g, "$1");
|
|
66
|
+
input = input.replace(/!\[(.*?)\]\(.*?\)/g, "$1");
|
|
67
|
+
input = input.replace(/(^|\n)>\s+(.+?)(\n|$)/g, "$2 ");
|
|
68
|
+
input = input.replace(/(^|\n)-\s+(.+?)(\n|$)/g, "$2 ");
|
|
69
|
+
input = input.replace(/(^|\n)\d+\.\s+(.+?)(\n|$)/g, "$2 ");
|
|
70
|
+
input = input.replace(/(^|\n)\s*([-*_]){3,}\s*(\n|$)/g, "$1");
|
|
71
|
+
input = input.replace(/~~(.*?)~~/g, "$1");
|
|
72
|
+
input = input.replace(/\s+/g, " ").trim();
|
|
73
|
+
}
|
|
74
|
+
return input;
|
|
75
|
+
}
|
|
76
|
+
function getDownloadFolderPath() {
|
|
77
|
+
const homeDirectory = homedir();
|
|
78
|
+
// Determine the Downloads folder path based on the platform
|
|
79
|
+
if (process.platform === "win32") {
|
|
80
|
+
return join(homeDirectory, "Downloads");
|
|
6
81
|
}
|
|
7
|
-
else if (
|
|
8
|
-
return
|
|
82
|
+
else if (process.platform === "darwin" || process.platform === "linux") {
|
|
83
|
+
return join(homeDirectory, "Downloads");
|
|
84
|
+
}
|
|
85
|
+
return homeDirectory;
|
|
86
|
+
}
|
|
87
|
+
function getFormattedDate() {
|
|
88
|
+
const date = new Date();
|
|
89
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
90
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
91
|
+
const year = date.getFullYear();
|
|
92
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
93
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
94
|
+
// Format as DD-MM-YYYY-HH-MM
|
|
95
|
+
return `${day}-${month}-${year}-${hours}-${minutes}`;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Export JSON as JSON
|
|
99
|
+
* @param js0n
|
|
100
|
+
* @param dataType (eg: anime/manga)
|
|
101
|
+
*/
|
|
102
|
+
function saveJSONasJSON(js0n, dataType) {
|
|
103
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
104
|
+
try {
|
|
105
|
+
const jsonData = JSON.stringify(js0n, null, 2);
|
|
106
|
+
const path = join(getDownloadFolderPath(), `${yield Auth.MyUserName()}@irfanshadikrishad-anilist-${dataType}-${getFormattedDate()}.json`);
|
|
107
|
+
yield writeFile(path, jsonData, "utf8");
|
|
108
|
+
console.log(`\nSaved as JSON successfully.`);
|
|
109
|
+
open(getDownloadFolderPath());
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
console.error("\nError saving JSON data:", error);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Export JSON as CSV
|
|
118
|
+
* @param js0n
|
|
119
|
+
* @param dataType (eg: anime/manga)
|
|
120
|
+
*/
|
|
121
|
+
function saveJSONasCSV(js0n, dataType) {
|
|
122
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
123
|
+
try {
|
|
124
|
+
const csvData = parse(js0n);
|
|
125
|
+
const path = join(getDownloadFolderPath(), `${yield Auth.MyUserName()}@irfanshadikrishad-anilist-${dataType}-${getFormattedDate()}.csv`);
|
|
126
|
+
yield writeFile(path, csvData, "utf8");
|
|
127
|
+
console.log(`\nSaved as CSV successfully.`);
|
|
128
|
+
open(getDownloadFolderPath());
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
console.error("\nError saving CSV data:", error);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
function listFilesInDownloadFolder() {
|
|
136
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
137
|
+
const downloadFolderPath = getDownloadFolderPath();
|
|
138
|
+
const files = yield readdir(downloadFolderPath);
|
|
139
|
+
return files;
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
function selectFile(fileType) {
|
|
143
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
144
|
+
try {
|
|
145
|
+
const files = yield listFilesInDownloadFolder();
|
|
146
|
+
console.log(getDownloadFolderPath());
|
|
147
|
+
// Filter to include only files, not directories, with the specified extension
|
|
148
|
+
const onlyFiles = files.filter((file) => {
|
|
149
|
+
const filePath = `${getDownloadFolderPath()}/${file}`; // Adjust this to the correct path
|
|
150
|
+
const isFile = fs.lstatSync(filePath).isFile(); // Check if it's a file
|
|
151
|
+
return isFile && file.endsWith(fileType);
|
|
152
|
+
});
|
|
153
|
+
if (onlyFiles.length > 0) {
|
|
154
|
+
const answers = yield inquirer.prompt([
|
|
155
|
+
{
|
|
156
|
+
type: "list",
|
|
157
|
+
name: "fileName",
|
|
158
|
+
message: "Select a file to import:",
|
|
159
|
+
choices: onlyFiles,
|
|
160
|
+
},
|
|
161
|
+
]);
|
|
162
|
+
return answers.fileName;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
throw new Error(`\nNo importable ${fileType} file(s) found in download folder.`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
console.error("\nError selecting file:", error);
|
|
170
|
+
throw error;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
function createAnimeXML(malId, progress, status, episodes, title) {
|
|
175
|
+
return `
|
|
176
|
+
<anime>
|
|
177
|
+
<series_animedb_id>${malId}</series_animedb_id>
|
|
178
|
+
<series_title><![CDATA[${title}]]></series_title>
|
|
179
|
+
<series_type>""</series_type>
|
|
180
|
+
<series_episodes>${episodes}</series_episodes>
|
|
181
|
+
<my_id>0</my_id>
|
|
182
|
+
<my_watched_episodes>${progress}</my_watched_episodes>
|
|
183
|
+
<my_start_date>0000-00-00</my_start_date>
|
|
184
|
+
<my_finish_date>0000-00-00</my_finish_date>
|
|
185
|
+
<my_score>0</my_score>
|
|
186
|
+
<my_storage_value>0.00</my_storage_value>
|
|
187
|
+
<my_status>${status}</my_status>
|
|
188
|
+
<my_comments><![CDATA[]]></my_comments>
|
|
189
|
+
<my_times_watched>0</my_times_watched>
|
|
190
|
+
<my_rewatch_value></my_rewatch_value>
|
|
191
|
+
<my_priority>LOW</my_priority>
|
|
192
|
+
<my_tags><![CDATA[]]></my_tags>
|
|
193
|
+
<my_rewatching>0</my_rewatching>
|
|
194
|
+
<my_rewatching_ep>0</my_rewatching_ep>
|
|
195
|
+
<my_discuss>0</my_discuss>
|
|
196
|
+
<my_sns>default</my_sns>
|
|
197
|
+
<update_on_import>1</update_on_import>
|
|
198
|
+
</anime>`;
|
|
199
|
+
}
|
|
200
|
+
function createMangaXML(malId, progress, status, chapters, title) {
|
|
201
|
+
return `
|
|
202
|
+
<manga>
|
|
203
|
+
<manga_mangadb_id>${malId}</manga_mangadb_id>
|
|
204
|
+
<manga_title><![CDATA[${title ? title : "unknown"}]]></manga_title>
|
|
205
|
+
<manga_volumes>0</manga_volumes>
|
|
206
|
+
<manga_chapters>${chapters ? chapters : 0}</manga_chapters>
|
|
207
|
+
<my_id>0</my_id>
|
|
208
|
+
<my_read_chapters>${progress}</my_read_chapters>
|
|
209
|
+
<my_start_date>0000-00-00</my_start_date>
|
|
210
|
+
<my_finish_date>0000-00-00</my_finish_date>
|
|
211
|
+
<my_score>0</my_score>
|
|
212
|
+
<my_status>${status}</my_status>
|
|
213
|
+
<my_reread_value></my_reread_value>
|
|
214
|
+
<my_priority>LOW</my_priority>
|
|
215
|
+
<my_rereading>0</my_rereading>
|
|
216
|
+
<my_discuss>0</my_discuss>
|
|
217
|
+
<update_on_import>1</update_on_import>
|
|
218
|
+
</manga>`;
|
|
219
|
+
}
|
|
220
|
+
function createAnimeListXML(mediaWithProgress) {
|
|
221
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
222
|
+
const statusMap = {
|
|
223
|
+
PLANNING: MALAnimeStatus.PLAN_TO_WATCH,
|
|
224
|
+
COMPLETED: MALAnimeStatus.COMPLETED,
|
|
225
|
+
CURRENT: MALAnimeStatus.WATCHING,
|
|
226
|
+
PAUSED: MALAnimeStatus.ON_HOLD,
|
|
227
|
+
DROPPED: MALAnimeStatus.DROPPED,
|
|
228
|
+
};
|
|
229
|
+
const xmlEntries = mediaWithProgress.map((anime) => {
|
|
230
|
+
const malId = anime.malId;
|
|
231
|
+
const progress = anime.progress;
|
|
232
|
+
const episodes = anime.episodes;
|
|
233
|
+
const title = getTitle(anime.title);
|
|
234
|
+
const status = statusMap[anime.status];
|
|
235
|
+
return createAnimeXML(malId, progress, status, episodes, title);
|
|
236
|
+
});
|
|
237
|
+
return `<myanimelist>
|
|
238
|
+
<myinfo>
|
|
239
|
+
<user_id/>
|
|
240
|
+
<user_name>${yield Auth.MyUserName()}</user_name>
|
|
241
|
+
<user_export_type>1</user_export_type>
|
|
242
|
+
<user_total_anime>0</user_total_anime>
|
|
243
|
+
<user_total_watching>0</user_total_watching>
|
|
244
|
+
<user_total_completed>0</user_total_completed>
|
|
245
|
+
<user_total_onhold>0</user_total_onhold>
|
|
246
|
+
<user_total_dropped>0</user_total_dropped>
|
|
247
|
+
<user_total_plantowatch>0</user_total_plantowatch>
|
|
248
|
+
</myinfo>
|
|
249
|
+
\n${xmlEntries.join("\n")}\n
|
|
250
|
+
</myanimelist>`;
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
function createMangaListXML(mediaWithProgress) {
|
|
254
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
255
|
+
const statusMap = {
|
|
256
|
+
PLANNING: MALMangaStatus.PLAN_TO_READ,
|
|
257
|
+
COMPLETED: MALMangaStatus.COMPLETED,
|
|
258
|
+
CURRENT: MALMangaStatus.READING,
|
|
259
|
+
PAUSED: MALMangaStatus.ON_HOLD,
|
|
260
|
+
DROPPED: MALMangaStatus.DROPPED,
|
|
261
|
+
};
|
|
262
|
+
const xmlEntries = mediaWithProgress.map((manga) => {
|
|
263
|
+
const malId = manga.malId;
|
|
264
|
+
const progress = manga.progress;
|
|
265
|
+
const chapters = manga.chapters;
|
|
266
|
+
const title = getTitle(manga.title);
|
|
267
|
+
const status = statusMap[manga.status];
|
|
268
|
+
return createMangaXML(malId, progress, status, chapters, title);
|
|
269
|
+
});
|
|
270
|
+
return `<myanimelist>
|
|
271
|
+
<myinfo>
|
|
272
|
+
<user_id/>
|
|
273
|
+
<user_name>${yield Auth.MyUserName()}</user_name>
|
|
274
|
+
<user_export_type>2</user_export_type>
|
|
275
|
+
<user_total_manga>5</user_total_manga>
|
|
276
|
+
<user_total_reading>1</user_total_reading>
|
|
277
|
+
<user_total_completed>1</user_total_completed>
|
|
278
|
+
<user_total_onhold>1</user_total_onhold>
|
|
279
|
+
<user_total_dropped>1</user_total_dropped>
|
|
280
|
+
<user_total_plantoread>1</user_total_plantoread>
|
|
281
|
+
</myinfo>
|
|
282
|
+
\n${xmlEntries.join("\n")}\n
|
|
283
|
+
</myanimelist>`;
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
function getCurrentPackageVersion() {
|
|
287
|
+
const require = createRequire(import.meta.url);
|
|
288
|
+
const packageJson = require("../../package.json");
|
|
289
|
+
const version = packageJson.version;
|
|
290
|
+
return version || null;
|
|
291
|
+
}
|
|
292
|
+
function timestampToTimeAgo(timestamp) {
|
|
293
|
+
const now = Math.floor(Date.now() / 1000);
|
|
294
|
+
const elapsed = now - timestamp;
|
|
295
|
+
if (elapsed < 60) {
|
|
296
|
+
return `${elapsed} second${elapsed === 1 ? "" : "s"} ago`;
|
|
297
|
+
}
|
|
298
|
+
else if (elapsed < 3600) {
|
|
299
|
+
const minutes = Math.floor(elapsed / 60);
|
|
300
|
+
return `${minutes} minute${minutes === 1 ? "" : "s"} ago`;
|
|
301
|
+
}
|
|
302
|
+
else if (elapsed < 86400) {
|
|
303
|
+
const hours = Math.floor(elapsed / 3600);
|
|
304
|
+
return `${hours} hour${hours === 1 ? "" : "s"} ago`;
|
|
305
|
+
}
|
|
306
|
+
else if (elapsed < 2592000) {
|
|
307
|
+
const days = Math.floor(elapsed / 86400);
|
|
308
|
+
return `${days} day${days === 1 ? "" : "s"} ago`;
|
|
309
|
+
}
|
|
310
|
+
else if (elapsed < 31536000) {
|
|
311
|
+
const months = Math.floor(elapsed / 2592000);
|
|
312
|
+
return `${months} month${months === 1 ? "" : "s"} ago`;
|
|
9
313
|
}
|
|
10
314
|
else {
|
|
11
|
-
|
|
315
|
+
const years = Math.floor(elapsed / 31536000);
|
|
316
|
+
return `${years} year${years === 1 ? "" : "s"} ago`;
|
|
12
317
|
}
|
|
13
318
|
}
|
|
14
|
-
|
|
319
|
+
function activityBy(activity) {
|
|
320
|
+
var _a, _b, _c, _d;
|
|
321
|
+
if ((_a = activity === null || activity === void 0 ? void 0 : activity.messenger) === null || _a === void 0 ? void 0 : _a.name) {
|
|
322
|
+
return `[${activity.id}]\t${activity.messenger.name} messaged ${activity.recipient.name}`;
|
|
323
|
+
}
|
|
324
|
+
else if ((_c = (_b = activity === null || activity === void 0 ? void 0 : activity.media) === null || _b === void 0 ? void 0 : _b.title) === null || _c === void 0 ? void 0 : _c.userPreferred) {
|
|
325
|
+
if (activity.progress) {
|
|
326
|
+
return `[${activity.id}]\t${activity.user.name} ${activity.status} ${activity.progress} of ${activity.media.title.userPreferred}`;
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
return `[${activity.id}]\t${activity.user.name} ${activity.status} ${activity.media.title.userPreferred}`;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
else if ((_d = activity === null || activity === void 0 ? void 0 : activity.user) === null || _d === void 0 ? void 0 : _d.name) {
|
|
333
|
+
return `[${activity.id}]\t${activity.user.name}`;
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
return `[${activity === null || activity === void 0 ? void 0 : activity.id}] ???`;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
const anidbToanilistMapper = (romanjiName, year, englishName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
340
|
+
const fetchAnime = (search) => __awaiter(void 0, void 0, void 0, function* () {
|
|
341
|
+
var _a;
|
|
342
|
+
try {
|
|
343
|
+
const response = yield fetcher(animeSearchQuery, {
|
|
344
|
+
search,
|
|
345
|
+
perPage: 50,
|
|
346
|
+
});
|
|
347
|
+
return ((_a = response.data) === null || _a === void 0 ? void 0 : _a.Page.media) || [];
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
console.error("Error fetching AniList data:", error);
|
|
351
|
+
return [];
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
// Search using romanjiName first
|
|
355
|
+
let results = yield fetchAnime(romanjiName);
|
|
356
|
+
// If no results, fallback to englishName
|
|
357
|
+
if (!results.length && englishName) {
|
|
358
|
+
results = yield fetchAnime(englishName);
|
|
359
|
+
}
|
|
360
|
+
// Match using year
|
|
361
|
+
for (const anime of results) {
|
|
362
|
+
if (anime.startDate.year === year) {
|
|
363
|
+
return anime.id;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return null;
|
|
367
|
+
});
|
|
368
|
+
export { activityBy, anidbToanilistMapper, aniListEndpoint, createAnimeListXML, createAnimeXML, createMangaListXML, createMangaXML, formatDateObject, getCurrentPackageVersion, getDownloadFolderPath, getFormattedDate, getNextSeasonAndYear, getTitle, redirectUri, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, selectFile, timestampToTimeAgo, };
|
package/bin/index.js
CHANGED
|
@@ -9,11 +9,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
import { Command } from "commander";
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
12
|
+
import process from "process";
|
|
13
|
+
import { Auth, Social } from "./helpers/auth.js";
|
|
14
|
+
import { AniList } from "./helpers/lists.js";
|
|
15
|
+
import { getCurrentPackageVersion } from "./helpers/workers.js";
|
|
15
16
|
const cli = new Command();
|
|
16
|
-
cli
|
|
17
|
+
cli
|
|
18
|
+
.name("anilist")
|
|
19
|
+
.description("Minimalist unofficial AniList CLI for Anime and Manga Enthusiasts.")
|
|
20
|
+
.version(getCurrentPackageVersion());
|
|
17
21
|
cli
|
|
18
22
|
.command("login")
|
|
19
23
|
.description("Login with AniList")
|
|
@@ -21,17 +25,17 @@ cli
|
|
|
21
25
|
.requiredOption("-s, --secret <string>", null)
|
|
22
26
|
.action((_a) => __awaiter(void 0, [_a], void 0, function* ({ id, secret }) {
|
|
23
27
|
if (id && secret) {
|
|
24
|
-
yield
|
|
28
|
+
yield Auth.Login(id, secret);
|
|
25
29
|
}
|
|
26
30
|
else {
|
|
27
|
-
console.log("
|
|
31
|
+
console.log("\nMust provide both ClientId and ClientSecret!");
|
|
28
32
|
}
|
|
29
33
|
}));
|
|
30
34
|
cli
|
|
31
|
-
.command("
|
|
35
|
+
.command("whoami")
|
|
32
36
|
.description("Get details of the logged in user")
|
|
33
37
|
.action(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
|
-
yield
|
|
38
|
+
yield Auth.Myself();
|
|
35
39
|
}));
|
|
36
40
|
cli
|
|
37
41
|
.command("trending")
|
|
@@ -39,7 +43,7 @@ cli
|
|
|
39
43
|
.description("Get the trending list from AniList")
|
|
40
44
|
.option("-c, --count <number>", "Number of list items to get", "10")
|
|
41
45
|
.action((_a) => __awaiter(void 0, [_a], void 0, function* ({ count }) {
|
|
42
|
-
yield
|
|
46
|
+
yield AniList.getTrendingAnime(Number(count));
|
|
43
47
|
}));
|
|
44
48
|
cli
|
|
45
49
|
.command("popular")
|
|
@@ -47,20 +51,19 @@ cli
|
|
|
47
51
|
.description("Get the popular list from AniList")
|
|
48
52
|
.option("-c, --count <number>", "Number of list items to get", "10")
|
|
49
53
|
.action((_a) => __awaiter(void 0, [_a], void 0, function* ({ count }) {
|
|
50
|
-
yield
|
|
54
|
+
yield AniList.getPopularAnime(Number(count));
|
|
51
55
|
}));
|
|
52
56
|
cli
|
|
53
|
-
.command("user")
|
|
57
|
+
.command("user <username>")
|
|
54
58
|
.description("Get user information")
|
|
55
|
-
.
|
|
56
|
-
.
|
|
57
|
-
yield getUserInfoByUsername(username);
|
|
59
|
+
.action((username) => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
|
+
yield AniList.getUserByUsername(username);
|
|
58
61
|
}));
|
|
59
62
|
cli
|
|
60
63
|
.command("logout")
|
|
61
64
|
.description("Log out the current user.")
|
|
62
65
|
.action(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
63
|
-
yield
|
|
66
|
+
yield Auth.Logout();
|
|
64
67
|
}));
|
|
65
68
|
cli
|
|
66
69
|
.command("lists")
|
|
@@ -70,30 +73,172 @@ cli
|
|
|
70
73
|
.option("-m, --manga", "For manga list of authenticated user", false)
|
|
71
74
|
.action((_a) => __awaiter(void 0, [_a], void 0, function* ({ anime, manga }) {
|
|
72
75
|
if ((!anime && !manga) || (anime && manga)) {
|
|
73
|
-
console.
|
|
76
|
+
console.error(`\nMust select an option, either --anime or --manga`);
|
|
74
77
|
}
|
|
75
78
|
else if (anime) {
|
|
76
|
-
yield
|
|
79
|
+
yield AniList.MyAnime();
|
|
77
80
|
}
|
|
78
81
|
else if (manga) {
|
|
79
|
-
yield
|
|
82
|
+
yield AniList.MyManga();
|
|
80
83
|
}
|
|
81
84
|
}));
|
|
82
85
|
cli
|
|
83
86
|
.command("delete")
|
|
84
87
|
.alias("del")
|
|
85
|
-
.description("Delete entire collections of anime or
|
|
88
|
+
.description("Delete entire collections of anime or manga")
|
|
86
89
|
.option("-a, --anime", "For anime list of authenticated user", false)
|
|
87
90
|
.option("-m, --manga", "For manga list of authenticated user", false)
|
|
91
|
+
.option("-s, --activity", "For activity of authenticated user", false)
|
|
92
|
+
.action((_a) => __awaiter(void 0, [_a], void 0, function* ({ anime, manga, activity }) {
|
|
93
|
+
const selectedOptions = [anime, manga, activity].filter(Boolean).length;
|
|
94
|
+
if (selectedOptions === 0) {
|
|
95
|
+
console.error(`\nMust select one option: either --anime, --manga, or --activity`);
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
if (selectedOptions > 1) {
|
|
99
|
+
console.error(`\nOnly one option can be selected at a time: --anime, --manga, or --activity`);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
if (anime) {
|
|
103
|
+
yield Auth.DeleteMyAnimeList();
|
|
104
|
+
}
|
|
105
|
+
else if (manga) {
|
|
106
|
+
yield Auth.DeleteMyMangaList();
|
|
107
|
+
}
|
|
108
|
+
else if (activity) {
|
|
109
|
+
yield Auth.DeleteMyActivities();
|
|
110
|
+
}
|
|
111
|
+
}));
|
|
112
|
+
cli
|
|
113
|
+
.command("upcoming")
|
|
114
|
+
.alias("up")
|
|
115
|
+
.description("Anime that will be released in upcoming season")
|
|
116
|
+
.option("-c, --count <number>", "Number of items to get", "10")
|
|
117
|
+
.action((_a) => __awaiter(void 0, [_a], void 0, function* ({ count }) {
|
|
118
|
+
yield AniList.getUpcomingAnime(Number(count));
|
|
119
|
+
}));
|
|
120
|
+
cli
|
|
121
|
+
.command("anime <id>")
|
|
122
|
+
.description("Get anime details by their ID")
|
|
123
|
+
.action((id) => __awaiter(void 0, void 0, void 0, function* () {
|
|
124
|
+
if (id && !Number.isNaN(Number(id))) {
|
|
125
|
+
yield AniList.getAnimeDetailsByID(Number(id));
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
console.error(`\nInvalid or missing ID (${id}). Please provide a valid numeric ID.`);
|
|
129
|
+
}
|
|
130
|
+
}));
|
|
131
|
+
cli
|
|
132
|
+
.command("search <query>")
|
|
133
|
+
.alias("srch")
|
|
134
|
+
.alias("find")
|
|
135
|
+
.description("Search anime or manga.")
|
|
136
|
+
.option("-a, --anime", "To get the anime search results.", false)
|
|
137
|
+
.option("-m, --manga", "To get the manga search results.", false)
|
|
138
|
+
.option("-c, --count <number>", "Number of search results to show.", "10")
|
|
139
|
+
.action((query_1, _a) => __awaiter(void 0, [query_1, _a], void 0, function* (query, { anime, manga, count }) {
|
|
140
|
+
if ((!anime && !manga) || (anime && manga)) {
|
|
141
|
+
console.error(`\nMust select an option, either --anime or --manga`);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
if (anime) {
|
|
145
|
+
yield AniList.searchAnime(query, Number(count));
|
|
146
|
+
}
|
|
147
|
+
else if (manga) {
|
|
148
|
+
yield AniList.searchManga(query, Number(count));
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
console.error(`\nMust select an option, either --anime or --manga`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}));
|
|
155
|
+
cli
|
|
156
|
+
.command("status <status>")
|
|
157
|
+
.alias("post")
|
|
158
|
+
.alias("write")
|
|
159
|
+
.description("Write a status...")
|
|
160
|
+
.action((status) => __awaiter(void 0, void 0, void 0, function* () {
|
|
161
|
+
yield Auth.Write(status);
|
|
162
|
+
}));
|
|
163
|
+
cli
|
|
164
|
+
.command("export")
|
|
165
|
+
.alias("exp")
|
|
166
|
+
.description("Export your anime or manga list.")
|
|
167
|
+
.option("-a, --anime", "To get the anime search results.", false)
|
|
168
|
+
.option("-m, --manga", "To get the manga search results.", false)
|
|
88
169
|
.action((_a) => __awaiter(void 0, [_a], void 0, function* ({ anime, manga }) {
|
|
89
170
|
if ((!anime && !manga) || (anime && manga)) {
|
|
90
|
-
console.
|
|
171
|
+
console.error(`\nMust select an option, either --anime or --manga`);
|
|
91
172
|
}
|
|
92
|
-
else
|
|
93
|
-
|
|
173
|
+
else {
|
|
174
|
+
if (anime) {
|
|
175
|
+
yield AniList.exportAnime();
|
|
176
|
+
}
|
|
177
|
+
else if (manga) {
|
|
178
|
+
yield AniList.exportManga();
|
|
179
|
+
}
|
|
94
180
|
}
|
|
95
|
-
|
|
96
|
-
|
|
181
|
+
}));
|
|
182
|
+
cli
|
|
183
|
+
.command("import")
|
|
184
|
+
.alias("imp")
|
|
185
|
+
.description("Import your anime or manga from anilist or other sources.")
|
|
186
|
+
.option("-a, --anime", "To get the anime search results.", false)
|
|
187
|
+
.option("-m, --manga", "To get the manga search results.", false)
|
|
188
|
+
.action((_a) => __awaiter(void 0, [_a], void 0, function* ({ anime, manga }) {
|
|
189
|
+
if ((!anime && !manga) || (anime && manga)) {
|
|
190
|
+
console.error(`\nMust select an option, either --anime or --manga`);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
if (yield Auth.isLoggedIn()) {
|
|
194
|
+
if (anime) {
|
|
195
|
+
yield Auth.callAnimeImporter();
|
|
196
|
+
}
|
|
197
|
+
else if (manga) {
|
|
198
|
+
yield Auth.callMangaImporter();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
console.error(`\nPlease login to use this feature.`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}));
|
|
206
|
+
cli
|
|
207
|
+
.command("autolike")
|
|
208
|
+
.alias("al")
|
|
209
|
+
.option("-2, --v2", "Like the activities", false)
|
|
210
|
+
.option("-c, --count <number>", "Number of activities to like", "25")
|
|
211
|
+
.description("Autolike following or global activities.")
|
|
212
|
+
.action((_a) => __awaiter(void 0, [_a], void 0, function* ({ v2, count }) {
|
|
213
|
+
if (v2) {
|
|
214
|
+
yield Auth.LikeFollowingActivityV2(count);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
yield Auth.AutoLike();
|
|
218
|
+
}
|
|
219
|
+
}));
|
|
220
|
+
cli
|
|
221
|
+
.command("social")
|
|
222
|
+
.alias("sol")
|
|
223
|
+
.description("Automate your process")
|
|
224
|
+
.option("-f, --follow", "Follow the user whos following you.", false)
|
|
225
|
+
.option("-u, --unfollow", "Unfollow the user whos not following you.", false)
|
|
226
|
+
.action((_a) => __awaiter(void 0, [_a], void 0, function* ({ follow, unfollow }) {
|
|
227
|
+
if (!follow && !unfollow) {
|
|
228
|
+
console.error(`\nMust select an option, either --follow or --unfollow`);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
if (yield Auth.isLoggedIn()) {
|
|
232
|
+
if (follow) {
|
|
233
|
+
yield Social.follow();
|
|
234
|
+
}
|
|
235
|
+
else if (unfollow) {
|
|
236
|
+
yield Social.unfollow();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
console.error(`\nPlease login to use this feature.`);
|
|
241
|
+
}
|
|
97
242
|
}
|
|
98
243
|
}));
|
|
99
244
|
cli.parse(process.argv);
|