polycopy 0.1.7 → 0.1.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/dist/cli.js +60 -127
- package/dist/index.js +292 -148
- package/dist/{init-Bs-N_AZi.js → process-lock-BbFF27h8.js} +183 -220
- package/package.json +4 -5
- package/dist/config.js +0 -13
- package/dist/paths-CEjGES8j.js +0 -20
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
|
|
6
|
+
const processLock = require("./process-lock-BbFF27h8.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 =
|
|
54
|
+
const runningPid = processLock.resolveRunningPid();
|
|
86
55
|
if (runningPid) {
|
|
87
|
-
console.log(`⚠️
|
|
88
|
-
console.log(`
|
|
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 =
|
|
64
|
+
const runningPid = processLock.resolveRunningPid();
|
|
109
65
|
if (runningPid) {
|
|
110
|
-
console.log(`⚠️
|
|
111
|
-
console.log(`
|
|
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 =
|
|
75
|
+
const pid = processLock.resolveRunningPid();
|
|
160
76
|
if (!pid) {
|
|
161
|
-
|
|
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
|
|
213
|
-
|
|
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(
|
|
128
|
+
if (!fs__namespace.existsSync(processLock.LOGS_DIR)) {
|
|
217
129
|
return null;
|
|
218
130
|
}
|
|
219
|
-
const
|
|
220
|
-
|
|
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 =
|
|
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(
|
|
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(
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
if (
|
|
254
|
-
|
|
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
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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
|
}
|