atm-droid 1.0.7 → 1.0.8

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": "atm-droid",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "ATM Token Manager CLI - 跨平台 Factory Token 管理工具",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -0,0 +1,163 @@
1
+ const os = require('os');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const { execSync } = require('child_process');
5
+
6
+ const APP_NAME = 'ATM-Droid';
7
+
8
+ // 获取启动命令
9
+ function getStartCommand() {
10
+ const daemonPath = path.join(__dirname, 'daemon-runner.js');
11
+ return `"${process.execPath}" "${daemonPath}"`;
12
+ }
13
+
14
+ // Windows: 注册表
15
+ function enableWindows() {
16
+ try {
17
+ const cmd = getStartCommand();
18
+ execSync(`reg add "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v "${APP_NAME}" /t REG_SZ /d "${cmd}" /f`, { stdio: 'ignore' });
19
+ return true;
20
+ } catch (e) {
21
+ return false;
22
+ }
23
+ }
24
+
25
+ function disableWindows() {
26
+ try {
27
+ execSync(`reg delete "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v "${APP_NAME}" /f`, { stdio: 'ignore' });
28
+ return true;
29
+ } catch (e) {
30
+ return false;
31
+ }
32
+ }
33
+
34
+ function isEnabledWindows() {
35
+ try {
36
+ execSync(`reg query "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v "${APP_NAME}"`, { stdio: 'ignore' });
37
+ return true;
38
+ } catch (e) {
39
+ return false;
40
+ }
41
+ }
42
+
43
+ // macOS: LaunchAgents
44
+ function getMacPlistPath() {
45
+ return path.join(os.homedir(), 'Library', 'LaunchAgents', 'com.atm-droid.daemon.plist');
46
+ }
47
+
48
+ function enableMac() {
49
+ try {
50
+ const plistPath = getMacPlistPath();
51
+ const daemonPath = path.join(__dirname, 'daemon-runner.js');
52
+
53
+ const plist = `<?xml version="1.0" encoding="UTF-8"?>
54
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
55
+ <plist version="1.0">
56
+ <dict>
57
+ <key>Label</key>
58
+ <string>com.atm-droid.daemon</string>
59
+ <key>ProgramArguments</key>
60
+ <array>
61
+ <string>${process.execPath}</string>
62
+ <string>${daemonPath}</string>
63
+ </array>
64
+ <key>RunAtLoad</key>
65
+ <true/>
66
+ <key>KeepAlive</key>
67
+ <false/>
68
+ </dict>
69
+ </plist>`;
70
+
71
+ fs.mkdirSync(path.dirname(plistPath), { recursive: true });
72
+ fs.writeFileSync(plistPath, plist);
73
+ return true;
74
+ } catch (e) {
75
+ return false;
76
+ }
77
+ }
78
+
79
+ function disableMac() {
80
+ try {
81
+ const plistPath = getMacPlistPath();
82
+ if (fs.existsSync(plistPath)) {
83
+ fs.unlinkSync(plistPath);
84
+ }
85
+ return true;
86
+ } catch (e) {
87
+ return false;
88
+ }
89
+ }
90
+
91
+ function isEnabledMac() {
92
+ return fs.existsSync(getMacPlistPath());
93
+ }
94
+
95
+ // Linux: ~/.config/autostart
96
+ function getLinuxDesktopPath() {
97
+ return path.join(os.homedir(), '.config', 'autostart', 'atm-droid.desktop');
98
+ }
99
+
100
+ function enableLinux() {
101
+ try {
102
+ const desktopPath = getLinuxDesktopPath();
103
+ const daemonPath = path.join(__dirname, 'daemon-runner.js');
104
+
105
+ const desktop = `[Desktop Entry]
106
+ Type=Application
107
+ Name=ATM Droid Daemon
108
+ Exec=${process.execPath} ${daemonPath}
109
+ Hidden=false
110
+ NoDisplay=true
111
+ X-GNOME-Autostart-enabled=true
112
+ `;
113
+
114
+ fs.mkdirSync(path.dirname(desktopPath), { recursive: true });
115
+ fs.writeFileSync(desktopPath, desktop);
116
+ return true;
117
+ } catch (e) {
118
+ return false;
119
+ }
120
+ }
121
+
122
+ function disableLinux() {
123
+ try {
124
+ const desktopPath = getLinuxDesktopPath();
125
+ if (fs.existsSync(desktopPath)) {
126
+ fs.unlinkSync(desktopPath);
127
+ }
128
+ return true;
129
+ } catch (e) {
130
+ return false;
131
+ }
132
+ }
133
+
134
+ function isEnabledLinux() {
135
+ return fs.existsSync(getLinuxDesktopPath());
136
+ }
137
+
138
+ // 统一接口
139
+ function enable() {
140
+ const platform = os.platform();
141
+ if (platform === 'win32') return enableWindows();
142
+ if (platform === 'darwin') return enableMac();
143
+ if (platform === 'linux') return enableLinux();
144
+ return false;
145
+ }
146
+
147
+ function disable() {
148
+ const platform = os.platform();
149
+ if (platform === 'win32') return disableWindows();
150
+ if (platform === 'darwin') return disableMac();
151
+ if (platform === 'linux') return disableLinux();
152
+ return false;
153
+ }
154
+
155
+ function isEnabled() {
156
+ const platform = os.platform();
157
+ if (platform === 'win32') return isEnabledWindows();
158
+ if (platform === 'darwin') return isEnabledMac();
159
+ if (platform === 'linux') return isEnabledLinux();
160
+ return false;
161
+ }
162
+
163
+ module.exports = { enable, disable, isEnabled };
package/src/commands.js CHANGED
@@ -6,6 +6,7 @@ const path = require('path');
6
6
  const { config, writeFactoryAuth, readFactoryAuth, getFactoryAuthPath } = require('./config');
