ani-auto 1.2.2 → 1.2.4

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