nekostream 2026.4.3 → 2026.4.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.
@@ -1,12 +1,17 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.runApplication = runApplication;
7
+ const chalk_1 = __importDefault(require("chalk"));
4
8
  const discord_1 = require("../discord");
5
9
  const logger_1 = require("../logger");
6
10
  const storage_1 = require("../storage");
7
11
  const domain_startup_1 = require("./domain-startup");
8
12
  const home_menu_1 = require("./menus/home-menu");
9
13
  const update_check_1 = require("./update-check");
14
+ const web_server_1 = require("./web-server");
10
15
  /**
11
16
  * Application entry point: bring up the runtime services, then hand control to
12
17
  * the home menu loop, which owns the interactive session until exit.
@@ -20,5 +25,12 @@ async function runApplication() {
20
25
  await (0, domain_startup_1.resolveProviderDomains)();
21
26
  await (0, discord_1.initDiscord)();
22
27
  (0, logger_1.debugLog)('NekoStream CLI started');
28
+ if (process.argv.includes('--web') || process.argv.includes('web')) {
29
+ const instance = await (0, web_server_1.startWebServer)();
30
+ console.log(chalk_1.default.cyan(`\n[NekoStream Web] Giao diện Web đang chạy tại: ${chalk_1.default.bold.underline(instance.url)}`));
31
+ console.log(chalk_1.default.gray('Nhấn Ctrl+C để dừng server.\n'));
32
+ (0, web_server_1.openBrowser)(instance.url);
33
+ return new Promise(() => { });
34
+ }
23
35
  await (0, home_menu_1.showHomeMenu)();
24
36
  }
@@ -12,6 +12,7 @@ exports.reportFailure = reportFailure;
12
12
  exports.reportEmpty = reportEmpty;
13
13
  exports.withSpinner = withSpinner;
14
14
  exports.withSilentSpinner = withSilentSpinner;
15
+ exports.warnIfDeprecatedProvider = warnIfDeprecatedProvider;
15
16
  const chalk_1 = __importDefault(require("chalk"));
16
17
  const ora_1 = __importDefault(require("ora"));
17
18
  const ui_1 = require("../ui");
@@ -85,3 +86,12 @@ async function withSilentSpinner(message, task) {
85
86
  return { ok: false, error };
86
87
  }
87
88
  }
89
+ /**
90
+ * Warn the user in red if they switch to a provider that may no longer work properly.
91
+ */
92
+ async function warnIfDeprecatedProvider(provider) {
93
+ if (provider === 'anime47' || provider === 'animehay') {
94
+ console.log(chalk_1.default.red('\nProvider này có thể không còn hoạt động đúng chức năng, khuyên bạn chuyển sang sử dụng AnimeVietsub Provider để có trải nghiệm tốt nhất.\n'));
95
+ await sleep(exports.NOTICE_DELAY_MS);
96
+ }
97
+ }
@@ -19,6 +19,8 @@ const provider_lists_1 = require("../flows/provider-lists");
19
19
  const auth_flow_1 = require("../flows/auth-flow");
20
20
  const history_menu_1 = require("./history-menu");
21
21
  const settings_menu_1 = require("./settings-menu");
22
+ const web_server_1 = require("../web-server");
23
+ let activeWebServer = null;
22
24
  const HOME_LIST_TITLES = {
23
25
  favorites: 'Hộp phim',
24
26
  history_provider: 'Lịch sử',
@@ -76,6 +78,7 @@ function homeChoices(provider, status) {
76
78
  { separator: `TÀI KHOẢN : ${username.toUpperCase()}` },
77
79
  ...accountChoices(provider, status),
78
80
  { separator: 'HỆ THỐNG' },
81
+ { title: chalk_1.default.cyan('🌐 Mở giao diện Web (Trình duyệt)'), value: 'open_web', description: 'Xem phim trên giao diện web trực quan' },
79
82
  { title: 'Tiếp tục xem (Lịch sử Local)', value: 'history' },
80
83
  { title: 'Cài đặt hệ thống', value: 'settings' },
81
84
  { title: 'Đổi Provider', value: 'change_provider' },
@@ -134,6 +137,9 @@ async function changeProvider(current) {
134
137
  message: 'Chọn provider',
135
138
  choices: provider_types_1.PROVIDER_IDS.map((name) => ({ title: name, value: name })),
136
139
  });
140
+ if (newProvider) {
141
+ await (0, feedback_1.warnIfDeprecatedProvider)(newProvider);
142
+ }
137
143
  return newProvider ?? current;
138
144
  }
