cortico-world-hands 0.11.3 → 0.13.0
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/index.js +91 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -24,7 +24,10 @@ var HANDS_DEFAULTS = {
|
|
|
24
24
|
honchoSessionId: "yixin",
|
|
25
25
|
hookGrams: "three",
|
|
26
26
|
skinPackUrl: "",
|
|
27
|
-
qqOwner: ""
|
|
27
|
+
qqOwner: "",
|
|
28
|
+
mediaKeepDays: 1,
|
|
29
|
+
mediaCleanHour: 4,
|
|
30
|
+
mediaMaxMB: 0
|
|
28
31
|
};
|
|
29
32
|
var KEY_CODES = {
|
|
30
33
|
back: 4,
|
|
@@ -1093,6 +1096,15 @@ var Hands = class {
|
|
|
1093
1096
|
} catch {
|
|
1094
1097
|
}
|
|
1095
1098
|
}
|
|
1099
|
+
/** QQ 快速回复:不打开 QQ 也不抢屏。 */
|
|
1100
|
+
async qqReply(text, to) {
|
|
1101
|
+
const cfg = this.cfg();
|
|
1102
|
+
const credential = this.readToken();
|
|
1103
|
+
const t = credential ? `t=${encodeURIComponent(credential)}` : "";
|
|
1104
|
+
const toq = to ? `&to=${encodeURIComponent(to)}` : "";
|
|
1105
|
+
const res = await post(this.port(cfg.handPort), `/hand/qq/reply?${t}${toq}&text=${encodeURIComponent(text)}`, "", 2e4);
|
|
1106
|
+
return res.body.toString("utf8");
|
|
1107
|
+
}
|
|
1096
1108
|
/** 解锁锁屏:密码由主人放在本机文件里,这里只触发,不接触密码。 */
|
|
1097
1109
|
async unlockScreen() {
|
|
1098
1110
|
const cfg = this.cfg();
|
|
@@ -1488,6 +1500,30 @@ var HANDS_TOOL_DECLS = [
|
|
|
1488
1500
|
description: "\u770B\u624B\u81EA\u5DF1\u7684\u72B6\u6001\uFF1A\u8D70\u54EA\u6761\u901A\u9053\u3001\u901A\u4E0D\u901A\u3001\u8FD9\u4E00\u5206\u949F\u52A8\u4E86\u51E0\u4E2A\u52A8\u4F5C\u3001\u521A\u624D\u90A3\u4E00\u4E0B\u6210\u4E86\u6CA1\u6709\u3002\u5BF9\u65B9\u95EE\u300C\u624B\u80FD\u7528\u5417\u300D\u300C\u4F60\u521A\u624D\u70B9\u4E86\u4EC0\u4E48\u300D\u65F6\u7528\u5B83\u3002",
|
|
1489
1501
|
parameters: { type: "object", properties: {}, required: [] }
|
|
1490
1502
|
},
|
|
1503
|
+
{
|
|
1504
|
+
name: "qq_reply",
|
|
1505
|
+
tags: ["act"],
|
|
1506
|
+
description: "\u5728 QQ \u91CC\u7528\u300C\u5FEB\u901F\u56DE\u590D\u300D\u56DE\u4E00\u53E5\uFF08\u4E0D\u6253\u5F00 QQ\u3001\u4E0D\u62A2\u5C4F\uFF09\uFF1A\u7ED9\u8981\u56DE\u7684\u8BDD\uFF1Bto \u53EF\u9009\uFF0C\u586B\u5BF9\u8BDD\u6807\u9898\u7684\u4E00\u90E8\u5206\u7528\u6765\u6307\u5B9A\u56DE\u7ED9\u8C01\u3002\u901A\u77E5\u91CC\u6CA1\u6709\u5FEB\u901F\u56DE\u590D\u5165\u53E3\u65F6\u4F1A\u5931\u8D25\u5E76\u8BF4\u660E\u3002",
|
|
1507
|
+
parameters: {
|
|
1508
|
+
type: "object",
|
|
1509
|
+
properties: {
|
|
1510
|
+
text: { type: "string", description: "\u8981\u56DE\u7684\u8BDD" },
|
|
1511
|
+
to: { type: "string", description: "\u53EF\u9009\uFF1A\u5BF9\u8BDD\u6807\u9898\u91CC\u7684\u4E00\u6BB5\uFF0C\u6BD4\u5982\u7FA4\u540D\u6216\u4EBA\u540D" }
|
|
1512
|
+
},
|
|
1513
|
+
required: ["text"]
|
|
1514
|
+
}
|
|
1515
|
+
},
|
|
1516
|
+
{
|
|
1517
|
+
name: "media_clean",
|
|
1518
|
+
tags: ["act"],
|
|
1519
|
+
description: "\u6E05\u7406\u5C4F\u5E55\u622A\u56FE\u9644\u4EF6\uFF1A\u5220\u6389 data/media \u91CC\u8D85\u8FC7\u6307\u5B9A\u5929\u6570\u7684\u56FE\uFF0C\u987A\u4FBF\u62A5\u91CA\u653E\u4E86\u591A\u5C11\u7A7A\u95F4\u3002\u9ED8\u8BA4\u6309\u914D\u7F6E\uFF08\u4FDD\u7559 1 \u5929\uFF09\u3002",
|
|
1520
|
+
parameters: {
|
|
1521
|
+
type: "object",
|
|
1522
|
+
properties: {
|
|
1523
|
+
days: { type: "integer", description: "\u4FDD\u7559\u6700\u8FD1\u51E0\u5929\uFF0C\u9ED8\u8BA4\u8BFB\u914D\u7F6E\uFF081 \u5929\uFF09\uFF1B\u586B 0 \u8868\u793A\u5168\u6E05" }
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
},
|
|
1491
1527
|
{
|
|
1492
1528
|
name: "screen_wake",
|
|
1493
1529
|
tags: ["act"],
|
|
@@ -1740,6 +1776,8 @@ var HandsWorld = class {
|
|
|
1740
1776
|
lastDiaryDay = "";
|
|
1741
1777
|
mineTimer = null;
|
|
1742
1778
|
qqTimer = null;
|
|
1779
|
+
mediaTimer = null;
|
|
1780
|
+
lastMediaDay = "";
|
|
1743
1781
|
cursor = 0;
|
|
1744
1782
|
lastHitKey = "";
|
|
1745
1783
|
opts;
|
|
@@ -1780,6 +1818,9 @@ var HandsWorld = class {
|
|
|
1780
1818
|
this.mineTimer = setInterval(() => {
|
|
1781
1819
|
void this.pushMineNudge();
|
|
1782
1820
|
}, 3 * 60 * 60 * 1e3);
|
|
1821
|
+
this.mediaTimer = setInterval(() => {
|
|
1822
|
+
void this.maybeCleanMedia();
|
|
1823
|
+
}, 30 * 60 * 1e3);
|
|
1783
1824
|
this.qqTimer = setInterval(() => {
|
|
1784
1825
|
void this.pollQq();
|
|
1785
1826
|
}, 5e3);
|
|
@@ -1792,6 +1833,7 @@ var HandsWorld = class {
|
|
|
1792
1833
|
if (this.mineTimer) clearInterval(this.mineTimer);
|
|
1793
1834
|
if (this.dailyDiaryTimer) clearInterval(this.dailyDiaryTimer);
|
|
1794
1835
|
if (this.qqTimer) clearInterval(this.qqTimer);
|
|
1836
|
+
if (this.mediaTimer) clearInterval(this.mediaTimer);
|
|
1795
1837
|
this.pollTimer = null;
|
|
1796
1838
|
this.mineTimer = null;
|
|
1797
1839
|
}
|
|
@@ -1877,6 +1919,27 @@ ${lines.join("\n")}
|
|
|
1877
1919
|
} catch {
|
|
1878
1920
|
}
|
|
1879
1921
|
}
|
|
1922
|
+
/** 钩子 6:到点把 data/media 里过期的附件删掉。 */
|
|
1923
|
+
async maybeCleanMedia() {
|
|
1924
|
+
const cfg = this.opts.cfg;
|
|
1925
|
+
const keepDays = cfg.mediaKeepDays ?? 1;
|
|
1926
|
+
const hour = cfg.mediaCleanHour ?? 4;
|
|
1927
|
+
const now = /* @__PURE__ */ new Date();
|
|
1928
|
+
if (now.getHours() !== hour) return;
|
|
1929
|
+
const day = now.toISOString().slice(0, 10);
|
|
1930
|
+
if (this.lastMediaDay === day) return;
|
|
1931
|
+
const dir = this.mediaDir();
|
|
1932
|
+
if (!dir) return;
|
|
1933
|
+
this.lastMediaDay = day;
|
|
1934
|
+
const r = cleanMedia(dir, { keepDays, maxMB: cfg.mediaMaxMB ?? 0 });
|
|
1935
|
+
this.log?.info(`\u9644\u4EF6\u6E05\u7406\uFF1A\u5220 ${r.removed} \u4E2A\uFF0C\u91CA\u653E ${r.freedMB}MB\uFF0C\u5269 ${r.kept} \u4E2A`);
|
|
1936
|
+
}
|
|
1937
|
+
mediaDir() {
|
|
1938
|
+
const base = this.opts.dataDir;
|
|
1939
|
+
if (!base) return null;
|
|
1940
|
+
const dir = base.endsWith("/data") ? join(base, "media") : join(base, "data", "media");
|
|
1941
|
+
return dir;
|
|
1942
|
+
}
|
|
1880
1943
|
/** 钩子 5:QQ 在后台收到的消息,原样递给她;谁来的一眼能看清。 */
|
|
1881
1944
|
async pollQq() {
|
|
1882
1945
|
if (!this.host) return;
|
|
@@ -1994,8 +2057,12 @@ ${lines.join("\n")}
|
|
|
1994
2057
|
return await this.diaryRead(args);
|
|
1995
2058
|
case "skin_install":
|
|
1996
2059
|
return await this.skinInstall(args);
|
|
2060
|
+
case "media_clean":
|
|
2061
|
+
return await this.mediaClean(args);
|
|
1997
2062
|
case "screen_wake":
|
|
1998
2063
|
return await this.screenWake();
|
|
2064
|
+
case "qq_reply":
|
|
2065
|
+
return await this.qqReply(args);
|
|
1999
2066
|
case "screen_unlock":
|
|
2000
2067
|
return await this.screenUnlock();
|
|
2001
2068
|
case "screen_sleep":
|
|
@@ -2137,6 +2204,20 @@ ${lines.join("\n")}
|
|
|
2137
2204
|
return failed(raw.slice(0, 120));
|
|
2138
2205
|
}
|
|
2139
2206
|
}
|
|
2207
|
+
/** 在 QQ 里回一句(快速回复,不抢屏)。 */
|
|
2208
|
+
async qqReply(args) {
|
|
2209
|
+
const text = typeof args.text === "string" ? args.text.trim() : "";
|
|
2210
|
+
if (!text) return failed("\u8981\u56DE\u4EC0\u4E48\uFF1F");
|
|
2211
|
+
const to = typeof args.to === "string" ? args.to.trim() : "";
|
|
2212
|
+
const raw = await this.hands.qqReply(text, to || void 0);
|
|
2213
|
+
try {
|
|
2214
|
+
const r = JSON.parse(raw);
|
|
2215
|
+
if (r.ok) return `\u56DE\u4E86${r.to ? "\u7ED9\u300C" + r.to + "\u300D" : ""}\uFF1A${text}`;
|
|
2216
|
+
return failed(r.error || "\u6CA1\u56DE\u51FA\u53BB");
|
|
2217
|
+
} catch {
|
|
2218
|
+
return failed(raw.slice(0, 120));
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2140
2221
|
/** 解锁:成功/没锁/失败都给人话。 */
|
|
2141
2222
|
async screenUnlock() {
|
|
2142
2223
|
const raw = await this.hands.unlockScreen();
|
|
@@ -2190,6 +2271,14 @@ ${lines.join("\n")}
|
|
|
2190
2271
|
const r = await installSkinPack(url, this.skinRoots(), this.log);
|
|
2191
2272
|
return r.ok ? r.detail : failed(r.detail);
|
|
2192
2273
|
}
|
|
2274
|
+
/** 手动清一次附件。 */
|
|
2275
|
+
async mediaClean(args) {
|
|
2276
|
+
const dir = this.mediaDir();
|
|
2277
|
+
if (!dir) return failed("\u4E0D\u77E5\u9053\u9644\u4EF6\u76EE\u5F55\u5728\u54EA");
|
|
2278
|
+
const keepDays = args.days === void 0 ? this.opts.cfg.mediaKeepDays ?? 1 : Math.max(0, Math.round(Number(args.days)));
|
|
2279
|
+
const r = cleanMedia(dir, { keepDays, maxMB: this.opts.cfg.mediaMaxMB ?? 0 });
|
|
2280
|
+
return `\u5220\u4E86 ${r.removed} \u4E2A\u9644\u4EF6\uFF0C\u91CA\u653E ${r.freedMB}MB\uFF0C\u8FD8\u5269 ${r.kept} \u4E2A\u3002`;
|
|
2281
|
+
}
|
|
2193
2282
|
skinRoots() {
|
|
2194
2283
|
const roots = [...this.opts.roots || []];
|
|
2195
2284
|
try {
|
|
@@ -2484,7 +2573,7 @@ function handsDefinition() {
|
|
|
2484
2573
|
id: HANDS_ID,
|
|
2485
2574
|
label: "\u624B",
|
|
2486
2575
|
defaults: () => structuredClone(HANDS_DEFAULTS),
|
|
2487
|
-
create: (ctx) => new HandsWorld({ cfg: ctx.cfg, timezone: ctx.timezone, roots: [ctx.botDir, ctx.dataDir, ctx.repoRoot, ctx.packageDir] })
|
|
2576
|
+
create: (ctx) => new HandsWorld({ cfg: ctx.cfg, timezone: ctx.timezone, roots: [ctx.botDir, ctx.dataDir, ctx.repoRoot, ctx.packageDir], dataDir: ctx.dataDir })
|
|
2488
2577
|
};
|
|
2489
2578
|
}
|
|
2490
2579
|
var HANDS = handsDefinition();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cortico-world-hands",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Cortico World: hands for the desktop pet — looks at the phone screen, then taps, swipes, pinches, drags, types and presses keys through whatever actuator the device actually has",
|
|
6
6
|
"license": "MIT",
|