@oxiaom/adoremix 1.0.3 → 1.0.5

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": "@oxiaom/adoremix",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "AdoreMix broadcast server - cross-platform installer, runner and service manager",
5
5
  "bin": {
6
6
  "adoremix": "./bin/adoremix.js"
package/src/cli.js CHANGED
@@ -117,6 +117,36 @@ function buildProgram() {
117
117
  });
118
118
  });
119
119
 
120
+ config
121
+ .command('network')
122
+ .description('交互式配置 IP(内网选网卡 / 外网手动输入),同时设 LocalIP/Meida_ip/Fip')
123
+ .option('--workdir <path>')
124
+ .option('--ip <addr>', '直接指定 IP(非交互)')
125
+ .option('--no-interactive', '自动选第一个网卡')
126
+ .action(async (opts) => {
127
+ const net = require('./config/network');
128
+ const code = await net.setupNetwork(resolveWorkdir(opts.workdir), {
129
+ ip: opts.ip,
130
+ interactive: opts.interactive !== false
131
+ });
132
+ process.exitCode = code || 0;
133
+ });
134
+
135
+ config
136
+ .command('preurl')
137
+ .description('配置设备拉资源用的 URL(默认 http://IP:12080/,CDN 加速改成域名)')
138
+ .option('--workdir <path>')
139
+ .option('--url <url>', '直接指定 URL(如 http://cdn.your.com/)')
140
+ .option('--no-interactive', '用本机 IP 自动生成')
141
+ .action(async (opts) => {
142
+ const net = require('./config/network');
143
+ const code = await net.setupPreurl(resolveWorkdir(opts.workdir), {
144
+ url: opts.url,
145
+ interactive: opts.interactive !== false
146
+ });
147
+ process.exitCode = code || 0;
148
+ });
149
+
120
150
  const runner = require('./runner');
