polycopy 0.0.1
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 +274 -0
- package/dist/config.js +13 -0
- package/dist/index.js +1048 -0
- package/dist/init-C8vHJzZn.js +932 -0
- package/package.json +41 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
const child_process = require("child_process");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
function _interopNamespace(e) {
|
|
7
|
+
if (e && e.__esModule) return e;
|
|
8
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
9
|
+
if (e) {
|
|
10
|
+
for (const k in e) {
|
|
11
|
+
if (k !== "default") {
|
|
12
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
13
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: () => e[k]
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
n.default = e;
|
|
21
|
+
return Object.freeze(n);
|
|
22
|
+
}
|
|
23
|
+
const fs__namespace = /* @__PURE__ */ _interopNamespace(fs);
|
|
24
|
+
const path__namespace = /* @__PURE__ */ _interopNamespace(path);
|
|
25
|
+
const PID_DIR = path__namespace.join(process.env.HOME || process.cwd(), ".polycopy");
|
|
26
|
+
const PID_FILE = path__namespace.join(PID_DIR, "polycopy.pid");
|
|
27
|
+
const LOGS_DIR = path__namespace.join(process.cwd(), "logs");
|
|
28
|
+
function ensurePidDir() {
|
|
29
|
+
if (!fs__namespace.existsSync(PID_DIR)) {
|
|
30
|
+
fs__namespace.mkdirSync(PID_DIR, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function getRunningPid() {
|
|
34
|
+
if (!fs__namespace.existsSync(PID_FILE)) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const pid = parseInt(fs__namespace.readFileSync(PID_FILE, "utf-8").trim());
|
|
39
|
+
process.kill(pid, 0);
|
|
40
|
+
return pid;
|
|
41
|
+
} catch {
|
|
42
|
+
fs__namespace.unlinkSync(PID_FILE);
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function savePid(pid) {
|
|
47
|
+
ensurePidDir();
|
|
48
|
+
fs__namespace.writeFileSync(PID_FILE, pid.toString());
|
|
49
|
+
}
|
|
50
|
+
function removePid() {
|
|
51
|
+
if (fs__namespace.existsSync(PID_FILE)) {
|
|
52
|
+
fs__namespace.unlinkSync(PID_FILE);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function showHelp() {
|
|
56
|
+
console.log(`
|
|
57
|
+
PolyMarket 跟单机器人
|
|
58
|
+
|
|
59
|
+
用法:
|
|
60
|
+
polycopy [选项] 启动机器人
|
|
61
|
+
polycopy stop 停止后台运行的机器人
|
|
62
|
+
polycopy log 查看实时日志(Ctrl+C 退出)
|
|
63
|
+
polycopy config 进入配置向导
|
|
64
|
+
|
|
65
|
+
选项:
|
|
66
|
+
-d, --daemon 后台运行(守护进程模式)
|
|
67
|
+
-h, --help 显示帮助信息
|
|
68
|
+
-v, --version 显示版本号
|
|
69
|
+
|
|
70
|
+
示例:
|
|
71
|
+
polycopy 前台运行,按 Ctrl+C 退出
|
|
72
|
+
polycopy -d 后台运行
|
|
73
|
+
polycopy stop 停止后台运行
|
|
74
|
+
polycopy log 查看后台进程的实时日志
|
|
75
|
+
polycopy config 配置 Bot Token、交易参数等
|
|
76
|
+
`);
|
|
77
|
+
}
|
|
78
|
+
function showVersion() {
|
|
79
|
+
const packagePath = path__namespace.join(__dirname, "..", "package.json");
|
|
80
|
+
try {
|
|
81
|
+
const pkg = JSON.parse(fs__namespace.readFileSync(packagePath, "utf-8"));
|
|
82
|
+
console.log(`polycopy v${pkg.version}`);
|
|
83
|
+
} catch {
|
|
84
|
+
console.log("polycopy v1.0.0");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async function startForeground() {
|
|
88
|
+
const runningPid = getRunningPid();
|
|
89
|
+
if (runningPid) {
|
|
90
|
+
console.log(`⚠️ 已有进程运行中 (PID: ${runningPid})`);
|
|
91
|
+
console.log(` 使用 'polycopy stop' 停止后再启动`);
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
savePid(process.pid);
|
|
95
|
+
const cleanup = () => {
|
|
96
|
+
removePid();
|
|
97
|
+
};
|
|
98
|
+
process.on("exit", cleanup);
|
|
99
|
+
process.on("SIGINT", () => {
|
|
100
|
+
cleanup();
|
|
101
|
+
process.exit(0);
|
|
102
|
+
});
|
|
103
|
+
process.on("SIGTERM", () => {
|
|
104
|
+
cleanup();
|
|
105
|
+
process.exit(0);
|
|
106
|
+
});
|
|
107
|
+
const mainPath = path__namespace.join(__dirname, "index.js");
|
|
108
|
+
await import(mainPath);
|
|
109
|
+
}
|
|
110
|
+
function startDaemon() {
|
|
111
|
+
const runningPid = getRunningPid();
|
|
112
|
+
if (runningPid) {
|
|
113
|
+
console.log(`⚠️ 已有进程运行中 (PID: ${runningPid})`);
|
|
114
|
+
console.log(` 使用 'polycopy stop' 停止后再启动`);
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
ensurePidDir();
|
|
118
|
+
const mainPath = path__namespace.join(__dirname, "index.js");
|
|
119
|
+
const child = child_process.spawn(process.execPath, [mainPath], {
|
|
120
|
+
detached: true,
|
|
121
|
+
stdio: "ignore",
|
|
122
|
+
env: { ...process.env, POLYCOPY_DAEMON: "1" }
|
|
123
|
+
});
|
|
124
|
+
if (child.pid) {
|
|
125
|
+
savePid(child.pid);
|
|
126
|
+
console.log(`✅ 已在后台启动 (PID: ${child.pid})`);
|
|
127
|
+
console.log(` 日志目录: ${LOGS_DIR}`);
|
|
128
|
+
console.log(` 使用 'polycopy stop' 停止`);
|
|
129
|
+
child.unref();
|
|
130
|
+
process.exit(0);
|
|
131
|
+
} else {
|
|
132
|
+
console.error("❌ 启动失败");
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function stopDaemon() {
|
|
137
|
+
const pid = getRunningPid();
|
|
138
|
+
if (!pid) {
|
|
139
|
+
console.log("ℹ️ 没有运行中的后台进程");
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
process.kill(pid, "SIGTERM");
|
|
144
|
+
console.log(`✅ 已发送停止信号 (PID: ${pid})`);
|
|
145
|
+
let attempts = 0;
|
|
146
|
+
const checkInterval = setInterval(() => {
|
|
147
|
+
attempts++;
|
|
148
|
+
try {
|
|
149
|
+
process.kill(pid, 0);
|
|
150
|
+
if (attempts >= 10) {
|
|
151
|
+
process.kill(pid, "SIGKILL");
|
|
152
|
+
console.log("⚠️ 进程未响应,已强制终止");
|
|
153
|
+
clearInterval(checkInterval);
|
|
154
|
+
removePid();
|
|
155
|
+
}
|
|
156
|
+
} catch {
|
|
157
|
+
console.log("✅ 进程已停止");
|
|
158
|
+
clearInterval(checkInterval);
|
|
159
|
+
removePid();
|
|
160
|
+
}
|
|
161
|
+
}, 500);
|
|
162
|
+
} catch (error) {
|
|
163
|
+
console.error("❌ 停止失败:", error);
|
|
164
|
+
removePid();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
async function runConfig() {
|
|
168
|
+
const configPath = path__namespace.join(__dirname, "config.js");
|
|
169
|
+
await import(configPath);
|
|
170
|
+
}
|
|
171
|
+
function getLatestLogFile() {
|
|
172
|
+
if (!fs__namespace.existsSync(LOGS_DIR)) {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
const files = fs__namespace.readdirSync(LOGS_DIR).filter((f) => f.endsWith(".log")).sort().reverse();
|
|
176
|
+
return files.length > 0 ? path__namespace.join(LOGS_DIR, files[0]) : null;
|
|
177
|
+
}
|
|
178
|
+
function showLogs() {
|
|
179
|
+
const runningPid = getRunningPid();
|
|
180
|
+
if (!runningPid) {
|
|
181
|
+
console.log("ℹ️ 没有运行中的后台进程");
|
|
182
|
+
console.log(" 使用 'polycopy -d' 启动后台进程");
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (!fs__namespace.existsSync(LOGS_DIR)) {
|
|
186
|
+
console.log("ℹ️ 日志目录不存在");
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
let currentLogFile = getLatestLogFile();
|
|
190
|
+
if (!currentLogFile) {
|
|
191
|
+
console.log("ℹ️ 没有日志文件");
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
console.log(`📋 后台进程 PID: ${runningPid}`);
|
|
195
|
+
console.log(` 按 Ctrl+C 退出
|
|
196
|
+
`);
|
|
197
|
+
console.log(`>>> 日志文件: ${currentLogFile}
|
|
198
|
+
`);
|
|
199
|
+
let tail = child_process.spawn("tail", ["-f", "-n", "100", currentLogFile], {
|
|
200
|
+
stdio: "inherit"
|
|
201
|
+
});
|
|
202
|
+
const watcher = fs__namespace.watch(LOGS_DIR, (eventType, filename) => {
|
|
203
|
+
if (eventType === "rename" && filename?.endsWith(".log")) {
|
|
204
|
+
const newLogFile = getLatestLogFile();
|
|
205
|
+
if (newLogFile && newLogFile !== currentLogFile) {
|
|
206
|
+
console.log(`
|
|
207
|
+
>>> 切换到新日志文件: ${newLogFile}
|
|
208
|
+
`);
|
|
209
|
+
currentLogFile = newLogFile;
|
|
210
|
+
if (tail) {
|
|
211
|
+
tail.kill();
|
|
212
|
+
}
|
|
213
|
+
tail = child_process.spawn("tail", ["-f", "-n", "10", currentLogFile], {
|
|
214
|
+
stdio: "inherit"
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
const cleanup = () => {
|
|
220
|
+
watcher.close();
|
|
221
|
+
if (tail) {
|
|
222
|
+
tail.kill();
|
|
223
|
+
}
|
|
224
|
+
process.exit(0);
|
|
225
|
+
};
|
|
226
|
+
process.on("SIGINT", cleanup);
|
|
227
|
+
process.on("SIGTERM", cleanup);
|
|
228
|
+
}
|
|
229
|
+
async function main() {
|
|
230
|
+
const args = process.argv.slice(2);
|
|
231
|
+
const command = args[0];
|
|
232
|
+
switch (command) {
|
|
233
|
+
case "stop":
|
|
234
|
+
stopDaemon();
|
|
235
|
+
break;
|
|
236
|
+
case "log":
|
|
237
|
+
case "logs":
|
|
238
|
+
showLogs();
|
|
239
|
+
break;
|
|
240
|
+
case "config":
|
|
241
|
+
await runConfig();
|
|
242
|
+
break;
|
|
243
|
+
case "-h":
|
|
244
|
+
case "--help":
|
|
245
|
+
case "help":
|
|
246
|
+
showHelp();
|
|
247
|
+
break;
|
|
248
|
+
case "-v":
|
|
249
|
+
case "--version":
|
|
250
|
+
case "version":
|
|
251
|
+
showVersion();
|
|
252
|
+
break;
|
|
253
|
+
case "-d":
|
|
254
|
+
case "--daemon":
|
|
255
|
+
startDaemon();
|
|
256
|
+
break;
|
|
257
|
+
case void 0:
|
|
258
|
+
case "start":
|
|
259
|
+
if (args.includes("-d") || args.includes("--daemon")) {
|
|
260
|
+
startDaemon();
|
|
261
|
+
} else {
|
|
262
|
+
await startForeground();
|
|
263
|
+
}
|
|
264
|
+
break;
|
|
265
|
+
default:
|
|
266
|
+
console.error(`未知命令: ${command}`);
|
|
267
|
+
console.log(`使用 'polycopy -h' 查看帮助`);
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
main().catch((error) => {
|
|
272
|
+
console.error("程序错误:", error);
|
|
273
|
+
process.exit(1);
|
|
274
|
+
});
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const init = require("./init-C8vHJzZn.js");
|
|
3
|
+
async function main() {
|
|
4
|
+
try {
|
|
5
|
+
await init.runConfigWizard();
|
|
6
|
+
init.logger.success("配置完成!");
|
|
7
|
+
process.exit(0);
|
|
8
|
+
} catch (error) {
|
|
9
|
+
init.logger.error("配置过程中出错:", error);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
main();
|