polycopy 0.1.7 → 0.1.9

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/dist/cli.js CHANGED
@@ -3,7 +3,7 @@
3
3
  const child_process = require("child_process");
4
4
  const fs = require("fs");
5
5
  const path = require("path");
6
- const paths = require("./paths-CEjGES8j.js");
6
+ const processLock = require("./process-lock-y_yjnMCr.js");
7
7
  function _interopNamespace(e) {
8
8
  if (e && e.__esModule) return e;
9
9
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
@@ -23,44 +23,13 @@ function _interopNamespace(e) {
23
23
  }
24
24
  const fs__namespace = /* @__PURE__ */ _interopNamespace(fs);
25
25
  const path__namespace = /* @__PURE__ */ _interopNamespace(path);
26
- function ensurePidDir() {
27
- if (!fs__namespace.existsSync(paths.PID_DIR)) {
28
- fs__namespace.mkdirSync(paths.PID_DIR, { recursive: true });
29
- }
30
- }
31
- function getRunningPid() {
32
- if (!fs__namespace.existsSync(paths.PID_FILE)) {
33
- return null;
34
- }
35
- try {
36
- const pid = parseInt(fs__namespace.readFileSync(paths.PID_FILE, "utf-8").trim());
37
- process.kill(pid, 0);
38
- if (!isPolycopyProcess(pid)) {
39
- fs__namespace.unlinkSync(paths.PID_FILE);
40
- return null;
41
- }
42
- return pid;
43
- } catch {
44
- fs__namespace.unlinkSync(paths.PID_FILE);
45
- return null;
46
- }
47
- }
48
- function savePid(pid) {
49
- ensurePidDir();
50
- fs__namespace.writeFileSync(paths.PID_FILE, pid.toString());
51
- }
52
- function removePid() {
53
- if (fs__namespace.existsSync(paths.PID_FILE)) {
54
- fs__namespace.unlinkSync(paths.PID_FILE);
55
- }
56
- }
57
26
  function showHelp() {
58
27
  console.log(`
59
28
  PolyMarket 跟单机器人
60
29
 
61
30
  用法:
62
31
  polycopy [选项] 启动机器人
63
- polycopy stop 停止后台运行的机器人
32
+ polycopy stop 停止运行的机器人
64
33
  polycopy log 查看实时日志(Ctrl+C 退出)
65
34
  polycopy config 进入配置向导
66
35
 
@@ -82,93 +51,30 @@ function showVersion() {
82
51
  console.log(`polycopy v${pkg.version}`);
83
52
  }
84
53
  async function startForeground() {
85
- const runningPid = getRunningPid();
54
+ const runningPid = processLock.resolveRunningPid();
86
55
  if (runningPid) {
87
- console.log(`⚠️ 已有进程运行中 (PID: ${runningPid})`);
88
- console.log(` 使用 'polycopy stop' 停止后再启动`);
56
+ console.log(`⚠️ 程序正在运行中 (PID: ${runningPid})`);
57
+ console.log(` 请先停止程序后再启动`);
89
58
  process.exit(1);
90
59
  }
91
- savePid(process.pid);
92
- const cleanup = () => {
93
- removePid();
94
- };
95
- process.on("exit", cleanup);
96
- process.on("SIGINT", () => {
97
- cleanup();
98
- process.exit(0);
99
- });
100
- process.on("SIGTERM", () => {
101
- cleanup();
102
- process.exit(0);
103
- });
104
60
  const mainPath = path__namespace.join(__dirname, "index.js");
105
61
  await import(mainPath);
106
62
  }
107
63
  async function startDaemon() {
108
- const runningPid = getRunningPid();
64
+ const runningPid = processLock.resolveRunningPid();
109
65
  if (runningPid) {
110
- console.log(`⚠️ 已有进程运行中 (PID: ${runningPid})`);
111
- console.log(` 使用 'polycopy stop' 停止后再启动`);
66
+ console.log(`⚠️ 程序正在运行中 (PID: ${runningPid})`);
67
+ console.log(` 请先停止程序后再启动`);
112
68
  process.exit(1);
113
69
  }
114
70
  process.env.POLYCOPY_DAEMON = "1";
115
71
  const mainPath = path__namespace.join(__dirname, "index.js");
116
72
  await import(mainPath);
117
73
  }
118
- function isPolycopyProcess(pid) {
119
- if (process.platform === "win32") {
120
- return true;
121
- }
122
- const result = child_process.spawnSync("ps", ["-p", String(pid), "-o", "command="], {
123
- encoding: "utf-8"
124
- });
125
- if (result.status !== 0) {
126
- return false;
127
- }
128
- const command = result.stdout.trim();
129
- if (!command) {
130
- return false;
131
- }
132
- return command.includes(paths.DIST_INDEX) || command.includes(paths.DIST_CLI);
133
- }
134
- function findPolycopyPids() {
135
- if (process.platform === "win32") {
136
- return [];
137
- }
138
- const result = child_process.spawnSync("ps", ["-ax", "-o", "pid=,command="], {
139
- encoding: "utf-8"
140
- });
141
- if (result.status !== 0) {
142
- return [];
143
- }
144
- return result.stdout.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => {
145
- const firstSpace = line.indexOf(" ");
146
- if (firstSpace === -1) return null;
147
- const pidText = line.slice(0, firstSpace).trim();
148
- const command = line.slice(firstSpace + 1).trim();
149
- const pid = parseInt(pidText, 10);
150
- if (Number.isNaN(pid)) return null;
151
- if (pid === process.pid) return null;
152
- if (!(command.includes(paths.DIST_INDEX) || command.includes(paths.DIST_CLI))) {
153
- return null;
154
- }
155
- return pid;
156
- }).filter((pid) => pid !== null);
157
- }
158
74
  async function stopDaemon() {
159
- const pid = getRunningPid();
75
+ const pid = processLock.resolveRunningPid();
160
76
  if (!pid) {
161
- const fallbackPids = findPolycopyPids();
162
- if (fallbackPids.length === 0) {
163
- console.log("ℹ️ 没有运行中的前台/后台进程");
164
- return;
165
- }
166
- console.log(
167
- `⚠️ 未找到 PID 文件,尝试停止前台/后台进程 (${fallbackPids.length} 个)`
168
- );
169
- await Promise.all(
170
- fallbackPids.map((fallbackPid) => stopPid(fallbackPid))
171
- );
77
+ console.log("ℹ️ 没有运行中的前台/后台进程");
172
78
  return;
173
79
  }
174
80
  await stopPid(pid, true);
@@ -180,7 +86,7 @@ async function stopPid(pid, isPrimary = false) {
180
86
  } catch (error) {
181
87
  console.error(`❌ 停止失败 (PID: ${pid}):`, error);
182
88
  if (isPrimary) {
183
- removePid();
89
+ processLock.removePid();
184
90
  }
185
91
  return;
186
92
  }
@@ -192,7 +98,7 @@ async function stopPid(pid, isPrimary = false) {
192
98
  } catch {
193
99
  console.log("✅ 进程已停止");
194
100
  if (isPrimary) {
195
- removePid();
101
+ processLock.removePid();
196
102
  }
197
103
  return;
198
104
  }
@@ -204,29 +110,53 @@ async function stopPid(pid, isPrimary = false) {
204
110
  console.error(`❌ 强制终止失败 (PID: ${pid}):`, error);
205
111
  } finally {
206
112
  if (isPrimary) {
207
- removePid();
113
+ processLock.removePid();
208
114
  }
209
115
  }
210
116
  }
211
117
  async function runConfig() {
212
- const configPath = path__namespace.join(__dirname, "config.js");
213
- await import(configPath);
118
+ const runningPid = processLock.resolveRunningPid();
119
+ if (runningPid) {
120
+ console.log(`⚠️ 程序正在运行中 (PID: ${runningPid})`);
121
+ console.log(" 请先停止程序后再配置");
122
+ process.exit(1);
123
+ }
124
+ await processLock.initConfig();
125
+ process.exit(0);
214
126
  }
215
127
  function getLatestLogFile() {
216
- if (!fs__namespace.existsSync(paths.LOGS_DIR)) {
128
+ if (!fs__namespace.existsSync(processLock.LOGS_DIR)) {
217
129
  return null;
218
130
  }
219
- const files = fs__namespace.readdirSync(paths.LOGS_DIR).filter((f) => f.endsWith(".log")).sort().reverse();
220
- return files.length > 0 ? path__namespace.join(paths.LOGS_DIR, files[0]) : null;
131
+ const logFiles = fs__namespace.readdirSync(processLock.LOGS_DIR).filter(
132
+ (filename) => filename.startsWith("polycopy.") && filename.endsWith(".log")
133
+ ).map((filename) => path__namespace.join(processLock.LOGS_DIR, filename));
134
+ if (logFiles.length === 0) {
135
+ return null;
136
+ }
137
+ let latestFile = logFiles[0];
138
+ let latestTime = 0;
139
+ for (const filePath of logFiles) {
140
+ try {
141
+ const stat = fs__namespace.statSync(filePath);
142
+ if (stat.mtimeMs >= latestTime) {
143
+ latestTime = stat.mtimeMs;
144
+ latestFile = filePath;
145
+ }
146
+ } catch {
147
+ continue;
148
+ }
149
+ }
150
+ return latestFile;
221
151
  }
222
152
  function showLogs() {
223
- const runningPid = getRunningPid();
153
+ const runningPid = processLock.resolveRunningPid();
224
154
  if (!runningPid) {
225
155
  console.log("ℹ️ 没有运行中的后台进程");
226
156
  console.log(" 使用 'polycopy -d' 启动后台进程");
227
157
  return;
228
158
  }
229
- if (!fs__namespace.existsSync(paths.LOGS_DIR)) {
159
+ if (!fs__namespace.existsSync(processLock.LOGS_DIR)) {
230
160
  console.log("ℹ️ 日志目录不存在");
231
161
  return;
232
162
  }
@@ -247,23 +177,26 @@ function showLogs() {
247
177
  stdio: "inherit"
248
178
  }
249
179
  );
250
- const watcher = fs__namespace.watch(paths.LOGS_DIR, (eventType, filename) => {
251
- if (eventType === "rename" && filename?.endsWith(".log")) {
252
- const newLogFile = getLatestLogFile();
253
- if (newLogFile && newLogFile !== currentLogFile) {
254
- console.log(`
180
+ const watcher = fs__namespace.watch(
181
+ processLock.LOGS_DIR,
182
+ (eventType, filename) => {
183
+ if (eventType === "rename" && filename && filename.startsWith("polycopy.") && filename.endsWith(".log")) {
184
+ const newLogFile = getLatestLogFile();
185
+ if (newLogFile && newLogFile !== currentLogFile) {
186
+ console.log(`
255
187
  >>> 切换到新日志文件: ${newLogFile}
256
188
  `);
257
- currentLogFile = newLogFile;
258
- if (tail) {
259
- tail.kill();
189
+ currentLogFile = newLogFile;
190
+ if (tail) {
191
+ tail.kill();
192
+ }
193
+ tail = child_process.spawn("tail", ["-f", "-n", "10", currentLogFile], {
194
+ stdio: "inherit"
195
+ });
260
196
  }
261
- tail = child_process.spawn("tail", ["-f", "-n", "10", currentLogFile], {
262
- stdio: "inherit"
263
- });
264
197
  }
265
198
  }
266
- });
199
+ );
267
200
  const cleanup = () => {
268
201
  watcher.close();
269
202
  if (tail) {
@@ -305,7 +238,7 @@ async function main() {
305
238
  case void 0:
306
239
  case "start":
307
240
  if (args.includes("-d") || args.includes("--daemon")) {
308
- startDaemon();
241
+ await startDaemon();
309
242
  } else {
310
243
  await startForeground();
311
244
  }