121
151
  const nativeRef = () => {
122
152
  try { return paths.loadNative(); }
@@ -0,0 +1,219 @@
1
+ 'use strict';
2
+
3
+ const os = require('os');
4
+ const prompts = require('prompts');
5
+ const logger = require('../logger');
6
+
7
+ const NET_KEYS = [
8
+ 'Settings.LocalIP',
9
+ 'Settings.Meida_ip',
10
+ 'Settings.Fip'
11
+ ];
12
+
13
+ const PREURL_KEY = 'Settings.preurl';
14
+ const HTTP_PORT_KEY = 'listener.port';
15
+
16
+ // 默认 preurl 格式:http://<IP>:<port>/
17
+ // 如果用户改成 CDN 域名(如 http://cdn.xxx.com/),改 IP 时不应该覆盖
18
+ function extractPreurlHost(preurl) {
19
+ if (!preurl) return null;
20
+ const m = String(preurl).match(/^https?:\/\/([^:/]+)/);
21
+ return m ? m[1] : null;
22
+ }
23
+
24
+ function isPreurlCdn(preurl) {
25
+ const host = extractPreurlHost(preurl);
26
+ if (!host) return false;
27
+ return !isValidIPv4(host); // 域名 = CDN,IP = 直连
28
+ }
29
+
30
+ function listInterfaces() {
31
+ const ifaces = os.networkInterfaces();
32
+ const list = [];
33
+ for (const name of Object.keys(ifaces)) {
34
+ for (const it of ifaces[name] || []) {
35
+ if (it.family === 'IPv4' && !it.internal) {
36
+ list.push({ name, address: it.address, mac: it.mac });
37
+ }
38
+ }
39
+ }
40
+ return list;
41
+ }
42
+
43
+ function isValidIPv4(s) {
44
+ return /^(\d{1,3}\.){3}\d{1,3}$/.test(s) && s.split('.').every(p => +p >= 0 && +p <= 255);
45
+ }
46
+
47
+ async function chooseIpInteractive(initial) {
48
+ const list = listInterfaces();
49
+ if (list.length === 0) {
50
+ logger.warn('未检测到任何 IPv4 网卡');
51
+ }
52
+ const choices = list.map(it => ({
53
+ title: `${it.address} (${it.name}${it.mac ? ', ' + it.mac.slice(0, 17) : ''})`,
54
+ value: it.address,
55
+ description: `网卡 ${it.name}`
56
+ }));
57
+ choices.push({
58
+ title: '🌐 手动输入外网/其他 IP(部署到云服务器用)',
59
+ value: '__custom__'
60
+ });
61
+ if (initial) {
62
+ choices.unshift({
63
+ title: `✓ 保持当前 IP: ${initial}`,
64
+ value: initial,
65
+ description: '不改'
66
+ });
67
+ }
68
+
69
+ const onCancel = () => { logger.warn('已取消'); process.exit(1); };
70
+ const resp = await prompts({
71
+ type: 'select',
72
+ name: 'ip',
73
+ message: '选择绑定的 IP',
74
+ choices,
75
+ initial: initial ? 0 : 0
76
+ }, { onCancel });
77
+ if (!resp.ip) return null;
78
+ if (resp.ip === '__custom__') {
79
+ const r2 = await prompts({
80
+ type: 'text',
81
+ name: 'ip',
82
+ message: '输入 IPv4 地址(外网/公网 IP)',
83
+ validate: v => isValidIPv4(v) ? true : 'IPv4 格式错误,如 1.2.3.4'
84
+ }, { onCancel });
85
+ return r2.ip;
86
+ }
87
+ return resp.ip;
88
+ }
89
+
90
+ async function setupNetwork(workdir, opts) {
91
+ opts = opts || {};
92
+ const cfg = require('./index');
93
+ const current = cfg.getConfigValue(workdir, 'Settings.LocalIP');
94
+ let ip;
95
+
96
+ if (opts.ip) {
97
+ if (!isValidIPv4(opts.ip)) {
98
+ logger.error(`IP 格式错误:${opts.ip}`);
99
+ return 1;
100
+ }
101
+ ip = opts.ip;
102
+ logger.log(`使用命令行指定的 IP: ${ip}`);
103
+ } else if (opts.interactive === false) {
104
+ // 非交互模式:自动选第一个网卡
105
+ const list = listInterfaces();
106
+ if (list.length === 0) {
107
+ logger.error('未检测到 IPv4 网卡,请用 --ip <地址> 指定');
108
+ return 1;
109
+ }
110
+ ip = list[0].address;
111
+ logger.log(`非交互模式:自动选择第一个网卡 ${list[0].name} = ${ip}`);
112
+ } else {
113
+ logger.log('');
114
+ logger.log('=== 网络配置向导 ===');
115
+ logger.log('说明:');
116
+ logger.log(' • 内网部署 → 选本机网卡 IP');
117
+ logger.log(' • 外网/云服务器 → 手动输入公网 IP');
118
+ logger.log(` • 将同时设置:${NET_KEYS.join(' / ')}`);
119
+ logger.log('');
120
+ ip = await chooseIpInteractive(current);
121
+ if (!ip) return 1;
122
+ }
123
+
124
+ for (const key of NET_KEYS) {
125
+ cfg.setConfigValue(workdir, key, ip);
126
+ }
127
+ logger.ok(`已设置 ${NET_KEYS.map(k => k.split('.')[1]).join(' / ')} = ${ip}`);
128
+
129
+ // 智能更新 preurl:如果是 IP 格式(直连),同步改;CDN 域名不动
130
+ const currentPreurl = cfg.getConfigValue(workdir, PREURL_KEY);
131
+ const port = cfg.getConfigValue(workdir, HTTP_PORT_KEY) || 12080;
132
+ if (currentPreurl && isPreurlCdn(currentPreurl)) {
133
+ logger.log('');
134
+ logger.log(`preurl 当前是 CDN/域名:${currentPreurl}(保留不覆盖)`);
135
+ logger.log(' 改 CDN 用:adoremix config preurl http://cdn.your.com/');
136
+ } else {
137
+ const newPreurl = `http://${ip}:${port}/`;
138
+ cfg.setConfigValue(workdir, PREURL_KEY, newPreurl);
139
+ logger.ok(`已同步更新 preurl = ${newPreurl}`);
140
+ }
141
+
142
+ // 顺便显示当前端口配置,方便检查
143
+ const ports = [
144
+ ['listener.port', 'HTTP 网页'],
145
+ ['Settings.wbport', 'web 后台'],
146
+ ['Settings.cuteport', 'cutehttpd'],
147
+ ['Settings.DataPort', '媒体数据'],
148
+ ['Settings.ManagePort', '管理端口']
149
+ ];
150
+ logger.log('');
151
+ logger.log('当前端口配置:');
152
+ for (const [k, desc] of ports) {
153
+ const v = cfg.getConfigValue(workdir, k);
154
+ logger.log(` ${desc.padEnd(12)} ${k} = ${v}`);
155
+ }
156
+ logger.log('');
157
+ logger.log('改完后记得:adoremix restart');
158
+ return 0;
159
+ }
160
+
161
+ async function setupPreurl(workdir, opts) {
162
+ opts = opts || {};
163
+ const cfg = require('./index');
164
+ const current = cfg.getConfigValue(workdir, PREURL_KEY);
165
+ const port = cfg.getConfigValue(workdir, HTTP_PORT_KEY) || 12080;
166
+ const ip = cfg.getConfigValue(workdir, 'Settings.LocalIP') || '127.0.0.1';
167
+
168
+ let url;
169
+ if (opts.url) {
170
+ url = opts.url;
171
+ } else if (opts.interactive === false) {
172
+ url = `http://${ip}:${port}/`;
173
+ } else {
174
+ logger.log('');
175
+ logger.log('=== preurl 配置(设备拉资源用的 URL)===');
176
+ logger.log('说明:');
177
+ logger.log(' • 直连:http://<本机IP>:<端口>/(默认)');
178
+ logger.log(' • CDN 加速:http://cdn.your.com/(设备从 CDN 拉资源)');
179
+ logger.log(` • 当前值:${current}`);
180
+ logger.log('');
181
+ const resp = await prompts({
182
+ type: 'select',
183
+ name: 'choice',
184
+ message: '选择 preurl 来源',
185
+ choices: [
186
+ { title: `用本机直连:http://${ip}:${port}/`, value: 'direct' },
187
+ { title: '🌐 手动输入 CDN/外网地址', value: 'custom' }
188
+ ]
189
+ });
190
+ if (resp.choice === 'direct') {
191
+ url = `http://${ip}:${port}/`;
192
+ } else if (resp.choice === 'custom') {
193
+ const r2 = await prompts({
194
+ type: 'text',
195
+ name: 'url',
196
+ message: '输入完整 URL(含 http(s):// 和末尾 /)',
197
+ initial: 'http://cdn.example.com/',
198
+ validate: v => /^https?:\/\/[^/]+\//.test(v) ? true : '格式:http(s)://域名或IP/'
199
+ });
200
+ url = r2.url;
201
+ } else {
202
+ return 1;
203
+ }
204
+ }
205
+ cfg.setConfigValue(workdir, PREURL_KEY, url);
206
+ logger.ok(`preurl = ${url}`);
207
+ logger.log('改完后记得:adoremix restart');
208
+ return 0;
209
+ }
210
+
211
+ module.exports = {
212
+ setupNetwork,
213
+ setupPreurl,
214
+ listInterfaces,
215
+ isValidIPv4,
216
+ isPreurlCdn,
217
+ NET_KEYS,
218
+ PREURL_KEY
219
+ };