7
7
  const api = require('./api');
8
8
  const daemon = require('./daemon');
9
+ const autostart = require('./autostart');
9
10
 
10
11
  // 格式化数字
11
12
  function formatNumber(num) {
@@ -45,6 +46,13 @@ async function login(code) {
45
46
  console.log(chalk.green(' ✓ 后台服务已启动'));
46
47
  }
47
48
 
49
+ // 默认启用开机自启动
50
+ if (!autostart.isEnabled()) {
51
+ if (autostart.enable()) {
52
+ console.log(chalk.green(' ✓ 已设置开机自启动'));
53
+ }
54
+ }
55
+
48
56
  console.log(chalk.yellow('\n 提示: 使用 atm list 查看账号列表'));
49
57
  } else {
50
58
  spinner.fail(chalk.red('激活失败: ' + (result.error || '未知错误')));
package/src/menu.js CHANGED
@@ -4,6 +4,7 @@ const fetch = require('node-fetch');
4
4
  const { config, writeFactoryAuth, getFactoryAuthPath } = require('./config');
5
5
  const api = require('./api');
6
6
  const daemon = require('./daemon');
7
+ const autostart = require('./autostart');
7
8
  const pkg = require('../package.json');
8
9
 
9
10
  let latestVersion = null;
@@ -79,6 +80,7 @@ async function showStatus() {
79
80
  console.log(chalk.gray(` 账号: ${tokens.length} 个可用`));
80
81
  console.log(chalk.gray(` 自动切换: ${autoSwitch ? '开启' : '关闭'}`));
81
82
  console.log(chalk.gray(` 后台服务: ${daemonStatus.running ? '运行中' : '未运行'}`));
83
+ console.log(chalk.gray(` 开机自启: ${autostart.isEnabled() ? '开启' : '关闭'}`));
82
84
  console.log();
83
85
 
84
86
  return tokens;
@@ -93,6 +95,10 @@ async function showStatus() {
93
95
  // 主菜单
94
96
  async function mainMenu() {
95
97
  clearScreen();
98
+
99
+ // 每次刷新菜单时检查新版本(后台执行,不阻塞)
100
+ checkNewVersion();
101
+
96
102
  showHeader();
97
103
 
98
104
  const tokens = await showStatus();
@@ -115,6 +121,13 @@ async function mainMenu() {
115
121
  choices.push({ name: '▶️ 启动后台服务', value: 'start' });
116
122
  }
117
123
 
124
+ // 开机自启动开关
125
+ if (autostart.isEnabled()) {
126
+ choices.push({ name: '🔕 关闭开机自启', value: 'autostart_off' });
127
+ } else {
128
+ choices.push({ name: '🔔 开启开机自启', value: 'autostart_on' });
129
+ }
130
+
118
131
  choices.push(new inquirer.Separator());
119
132
  choices.push({ name: '🚪 退出登录', value: 'logout' });
120
133
  }
@@ -482,6 +495,22 @@ async function menu() {
482
495
  case 'logout':
483
496
  await doLogout();
484
497
  break;
498
+ case 'autostart_on':
499
+ if (autostart.enable()) {
500
+ console.log(chalk.green('\n ✓ 已开启开机自启动\n'));
501
+ } else {
502
+ console.log(chalk.red('\n ✗ 设置失败\n'));
503
+ }
504
+ await pause();
505
+ break;
506
+ case 'autostart_off':
507
+ if (autostart.disable()) {
508
+ console.log(chalk.yellow('\n ✓ 已关闭开机自启动\n'));
509
+ } else {
510
+ console.log(chalk.red('\n ✗ 设置失败\n'));
511
+ }
512
+ await pause();
513
+ break;
485
514
  case 'update':
486
515
  await doUpdate();
487
516
  break;