@irfanshadikrishad/anilist 1.1.10 → 1.2.0-forbidden.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +373 -382
- package/LICENSE.md +382 -0
- package/README.md +87 -53
- package/bin/helpers/auth.d.ts +52 -8
- package/bin/helpers/auth.js +639 -271
- package/bin/helpers/fetcher.d.ts +2 -1
- package/bin/helpers/fetcher.js +9 -3
- package/bin/helpers/lists.d.ts +5 -1
- package/bin/helpers/lists.js +347 -260
- package/bin/helpers/mutations.d.ts +2 -1
- package/bin/helpers/mutations.js +37 -32
- package/bin/helpers/queries.d.ts +14 -7
- package/bin/helpers/queries.js +184 -128
- package/bin/helpers/truncate.d.ts +6 -0
- package/bin/helpers/truncate.js +10 -0
- package/bin/helpers/types.d.ts +367 -16
- package/bin/helpers/validation.d.ts +29 -0
- package/bin/helpers/validation.js +117 -0
- package/bin/helpers/workers.d.ts +22 -9
- package/bin/helpers/workers.js +220 -81
- package/bin/index.js +50 -8
- package/package.json +86 -75
package/bin/helpers/workers.js
CHANGED
|
@@ -7,16 +7,30 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
11
|
+
var t = {};
|
|
12
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
13
|
+
t[p] = s[p];
|
|
14
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
15
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
16
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
17
|
+
t[p[i]] = s[p[i]];
|
|
18
|
+
}
|
|
19
|
+
return t;
|
|
20
|
+
};
|
|
10
21
|
import fs from "fs";
|
|
11
22
|
import { readdir, writeFile } from "fs/promises";
|
|
12
23
|
import inquirer from "inquirer";
|
|
13
|
-
import {
|
|
24
|
+
import { createRequire } from "module";
|
|
14
25
|
import open from "open";
|
|
15
26
|
import { homedir } from "os";
|
|
27
|
+
import Papa from "papaparse";
|
|
16
28
|
import { join } from "path";
|
|
17
29
|
import process from "process";
|
|
18
30
|
import { Auth } from "./auth.js";
|
|
19
|
-
import {
|
|
31
|
+
import { fetcher } from "./fetcher.js";
|
|
32
|
+
import { animeSearchQuery } from "./queries.js";
|
|
33
|
+
import { MALAnimeStatus, MALMangaStatus, } from "./types.js";
|
|
20
34
|
const aniListEndpoint = `https://graphql.anilist.co`;
|
|
21
35
|
const redirectUri = "https://anilist.co/api/v2/oauth/pin";
|
|
22
36
|
function getTitle(title) {
|
|
@@ -94,13 +108,13 @@ function getFormattedDate() {
|
|
|
94
108
|
/**
|
|
95
109
|
* Export JSON as JSON
|
|
96
110
|
* @param js0n
|
|
97
|
-
* @param dataType (eg: anime
|
|
111
|
+
* @param dataType (eg: anime|manga)
|
|
98
112
|
*/
|
|
99
113
|
function saveJSONasJSON(js0n, dataType) {
|
|
100
114
|
return __awaiter(this, void 0, void 0, function* () {
|
|
101
115
|
try {
|
|
102
116
|
const jsonData = JSON.stringify(js0n, null, 2);
|
|
103
|
-
const path =
|
|
117
|
+
const path = yield saveToPath(dataType, ".json");
|
|
104
118
|
yield writeFile(path, jsonData, "utf8");
|
|
105
119
|
console.log(`\nSaved as JSON successfully.`);
|
|
106
120
|
open(getDownloadFolderPath());
|
|
@@ -113,13 +127,17 @@ function saveJSONasJSON(js0n, dataType) {
|
|
|
113
127
|
/**
|
|
114
128
|
* Export JSON as CSV
|
|
115
129
|
* @param js0n
|
|
116
|
-
* @param dataType (eg: anime
|
|
130
|
+
* @param dataType (eg: anime|manga)
|
|
117
131
|
*/
|
|
118
132
|
function saveJSONasCSV(js0n, dataType) {
|
|
119
133
|
return __awaiter(this, void 0, void 0, function* () {
|
|
120
134
|
try {
|
|
121
|
-
const
|
|
122
|
-
|
|
135
|
+
const js0n_WTAS = js0n.map((_a) => {
|
|
136
|
+
var { title } = _a, rest = __rest(_a, ["title"]);
|
|
137
|
+
return (Object.assign(Object.assign({}, rest), { title: getTitle(title) }));
|
|
138
|
+
});
|
|
139
|
+
const csvData = Papa.unparse(js0n_WTAS);
|
|
140
|
+
const path = yield saveToPath(dataType, ".csv");
|
|
123
141
|
yield writeFile(path, csvData, "utf8");
|
|
124
142
|
console.log(`\nSaved as CSV successfully.`);
|
|
125
143
|
open(getDownloadFolderPath());
|
|
@@ -129,6 +147,20 @@ function saveJSONasCSV(js0n, dataType) {
|
|
|
129
147
|
}
|
|
130
148
|
});
|
|
131
149
|
}
|
|
150
|
+
function saveJSONasXML(js0n, data_type) {
|
|
151
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
152
|
+
try {
|
|
153
|
+
const xmlContent = data_type === 0 ? createAnimeListXML(js0n) : createMangaListXML(js0n);
|
|
154
|
+
const path = yield saveToPath(data_type === 0 ? "anime" : "manga", ".xml");
|
|
155
|
+
yield writeFile(path, yield xmlContent, "utf8");
|
|
156
|
+
console.log(`\nGenerated XML for MyAnimeList.`);
|
|
157
|
+
open(getDownloadFolderPath());
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
console.error(`Error saving XML data:`, error);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
132
164
|
function listFilesInDownloadFolder() {
|
|
133
165
|
return __awaiter(this, void 0, void 0, function* () {
|
|
134
166
|
const downloadFolderPath = getDownloadFolderPath();
|
|
@@ -140,9 +172,10 @@ function selectFile(fileType) {
|
|
|
140
172
|
return __awaiter(this, void 0, void 0, function* () {
|
|
141
173
|
try {
|
|
142
174
|
const files = yield listFilesInDownloadFolder();
|
|
175
|
+
console.log(getDownloadFolderPath());
|
|
143
176
|
// Filter to include only files, not directories, with the specified extension
|
|
144
177
|
const onlyFiles = files.filter((file) => {
|
|
145
|
-
const filePath =
|
|
178
|
+
const filePath = `${getDownloadFolderPath()}/${file}`; // Adjust this to the correct path
|
|
146
179
|
const isFile = fs.lstatSync(filePath).isFile(); // Check if it's a file
|
|
147
180
|
return isFile && file.endsWith(fileType);
|
|
148
181
|
});
|
|
@@ -158,59 +191,60 @@ function selectFile(fileType) {
|
|
|
158
191
|
return answers.fileName;
|
|
159
192
|
}
|
|
160
193
|
else {
|
|
161
|
-
|
|
194
|
+
console.error(`\nNo importable ${fileType} file(s) found in download folder.`);
|
|
195
|
+
return null;
|
|
162
196
|
}
|
|
163
197
|
}
|
|
164
198
|
catch (error) {
|
|
165
199
|
console.error("\nError selecting file:", error);
|
|
166
|
-
|
|
200
|
+
return null;
|
|
167
201
|
}
|
|
168
202
|
});
|
|
169
203
|
}
|
|
170
|
-
function createAnimeXML(malId, progress, status, episodes, title) {
|
|
171
|
-
return `
|
|
172
|
-
<anime>
|
|
173
|
-
<series_animedb_id>${malId}</series_animedb_id>
|
|
174
|
-
<series_title><![CDATA[${title}]]></series_title>
|
|
175
|
-
<series_type
|
|
176
|
-
<series_episodes>${episodes}</series_episodes>
|
|
177
|
-
<my_id>0</my_id>
|
|
178
|
-
<my_watched_episodes>${progress}</my_watched_episodes>
|
|
179
|
-
<my_start_date>0000-00-00</my_start_date>
|
|
180
|
-
<my_finish_date>0000-00-00</my_finish_date>
|
|
181
|
-
<my_score>0</my_score>
|
|
182
|
-
<my_storage_value>0.00</my_storage_value>
|
|
183
|
-
<my_status>${status}</my_status>
|
|
184
|
-
<my_comments><![CDATA[]]></my_comments>
|
|
185
|
-
<my_times_watched>0</my_times_watched>
|
|
186
|
-
<my_rewatch_value></my_rewatch_value>
|
|
187
|
-
<my_priority>LOW</my_priority>
|
|
188
|
-
<my_tags><![CDATA[]]></my_tags>
|
|
189
|
-
<my_rewatching>0</my_rewatching>
|
|
190
|
-
<my_rewatching_ep>0</my_rewatching_ep>
|
|
191
|
-
<my_discuss>0</my_discuss>
|
|
192
|
-
<my_sns>default</my_sns>
|
|
193
|
-
<update_on_import>1</update_on_import>
|
|
204
|
+
function createAnimeXML(malId, progress, status, episodes, title, format) {
|
|
205
|
+
return `
|
|
206
|
+
<anime>
|
|
207
|
+
<series_animedb_id>${malId}</series_animedb_id>
|
|
208
|
+
<series_title><![CDATA[${title}]]></series_title>
|
|
209
|
+
<series_type>${format}</series_type>
|
|
210
|
+
<series_episodes>${episodes}</series_episodes>
|
|
211
|
+
<my_id>0</my_id>
|
|
212
|
+
<my_watched_episodes>${progress}</my_watched_episodes>
|
|
213
|
+
<my_start_date>0000-00-00</my_start_date>
|
|
214
|
+
<my_finish_date>0000-00-00</my_finish_date>
|
|
215
|
+
<my_score>0</my_score>
|
|
216
|
+
<my_storage_value>0.00</my_storage_value>
|
|
217
|
+
<my_status>${status}</my_status>
|
|
218
|
+
<my_comments><![CDATA[]]></my_comments>
|
|
219
|
+
<my_times_watched>0</my_times_watched>
|
|
220
|
+
<my_rewatch_value></my_rewatch_value>
|
|
221
|
+
<my_priority>LOW</my_priority>
|
|
222
|
+
<my_tags><![CDATA[]]></my_tags>
|
|
223
|
+
<my_rewatching>0</my_rewatching>
|
|
224
|
+
<my_rewatching_ep>0</my_rewatching_ep>
|
|
225
|
+
<my_discuss>0</my_discuss>
|
|
226
|
+
<my_sns>default</my_sns>
|
|
227
|
+
<update_on_import>1</update_on_import>
|
|
194
228
|
</anime>`;
|
|
195
229
|
}
|
|
196
230
|
function createMangaXML(malId, progress, status, chapters, title) {
|
|
197
|
-
return `
|
|
198
|
-
<manga>
|
|
199
|
-
<manga_mangadb_id>${malId}</manga_mangadb_id>
|
|
200
|
-
<manga_title><![CDATA[${title ? title : "unknown"}]]></manga_title>
|
|
201
|
-
<manga_volumes>0</manga_volumes>
|
|
202
|
-
<manga_chapters>${chapters ? chapters : 0}</manga_chapters>
|
|
203
|
-
<my_id>0</my_id>
|
|
204
|
-
<my_read_chapters>${progress}</my_read_chapters>
|
|
205
|
-
<my_start_date>0000-00-00</my_start_date>
|
|
206
|
-
<my_finish_date>0000-00-00</my_finish_date>
|
|
207
|
-
<my_score>0</my_score>
|
|
208
|
-
<my_status>${status}</my_status>
|
|
209
|
-
<my_reread_value></my_reread_value>
|
|
210
|
-
<my_priority>LOW</my_priority>
|
|
211
|
-
<my_rereading>0</my_rereading>
|
|
212
|
-
<my_discuss>0</my_discuss>
|
|
213
|
-
<update_on_import>1</update_on_import>
|
|
231
|
+
return `
|
|
232
|
+
<manga>
|
|
233
|
+
<manga_mangadb_id>${malId}</manga_mangadb_id>
|
|
234
|
+
<manga_title><![CDATA[${title ? title : "unknown"}]]></manga_title>
|
|
235
|
+
<manga_volumes>0</manga_volumes>
|
|
236
|
+
<manga_chapters>${chapters ? chapters : 0}</manga_chapters>
|
|
237
|
+
<my_id>0</my_id>
|
|
238
|
+
<my_read_chapters>${progress}</my_read_chapters>
|
|
239
|
+
<my_start_date>0000-00-00</my_start_date>
|
|
240
|
+
<my_finish_date>0000-00-00</my_finish_date>
|
|
241
|
+
<my_score>0</my_score>
|
|
242
|
+
<my_status>${status}</my_status>
|
|
243
|
+
<my_reread_value></my_reread_value>
|
|
244
|
+
<my_priority>LOW</my_priority>
|
|
245
|
+
<my_rereading>0</my_rereading>
|
|
246
|
+
<my_discuss>0</my_discuss>
|
|
247
|
+
<update_on_import>1</update_on_import>
|
|
214
248
|
</manga>`;
|
|
215
249
|
}
|
|
216
250
|
function createAnimeListXML(mediaWithProgress) {
|
|
@@ -222,27 +256,30 @@ function createAnimeListXML(mediaWithProgress) {
|
|
|
222
256
|
PAUSED: MALAnimeStatus.ON_HOLD,
|
|
223
257
|
DROPPED: MALAnimeStatus.DROPPED,
|
|
224
258
|
};
|
|
225
|
-
|
|
259
|
+
// Filter out anime without malId
|
|
260
|
+
const filteredMedia = mediaWithProgress.filter((anime) => anime.malId);
|
|
261
|
+
const xmlEntries = filteredMedia.map((anime) => {
|
|
226
262
|
const malId = anime.malId;
|
|
227
263
|
const progress = anime.progress;
|
|
228
264
|
const episodes = anime.episodes;
|
|
229
265
|
const title = getTitle(anime.title);
|
|
230
266
|
const status = statusMap[anime.status];
|
|
231
|
-
|
|
267
|
+
const format = anime.format ? anime.format : "";
|
|
268
|
+
return createAnimeXML(malId, progress, status, episodes, title, format);
|
|
232
269
|
});
|
|
233
|
-
return `<myanimelist>
|
|
234
|
-
<myinfo>
|
|
235
|
-
<user_id/>
|
|
236
|
-
<user_name>${yield Auth.MyUserName()}</user_name>
|
|
237
|
-
<user_export_type>1</user_export_type>
|
|
238
|
-
<user_total_anime>0</user_total_anime>
|
|
239
|
-
<user_total_watching>0</user_total_watching>
|
|
240
|
-
<user_total_completed>0</user_total_completed>
|
|
241
|
-
<user_total_onhold>0</user_total_onhold>
|
|
242
|
-
<user_total_dropped>0</user_total_dropped>
|
|
243
|
-
<user_total_plantowatch>0</user_total_plantowatch>
|
|
244
|
-
</myinfo>
|
|
245
|
-
\n${xmlEntries.join("\n")}\n
|
|
270
|
+
return `<myanimelist>
|
|
271
|
+
<myinfo>
|
|
272
|
+
<user_id/>
|
|
273
|
+
<user_name>${yield Auth.MyUserName()}</user_name>
|
|
274
|
+
<user_export_type>1</user_export_type>
|
|
275
|
+
<user_total_anime>0</user_total_anime>
|
|
276
|
+
<user_total_watching>0</user_total_watching>
|
|
277
|
+
<user_total_completed>0</user_total_completed>
|
|
278
|
+
<user_total_onhold>0</user_total_onhold>
|
|
279
|
+
<user_total_dropped>0</user_total_dropped>
|
|
280
|
+
<user_total_plantowatch>0</user_total_plantowatch>
|
|
281
|
+
</myinfo>
|
|
282
|
+
\n${xmlEntries.join("\n")}\n
|
|
246
283
|
</myanimelist>`;
|
|
247
284
|
});
|
|
248
285
|
}
|
|
@@ -255,7 +292,9 @@ function createMangaListXML(mediaWithProgress) {
|
|
|
255
292
|
PAUSED: MALMangaStatus.ON_HOLD,
|
|
256
293
|
DROPPED: MALMangaStatus.DROPPED,
|
|
257
294
|
};
|
|
258
|
-
|
|
295
|
+
// Filter out manga without malId
|
|
296
|
+
const filteredMedia = mediaWithProgress.filter((manga) => manga.malId);
|
|
297
|
+
const xmlEntries = filteredMedia.map((manga) => {
|
|
259
298
|
const malId = manga.malId;
|
|
260
299
|
const progress = manga.progress;
|
|
261
300
|
const chapters = manga.chapters;
|
|
@@ -263,20 +302,120 @@ function createMangaListXML(mediaWithProgress) {
|
|
|
263
302
|
const status = statusMap[manga.status];
|
|
264
303
|
return createMangaXML(malId, progress, status, chapters, title);
|
|
265
304
|
});
|
|
266
|
-
return `<myanimelist>
|
|
267
|
-
<myinfo>
|
|
268
|
-
<user_id/>
|
|
269
|
-
<user_name>${yield Auth.MyUserName()}</user_name>
|
|
270
|
-
<user_export_type>2</user_export_type>
|
|
271
|
-
<user_total_manga>5</user_total_manga>
|
|
272
|
-
<user_total_reading>1</user_total_reading>
|
|
273
|
-
<user_total_completed>1</user_total_completed>
|
|
274
|
-
<user_total_onhold>1</user_total_onhold>
|
|
275
|
-
<user_total_dropped>1</user_total_dropped>
|
|
276
|
-
<user_total_plantoread>1</user_total_plantoread>
|
|
277
|
-
</myinfo>
|
|
278
|
-
\n${xmlEntries.join("\n")}\n
|
|
305
|
+
return `<myanimelist>
|
|
306
|
+
<myinfo>
|
|
307
|
+
<user_id/>
|
|
308
|
+
<user_name>${yield Auth.MyUserName()}</user_name>
|
|
309
|
+
<user_export_type>2</user_export_type>
|
|
310
|
+
<user_total_manga>5</user_total_manga>
|
|
311
|
+
<user_total_reading>1</user_total_reading>
|
|
312
|
+
<user_total_completed>1</user_total_completed>
|
|
313
|
+
<user_total_onhold>1</user_total_onhold>
|
|
314
|
+
<user_total_dropped>1</user_total_dropped>
|
|
315
|
+
<user_total_plantoread>1</user_total_plantoread>
|
|
316
|
+
</myinfo>
|
|
317
|
+
\n${xmlEntries.join("\n")}\n
|
|
279
318
|
</myanimelist>`;
|
|
280
319
|
});
|
|
281
320
|
}
|
|
282
|
-
|
|
321
|
+
function getCurrentPackageVersion() {
|
|
322
|
+
const require = createRequire(import.meta.url);
|
|
323
|
+
const packageJson = require("../../package.json");
|
|
324
|
+
const version = packageJson.version;
|
|
325
|
+
return version || null;
|
|
326
|
+
}
|
|
327
|
+
function timestampToTimeAgo(timestamp) {
|
|
328
|
+
const now = Math.floor(Date.now() / 1000);
|
|
329
|
+
const elapsed = now - timestamp;
|
|
330
|
+
if (elapsed < 60) {
|
|
331
|
+
return `${elapsed} second${elapsed === 1 ? "" : "s"} ago`;
|
|
332
|
+
}
|
|
333
|
+
else if (elapsed < 3600) {
|
|
334
|
+
const minutes = Math.floor(elapsed / 60);
|
|
335
|
+
return `${minutes} minute${minutes === 1 ? "" : "s"} ago`;
|
|
336
|
+
}
|
|
337
|
+
else if (elapsed < 86400) {
|
|
338
|
+
const hours = Math.floor(elapsed / 3600);
|
|
339
|
+
return `${hours} hour${hours === 1 ? "" : "s"} ago`;
|
|
340
|
+
}
|
|
341
|
+
else if (elapsed < 2592000) {
|
|
342
|
+
const days = Math.floor(elapsed / 86400);
|
|
343
|
+
return `${days} day${days === 1 ? "" : "s"} ago`;
|
|
344
|
+
}
|
|
345
|
+
else if (elapsed < 31536000) {
|
|
346
|
+
const months = Math.floor(elapsed / 2592000);
|
|
347
|
+
return `${months} month${months === 1 ? "" : "s"} ago`;
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
const years = Math.floor(elapsed / 31536000);
|
|
351
|
+
return `${years} year${years === 1 ? "" : "s"} ago`;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
const anidbToanilistMapper = (romanjiName, year, englishName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
355
|
+
const fetchAnime = (search) => __awaiter(void 0, void 0, void 0, function* () {
|
|
356
|
+
var _a;
|
|
357
|
+
try {
|
|
358
|
+
const response = yield fetcher(animeSearchQuery, {
|
|
359
|
+
search,
|
|
360
|
+
perPage: 50,
|
|
361
|
+
});
|
|
362
|
+
return ((_a = response.data) === null || _a === void 0 ? void 0 : _a.Page.media) || [];
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
console.error("Error fetching AniList data:", error);
|
|
366
|
+
return [];
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
// Search using romanjiName first
|
|
370
|
+
let results = yield fetchAnime(romanjiName);
|
|
371
|
+
// If no results, fallback to englishName
|
|
372
|
+
if (!results.length && englishName) {
|
|
373
|
+
results = yield fetchAnime(englishName);
|
|
374
|
+
}
|
|
375
|
+
// Match using year
|
|
376
|
+
for (const anime of results) {
|
|
377
|
+
if (anime.startDate.year === year) {
|
|
378
|
+
return anime.id;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return null;
|
|
382
|
+
});
|
|
383
|
+
function activityBy(activity, count) {
|
|
384
|
+
var _a, _b, _c, _d;
|
|
385
|
+
const countStr = `[${count ? count : "?"}]`.padEnd(6);
|
|
386
|
+
if ((_a = activity === null || activity === void 0 ? void 0 : activity.messenger) === null || _a === void 0 ? void 0 : _a.name) {
|
|
387
|
+
return `${countStr}${activity.messenger.name} >> messaged ${activity.recipient.name}`;
|
|
388
|
+
}
|
|
389
|
+
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) {
|
|
390
|
+
if (activity.progress) {
|
|
391
|
+
return `${countStr}${activity.user.name} >> ${activity.status} ${activity.progress} of ${activity.media.title.userPreferred}`;
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
return `${countStr}${activity.user.name} >> ${activity.status} ${activity.media.title.userPreferred}`;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
else if ((_d = activity === null || activity === void 0 ? void 0 : activity.user) === null || _d === void 0 ? void 0 : _d.name) {
|
|
398
|
+
return `${countStr}${activity.user.name}`;
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
return `${countStr}???`;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Extract the save file path
|
|
406
|
+
* @param data_type - anime|manga
|
|
407
|
+
* @param file_format - save format (eg: .json|.csv)
|
|
408
|
+
* @returns string of file path
|
|
409
|
+
*/
|
|
410
|
+
function saveToPath(data_type, file_format) {
|
|
411
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
412
|
+
return join(getDownloadFolderPath(), `${yield Auth.MyUserName()}@irfanshadikrishad-anilist-${data_type}-${getFormattedDate()}.${file_format}`);
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
function simpleDateFormat(date) {
|
|
416
|
+
if (!date.day && !date.month && !date.year) {
|
|
417
|
+
return `null`;
|
|
418
|
+
}
|
|
419
|
+
return `${date === null || date === void 0 ? void 0 : date.day}/${date === null || date === void 0 ? void 0 : date.month}/${date === null || date === void 0 ? void 0 : date.year}`;
|
|
420
|
+
}
|
|
421
|
+
export { activityBy, anidbToanilistMapper, aniListEndpoint, createAnimeListXML, createAnimeXML, createMangaListXML, createMangaXML, formatDateObject, getCurrentPackageVersion, getDownloadFolderPath, getFormattedDate, getNextSeasonAndYear, getTitle, redirectUri, removeHtmlAndMarkdown, saveJSONasCSV, saveJSONasJSON, saveJSONasXML, saveToPath, selectFile, simpleDateFormat, timestampToTimeAgo, };
|
package/bin/index.js
CHANGED
|
@@ -9,18 +9,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
import { Command } from "commander";
|
|
12
|
-
import { createRequire } from "module";
|
|
13
12
|
import process from "process";
|
|
14
|
-
import { Auth } from "./helpers/auth.js";
|
|
13
|
+
import { Auth, Social } from "./helpers/auth.js";
|
|
15
14
|
import { AniList } from "./helpers/lists.js";
|
|
16
|
-
|
|
17
|
-
const packageJson = require("../package.json");
|
|
18
|
-
const version = packageJson.version;
|
|
15
|
+
import { getCurrentPackageVersion } from "./helpers/workers.js";
|
|
19
16
|
const cli = new Command();
|
|
20
17
|
cli
|
|
21
18
|
.name("anilist")
|
|
22
19
|
.description("Minimalist unofficial AniList CLI for Anime and Manga Enthusiasts.")
|
|
23
|
-
.version(
|
|
20
|
+
.version(getCurrentPackageVersion());
|
|
24
21
|
cli
|
|
25
22
|
.command("login")
|
|
26
23
|
.description("Login with AniList")
|
|
@@ -35,7 +32,7 @@ cli
|
|
|
35
32
|
}
|
|
36
33
|
}));
|
|
37
34
|
cli
|
|
38
|
-
.command("
|
|
35
|
+
.command("whoami")
|
|
39
36
|
.description("Get details of the logged in user")
|
|
40
37
|
.action(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
41
38
|
yield Auth.Myself();
|
|
@@ -91,7 +88,7 @@ cli
|
|
|
91
88
|
.description("Delete entire collections of anime or manga")
|
|
92
89
|
.option("-a, --anime", "For anime list of authenticated user", false)
|
|
93
90
|
.option("-m, --manga", "For manga list of authenticated user", false)
|
|
94
|
-
.option("-
|
|
91
|
+
.option("-s, --activity", "For activity of authenticated user", false)
|
|
95
92
|
.action((_a) => __awaiter(void 0, [_a], void 0, function* ({ anime, manga, activity }) {
|
|
96
93
|
const selectedOptions = [anime, manga, activity].filter(Boolean).length;
|
|
97
94
|
if (selectedOptions === 0) {
|
|
@@ -131,6 +128,13 @@ cli
|
|
|
131
128
|
console.error(`\nInvalid or missing ID (${id}). Please provide a valid numeric ID.`);
|
|
132
129
|
}
|
|
133
130
|
}));
|
|
131
|
+
cli
|
|
132
|
+
.command("manga <id>")
|
|
133
|
+
.description("Get manga details by their ID")
|
|
134
|
+
.option("-c, --count <number>", "Number of items to get", "10")
|
|
135
|
+
.action((id) => __awaiter(void 0, void 0, void 0, function* () {
|
|
136
|
+
yield AniList.getMangaDetailsByID(id);
|
|
137
|
+
}));
|
|
134
138
|
cli
|
|
135
139
|
.command("search <query>")
|
|
136
140
|
.alias("srch")
|
|
@@ -206,4 +210,42 @@ cli
|
|
|
206
210
|
}
|
|
207
211
|
}
|
|
208
212
|
}));
|
|
213
|
+
cli
|
|
214
|
+
.command("autolike")
|
|
215
|
+
.alias("al")
|
|
216
|
+
.option("-2, --v2", "Like the activities", false)
|
|
217
|
+
.option("-c, --count <number>", "Number of activities to like", "25")
|
|
218
|
+
.description("Autolike following or global activities.")
|
|
219
|
+
.action((_a) => __awaiter(void 0, [_a], void 0, function* ({ v2, count }) {
|
|
220
|
+
if (v2) {
|
|
221
|
+
yield Auth.LikeFollowingActivityV2(count);
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
yield Auth.AutoLike();
|
|
225
|
+
}
|
|
226
|
+
}));
|
|
227
|
+
cli
|
|
228
|
+
.command("social")
|
|
229
|
+
.alias("sol")
|
|
230
|
+
.description("Automate your process")
|
|
231
|
+
.option("-f, --follow", "Follow the user whos following you.", false)
|
|
232
|
+
.option("-u, --unfollow", "Unfollow the user whos not following you.", false)
|
|
233
|
+
.action((_a) => __awaiter(void 0, [_a], void 0, function* ({ follow, unfollow }) {
|
|
234
|
+
if (!follow && !unfollow) {
|
|
235
|
+
console.error(`\nMust select an option, either --follow or --unfollow`);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
if (yield Auth.isLoggedIn()) {
|
|
239
|
+
if (follow) {
|
|
240
|
+
yield Social.follow();
|
|
241
|
+
}
|
|
242
|
+
else if (unfollow) {
|
|
243
|
+
yield Social.unfollow();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
console.error(`\nPlease login to use this feature.`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}));
|
|
209
251
|
cli.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,75 +1,86 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@irfanshadikrishad/anilist",
|
|
3
|
-
"description": "Minimalist unofficial AniList CLI for Anime and Manga Enthusiasts",
|
|
4
|
-
"author": "Irfan Shadik Rishad",
|
|
5
|
-
"version": "1.
|
|
6
|
-
"main": "./bin/index.js",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"types": "./bin/index.d.ts",
|
|
9
|
-
"bin": {
|
|
10
|
-
"anilist": "./bin/index.js"
|
|
11
|
-
},
|
|
12
|
-
"publishConfig": {
|
|
13
|
-
"access": "public"
|
|
14
|
-
},
|
|
15
|
-
"scripts": {
|
|
16
|
-
"build": "rm -rf ./bin && tsc",
|
|
17
|
-
"
|
|
18
|
-
"format": "prettier . --write",
|
|
19
|
-
"format:check": "prettier . --check",
|
|
20
|
-
"lint": "eslint ./dist",
|
|
21
|
-
"lint:fix": "eslint ./dist --fix",
|
|
22
|
-
"all": "npm run lint && npm run lint:fix && npm run format",
|
|
23
|
-
"test": "
|
|
24
|
-
},
|
|
25
|
-
"keywords": [
|
|
26
|
-
"anilist",
|
|
27
|
-
"CLI",
|
|
28
|
-
"anime",
|
|
29
|
-
"manga",
|
|
30
|
-
"anime list",
|
|
31
|
-
"manga list",
|
|
32
|
-
"anime tracker",
|
|
33
|
-
"manga tracker",
|
|
34
|
-
"anilist API",
|
|
35
|
-
"anime progress",
|
|
36
|
-
"manga progress",
|
|
37
|
-
"media list",
|
|
38
|
-
"export anime",
|
|
39
|
-
"import anime",
|
|
40
|
-
"export manga",
|
|
41
|
-
"import manga",
|
|
42
|
-
"status tracker",
|
|
43
|
-
"watchlist",
|
|
44
|
-
"reading list",
|
|
45
|
-
"graphql"
|
|
46
|
-
],
|
|
47
|
-
"repository": {
|
|
48
|
-
"type": "git",
|
|
49
|
-
"url": "https://github.com/irfanshadikrishad/anilist"
|
|
50
|
-
},
|
|
51
|
-
"homepage": "https://github.com/irfanshadikrishad/anilist",
|
|
52
|
-
"bugs": {
|
|
53
|
-
"url": "https://github.com/irfanshadikrishad/anilist/issues"
|
|
54
|
-
},
|
|
55
|
-
"license": "MPL-2.0",
|
|
56
|
-
"devDependencies": {
|
|
57
|
-
"@
|
|
58
|
-
"@
|
|
59
|
-
"@types/
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@irfanshadikrishad/anilist",
|
|
3
|
+
"description": "Minimalist unofficial AniList CLI for Anime and Manga Enthusiasts",
|
|
4
|
+
"author": "Irfan Shadik Rishad",
|
|
5
|
+
"version": "1.2.0-forbidden.6",
|
|
6
|
+
"main": "./bin/index.js",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"types": "./bin/index.d.ts",
|
|
9
|
+
"bin": {
|
|
10
|
+
"anilist": "./bin/index.js"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "rm -rf ./bin && tsc",
|
|
17
|
+
"build:watch": "rm -rf ./bin && tsc -w",
|
|
18
|
+
"format": "prettier . --write",
|
|
19
|
+
"format:check": "prettier . --check",
|
|
20
|
+
"lint": "eslint ./dist",
|
|
21
|
+
"lint:fix": "eslint ./dist --fix",
|
|
22
|
+
"all": "npm run build && npm run lint && npm run lint:fix && npm run format && npm test",
|
|
23
|
+
"test": "jest ./tests"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"anilist",
|
|
27
|
+
"CLI",
|
|
28
|
+
"anime",
|
|
29
|
+
"manga",
|
|
30
|
+
"anime list",
|
|
31
|
+
"manga list",
|
|
32
|
+
"anime tracker",
|
|
33
|
+
"manga tracker",
|
|
34
|
+
"anilist API",
|
|
35
|
+
"anime progress",
|
|
36
|
+
"manga progress",
|
|
37
|
+
"media list",
|
|
38
|
+
"export anime",
|
|
39
|
+
"import anime",
|
|
40
|
+
"export manga",
|
|
41
|
+
"import manga",
|
|
42
|
+
"status tracker",
|
|
43
|
+
"watchlist",
|
|
44
|
+
"reading list",
|
|
45
|
+
"graphql"
|
|
46
|
+
],
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "https://github.com/irfanshadikrishad/anilist"
|
|
50
|
+
},
|
|
51
|
+
"homepage": "https://github.com/irfanshadikrishad/anilist",
|
|
52
|
+
"bugs": {
|
|
53
|
+
"url": "https://github.com/irfanshadikrishad/anilist/issues"
|
|
54
|
+
},
|
|
55
|
+
"license": "MPL-2.0",
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@babel/preset-env": "^7.26.9",
|
|
58
|
+
"@eslint/js": "^9.21.0",
|
|
59
|
+
"@types/jest": "^29.5.14",
|
|
60
|
+
"@types/node": "^22.13.5",
|
|
61
|
+
"@types/papaparse": "^5.3.15",
|
|
62
|
+
"@types/xml2js": "^0.4.14",
|
|
63
|
+
"@typescript-eslint/eslint-plugin": "^8.24.1",
|
|
64
|
+
"eslint": "^9.21.0",
|
|
65
|
+
"globals": "^16.0.0",
|
|
66
|
+
"jest": "^29.7.0",
|
|
67
|
+
"prettier": "^3.5.2",
|
|
68
|
+
"prettier-plugin-organize-imports": "^4.1.0",
|
|
69
|
+
"ts-jest": "^29.2.6",
|
|
70
|
+
"ts-node": "^10.9.2",
|
|
71
|
+
"typescript": "^5.7.3"
|
|
72
|
+
},
|
|
73
|
+
"dependencies": {
|
|
74
|
+
"@irfanshadikrishad/cipher": "^1.0.1",
|
|
75
|
+
"cli-truncate": "^4.0.0",
|
|
76
|
+
"commander": "^13.1.0",
|
|
77
|
+
"fast-xml-parser": "^5.0.6",
|
|
78
|
+
"inquirer": "^12.4.2",
|
|
79
|
+
"jsonrepair": "^3.12.0",
|
|
80
|
+
"node-fetch": "^3.3.2",
|
|
81
|
+
"open": "^10.1.0",
|
|
82
|
+
"papaparse": "^5.5.2",
|
|
83
|
+
"tiny-spinner": "^2.0.5",
|
|
84
|
+
"xml2js": "^0.6.2"
|
|
85
|
+
}
|
|
86
|
+
}
|