139
145
  function exitApplication() {
@@ -193,6 +199,15 @@ async function showHomeMenu() {
193
199
  case 'change_provider':
194
200
  currentProvider = await changeProvider(currentProvider);
195
201
  break;
202
+ case 'open_web':
203
+ if (!activeWebServer) {
204
+ activeWebServer = await (0, web_server_1.startWebServer)();
205
+ }
206
+ (0, web_server_1.openBrowser)(activeWebServer.url);
207
+ console.log(chalk_1.default.cyan(`\n[NekoStream Web] Giao diện Web đang chạy tại: ${chalk_1.default.bold.underline(activeWebServer.url)}`));
208
+ console.log(chalk_1.default.gray('Trình duyệt web của bạn đã được mở. Nhấn Enter để quay lại menu chính...\n'));
209
+ await (0, prompts_wrapper_1.default)({ type: 'text', name: 'pressEnter', message: 'Nhấn Enter để tiếp tục' });
210
+ break;
196
211
  }
197
212
  }
198
213
  }
@@ -22,8 +22,10 @@ async function chooseDefaultProvider() {
22
22
  message: 'Chọn provider mặc định',
23
23
  choices: provider_types_1.PROVIDER_IDS.map((name) => ({ title: name, value: name })),
24
24
  });
25
- if (newProvider)
25
+ if (newProvider) {
26
+ await (0, feedback_1.warnIfDeprecatedProvider)(newProvider);
26
27
  (0, storage_1.saveSettings)({ defaultProvider: newProvider });
28
+ }
27
29
  }
28
30
  async function chooseDefaultQuality() {
29
31
  const { newQuality } = await (0, prompts_wrapper_1.default)({
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.isNewerVersion = isNewerVersion;
6
7
  exports.checkUpdate = checkUpdate;
7
8
  const fs_1 = __importDefault(require("fs"));
8
9
  const path_1 = __importDefault(require("path"));
@@ -52,17 +53,39 @@ function runUpdate() {
52
53
  spinner.fail(chalk_1.default.red(`Cập nhật thất bại. Vui lòng chạy thủ công: ${installCommand}`));
53
54
  }
54
55
  }
56
+ /**
57
+ * Compare two version strings. Returns true only if `latest` is strictly newer than `current`.
58
+ */
59
+ function isNewerVersion(latest, current) {
60
+ const parse = (v) => v.split('.').map(part => parseInt(part.replace(/\D/g, ''), 10) || 0);
61
+ const l = parse(latest);
62
+ const c = parse(current);
63
+ const len = Math.max(l.length, c.length);
64
+ for (let i = 0; i < len; i++) {
65
+ const a = l[i] ?? 0;
66
+ const b = c[i] ?? 0;
67
+ if (a > b)
68
+ return true;
69
+ if (a < b)
70
+ return false;
71
+ }
72
+ return false;
73
+ }
55
74
  /**
56
75
  * Compare the installed version against the registry and offer to upgrade.
57
76
  * The CLI is version-gated: when an update exists the process exits either way,
58
77
  * so the user always runs a current build.
59
78
  */
60
79
  async function checkUpdate() {
80
+ // When running directly from source via `npm start` or tsx in dev, never gate or force-install
81
+ const isSourceRun = !/dist([\\/]cli)?[\\/]?$/.test(__dirname);
82
+ if (isSourceRun && process.env.NODE_ENV !== 'production')
83
+ return;
61
84
  const currentVersion = readCurrentVersion();
62
85
  if (!currentVersion)
63
86
  return;
64
87
  const latestVersion = await fetchLatestVersion();
65
- if (!latestVersion || latestVersion === currentVersion)
88
+ if (!latestVersion || !isNewerVersion(latestVersion, currentVersion))
66
89
  return;
67
90
  (0, ui_1.clearScreen)();
68
91
  (0, ui_1.printUpdateNotice)(currentVersion, latestVersion, NPM_PACKAGE_NAME);