ani-auto 1.2.2 → 1.2.3
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/package.json +1 -1
- package/src/cli.js +84 -11
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -68,17 +68,18 @@ program
|
|
|
68
68
|
}]);
|
|
69
69
|
anilistToken = tokenAnswer.anilistToken;
|
|
70
70
|
|
|
71
|
+
console.log(chalk.gray(' Tip: select multiple statuses with space, confirm with enter.'));
|
|
71
72
|
const statusAnswer = await inquirer.prompt([{
|
|
72
|
-
type:
|
|
73
|
-
|
|
73
|
+
type: 'checkbox',
|
|
74
|
+
name: 'watchStatuses',
|
|
75
|
+
message: 'Which AniList statuses to download?',
|
|
74
76
|
choices: [
|
|
75
|
-
{ name: 'CURRENT (Watching)', value: 'CURRENT' },
|
|
76
|
-
{ name: 'PLANNING (Plan to Watch)', value: 'PLANNING' },
|
|
77
|
-
{ name: 'PAUSED', value: 'PAUSED' },
|
|
78
|
-
{ name: 'REPEATING', value: 'REPEATING' },
|
|
77
|
+
{ name: 'CURRENT (Watching)', value: 'CURRENT', checked: (current.watchStatuses || ['CURRENT']).includes('CURRENT') },
|
|
78
|
+
{ name: 'PLANNING (Plan to Watch)', value: 'PLANNING', checked: (current.watchStatuses || []).includes('PLANNING') },
|
|
79
|
+
{ name: 'PAUSED', value: 'PAUSED', checked: (current.watchStatuses || []).includes('PAUSED') },
|
|
80
|
+
{ name: 'REPEATING', value: 'REPEATING', checked: (current.watchStatuses || []).includes('REPEATING') },
|
|
79
81
|
],
|
|
80
|
-
|
|
81
|
-
filter: v => [v],
|
|
82
|
+
validate: v => v.length > 0 ? true : 'Select at least one status',
|
|
82
83
|
}]);
|
|
83
84
|
watchStatuses = statusAnswer.watchStatuses;
|
|
84
85
|
}
|
|
@@ -153,7 +154,6 @@ program
|
|
|
153
154
|
console.log(chalk.green(` ✔ Saved default quality: ${quality}\n`));
|
|
154
155
|
}
|
|
155
156
|
|
|
156
|
-
// Status selection for this run
|
|
157
157
|
const { pickedStatuses } = await inquirer.prompt([{
|
|
158
158
|
type: 'checkbox',
|
|
159
159
|
name: 'pickedStatuses',
|
|
@@ -257,8 +257,32 @@ program
|
|
|
257
257
|
const config = loadConfig();
|
|
258
258
|
const manualList = config.manualList || [];
|
|
259
259
|
|
|
260
|
-
const
|
|
261
|
-
if (
|
|
260
|
+
const existsManual = manualList.find(m => m.title.toLowerCase() === resolvedTitle.toLowerCase());
|
|
261
|
+
if (existsManual) { console.log(chalk.yellow(` "${resolvedTitle}" is already in your manual list.`)); return; }
|
|
262
|
+
|
|
263
|
+
// Check if already in AniList watch list (fuzzy match)
|
|
264
|
+
const normalize = s => s.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
265
|
+
const { getUserList, pickTitle: pt } = require('./anilist');
|
|
266
|
+
if (config.anilistUsername) {
|
|
267
|
+
try {
|
|
268
|
+
const anilistEntries = await getUserList(
|
|
269
|
+
config.anilistUsername,
|
|
270
|
+
['CURRENT', 'PLANNING', 'PAUSED', 'REPEATING'],
|
|
271
|
+
config.anilistToken || null
|
|
272
|
+
);
|
|
273
|
+
const normResolved = normalize(resolvedTitle);
|
|
274
|
+
const inAnilist = anilistEntries.find(e => {
|
|
275
|
+
const t = e.titles;
|
|
276
|
+
return [t.english, t.romaji, t.native].some(
|
|
277
|
+
title => title && normalize(title) === normResolved
|
|
278
|
+
);
|
|
279
|
+
});
|
|
280
|
+
if (inAnilist) {
|
|
281
|
+
console.log(chalk.yellow(` "${resolvedTitle}" is already in your AniList list (${inAnilist.status}) — no need to add manually.`));
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
} catch (e) {}
|
|
285
|
+
}
|
|
262
286
|
|
|
263
287
|
const entry = { title: resolvedTitle, anilistId: picked.anilistId, enabled: true, quality: opts.quality || null, language: opts.language || null };
|
|
264
288
|
manualList.push(entry);
|
|
@@ -411,6 +435,55 @@ program
|
|
|
411
435
|
console.log('');
|
|
412
436
|
});
|
|
413
437
|
|
|
438
|
+
// ── update ───────────────────────────────────────────────────────────────
|
|
439
|
+
|
|
440
|
+
program
|
|
441
|
+
.command('update')
|
|
442
|
+
.description('Check for updates and install the latest version')
|
|
443
|
+
.action(async () => {
|
|
444
|
+
banner();
|
|
445
|
+
const fetch = require('node-fetch');
|
|
446
|
+
const { execSync } = require('child_process');
|
|
447
|
+
|
|
448
|
+
const spinner = ora('Checking for updates...').start();
|
|
449
|
+
try {
|
|
450
|
+
const res = await fetch('https://registry.npmjs.org/ani-auto/latest');
|
|
451
|
+
const data = await res.json();
|
|
452
|
+
const latest = data.version;
|
|
453
|
+
spinner.stop();
|
|
454
|
+
|
|
455
|
+
if (latest === version) {
|
|
456
|
+
console.log(chalk.green(` ✔ Already on the latest version (v${version}).\n`));
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
console.log(chalk.cyan(` Current version: ${chalk.bold(version)}`));
|
|
461
|
+
console.log(chalk.cyan(` Latest version: ${chalk.bold(latest)}\n`));
|
|
462
|
+
|
|
463
|
+
const { confirm } = await inquirer.prompt([{
|
|
464
|
+
type: 'confirm',
|
|
465
|
+
name: 'confirm',
|
|
466
|
+
message: `Update to v${latest}?`,
|
|
467
|
+
default: true,
|
|
468
|
+
}]);
|
|
469
|
+
|
|
470
|
+
if (!confirm) return;
|
|
471
|
+
|
|
472
|
+
const installing = ora(`Installing v${latest}...`).start();
|
|
473
|
+
try {
|
|
474
|
+
execSync('npm install -g ani-auto@latest', { stdio: 'pipe' });
|
|
475
|
+
installing.succeed(`Updated to v${latest} — restart your terminal to use the new version.`);
|
|
476
|
+
} catch (e) {
|
|
477
|
+
installing.fail('Update failed. Try manually: npm install -g ani-auto@latest');
|
|
478
|
+
}
|
|
479
|
+
} catch (e) {
|
|
480
|
+
spinner.fail(`Could not check for updates: ${e.message}`);
|
|
481
|
+
}
|
|
482
|
+
console.log('');
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
// ── daemon ────────────────────────────────────────────────────────────────
|
|
486
|
+
|
|
414
487
|
program
|
|
415
488
|
.command('daemon')
|
|
416
489
|
.description('Start the background daemon')
|