@ycodium-ai/plugin-im 0.2.3202 → 0.2.3208
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/assets/ui.js +1 -1
- package/dist/index.js +399 -220
- package/locales/en.json +1 -0
- package/locales/zh-CN.json +1 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -137,7 +137,7 @@ var require_punycode = __commonJS({
|
|
|
137
137
|
}
|
|
138
138
|
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
|
|
139
139
|
};
|
|
140
|
-
var
|
|
140
|
+
var decode3 = function(input) {
|
|
141
141
|
const output = [];
|
|
142
142
|
const inputLength = input.length;
|
|
143
143
|
let i = 0;
|
|
@@ -249,7 +249,7 @@ var require_punycode = __commonJS({
|
|
|
249
249
|
};
|
|
250
250
|
var toUnicode = function(input) {
|
|
251
251
|
return mapDomain(input, function(string) {
|
|
252
|
-
return regexPunycode.test(string) ?
|
|
252
|
+
return regexPunycode.test(string) ? decode3(string.slice(4).toLowerCase()) : string;
|
|
253
253
|
});
|
|
254
254
|
};
|
|
255
255
|
var toASCII = function(input) {
|
|
@@ -275,7 +275,7 @@ var require_punycode = __commonJS({
|
|
|
275
275
|
"decode": ucs2decode,
|
|
276
276
|
"encode": ucs2encode
|
|
277
277
|
},
|
|
278
|
-
"decode":
|
|
278
|
+
"decode": decode3,
|
|
279
279
|
"encode": encode2,
|
|
280
280
|
"toASCII": toASCII,
|
|
281
281
|
"toUnicode": toUnicode
|
|
@@ -18475,7 +18475,7 @@ var require_utils = __commonJS({
|
|
|
18475
18475
|
return acc;
|
|
18476
18476
|
}, target2);
|
|
18477
18477
|
};
|
|
18478
|
-
var
|
|
18478
|
+
var decode3 = function(str2, defaultDecoder, charset) {
|
|
18479
18479
|
var strWithoutPlus = str2.replace(/\+/g, " ");
|
|
18480
18480
|
if (charset === "iso-8859-1") {
|
|
18481
18481
|
return strWithoutPlus.replace(/%[0-9a-f]{2}/gi, unescape);
|
|
@@ -18601,7 +18601,7 @@ var require_utils = __commonJS({
|
|
|
18601
18601
|
assign,
|
|
18602
18602
|
combine,
|
|
18603
18603
|
compact,
|
|
18604
|
-
decode:
|
|
18604
|
+
decode: decode3,
|
|
18605
18605
|
encode: encode2,
|
|
18606
18606
|
isBuffer,
|
|
18607
18607
|
isOverflow,
|
|
@@ -23360,7 +23360,7 @@ var require_websocket = __commonJS({
|
|
|
23360
23360
|
var http = __require("http");
|
|
23361
23361
|
var net = __require("net");
|
|
23362
23362
|
var tls = __require("tls");
|
|
23363
|
-
var { randomBytes, createHash:
|
|
23363
|
+
var { randomBytes, createHash: createHash7 } = __require("crypto");
|
|
23364
23364
|
var { Duplex, Readable } = __require("stream");
|
|
23365
23365
|
var { URL: URL2 } = __require("url");
|
|
23366
23366
|
var PerMessageDeflate = require_permessage_deflate();
|
|
@@ -24028,7 +24028,7 @@ var require_websocket = __commonJS({
|
|
|
24028
24028
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
24029
24029
|
return;
|
|
24030
24030
|
}
|
|
24031
|
-
const digest =
|
|
24031
|
+
const digest = createHash7("sha1").update(key + GUID).digest("base64");
|
|
24032
24032
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
24033
24033
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
24034
24034
|
return;
|
|
@@ -24397,7 +24397,7 @@ var require_websocket_server = __commonJS({
|
|
|
24397
24397
|
var EventEmitter = __require("events");
|
|
24398
24398
|
var http = __require("http");
|
|
24399
24399
|
var { Duplex } = __require("stream");
|
|
24400
|
-
var { createHash:
|
|
24400
|
+
var { createHash: createHash7 } = __require("crypto");
|
|
24401
24401
|
var extension = require_extension();
|
|
24402
24402
|
var PerMessageDeflate = require_permessage_deflate();
|
|
24403
24403
|
var subprotocol = require_subprotocol();
|
|
@@ -24704,7 +24704,7 @@ var require_websocket_server = __commonJS({
|
|
|
24704
24704
|
);
|
|
24705
24705
|
}
|
|
24706
24706
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
24707
|
-
const digest =
|
|
24707
|
+
const digest = createHash7("sha1").update(key + GUID).digest("base64");
|
|
24708
24708
|
const headers = [
|
|
24709
24709
|
"HTTP/1.1 101 Switching Protocols",
|
|
24710
24710
|
"Upgrade: websocket",
|
|
@@ -24912,7 +24912,7 @@ var require_base64 = __commonJS({
|
|
|
24912
24912
|
return String.fromCharCode.apply(String, chunk.slice(0, i2));
|
|
24913
24913
|
};
|
|
24914
24914
|
var invalidEncoding = "invalid encoding";
|
|
24915
|
-
base64.decode = function
|
|
24915
|
+
base64.decode = function decode3(string, buffer, offset) {
|
|
24916
24916
|
var start = offset;
|
|
24917
24917
|
var j = 0, t;
|
|
24918
24918
|
for (var i2 = 0; i2 < string.length; ) {
|
|
@@ -121305,7 +121305,7 @@ var require_lib2 = __commonJS({
|
|
|
121305
121305
|
Header.encodeDelimited = function encodeDelimited(message, writer) {
|
|
121306
121306
|
return this.encode(message, writer).ldelim();
|
|
121307
121307
|
};
|
|
121308
|
-
Header.decode = function
|
|
121308
|
+
Header.decode = function decode4(reader, length) {
|
|
121309
121309
|
if (!(reader instanceof $Reader))
|
|
121310
121310
|
reader = $Reader.create(reader);
|
|
121311
121311
|
let end = length === void 0 ? reader.len : reader.pos + length, message = new $root.pbbp2.Header();
|
|
@@ -121451,7 +121451,7 @@ var require_lib2 = __commonJS({
|
|
|
121451
121451
|
Frame.encodeDelimited = function encodeDelimited(message, writer) {
|
|
121452
121452
|
return this.encode(message, writer).ldelim();
|
|
121453
121453
|
};
|
|
121454
|
-
Frame.decode = function
|
|
121454
|
+
Frame.decode = function decode4(reader, length) {
|
|
121455
121455
|
if (!(reader instanceof $Reader))
|
|
121456
121456
|
reader = $Reader.create(reader);
|
|
121457
121457
|
let end = length === void 0 ? reader.len : reader.pos + length, message = new $root.pbbp2.Frame();
|
|
@@ -121678,7 +121678,7 @@ var require_lib2 = __commonJS({
|
|
|
121678
121678
|
})();
|
|
121679
121679
|
return pbbp22;
|
|
121680
121680
|
})();
|
|
121681
|
-
var
|
|
121681
|
+
var decode3 = (buffer) => {
|
|
121682
121682
|
return pbbp2.Frame.decode(buffer);
|
|
121683
121683
|
};
|
|
121684
121684
|
var WSConfig = class {
|
|
@@ -122177,7 +122177,7 @@ var require_lib2 = __commonJS({
|
|
|
122177
122177
|
const wsInstance = this.wsConfig.getWSInstance();
|
|
122178
122178
|
wsInstance === null || wsInstance === void 0 ? void 0 : wsInstance.on("message", (buffer) => __awaiter(this, void 0, void 0, function* () {
|
|
122179
122179
|
this.clearLiveness();
|
|
122180
|
-
const data =
|
|
122180
|
+
const data = decode3(buffer);
|
|
122181
122181
|
const { method } = data;
|
|
122182
122182
|
if (method === FrameType.control) {
|
|
122183
122183
|
yield this.handleControlData(data);
|
|
@@ -127416,6 +127416,31 @@ var makeChatQueue = (core) => {
|
|
|
127416
127416
|
// src/chatSetup.ts
|
|
127417
127417
|
import { threadOrNull } from "@ycodium-ai/plugin-api";
|
|
127418
127418
|
|
|
127419
|
+
// src/cooldown.ts
|
|
127420
|
+
var makeCooldown = (windowMs, now, maxKeys = Number.POSITIVE_INFINITY) => {
|
|
127421
|
+
const lastAt = /* @__PURE__ */ new Map();
|
|
127422
|
+
return {
|
|
127423
|
+
tryAcquire: (key) => {
|
|
127424
|
+
const current = now();
|
|
127425
|
+
const previous = lastAt.get(key);
|
|
127426
|
+
if (previous !== void 0 && current - previous < windowMs) return false;
|
|
127427
|
+
lastAt.delete(key);
|
|
127428
|
+
lastAt.set(key, current);
|
|
127429
|
+
if (lastAt.size > maxKeys) {
|
|
127430
|
+
for (const [candidate, at] of lastAt) {
|
|
127431
|
+
if (current - at >= windowMs) lastAt.delete(candidate);
|
|
127432
|
+
}
|
|
127433
|
+
while (lastAt.size > maxKeys) {
|
|
127434
|
+
const oldest = lastAt.keys().next().value;
|
|
127435
|
+
if (oldest === void 0) break;
|
|
127436
|
+
lastAt.delete(oldest);
|
|
127437
|
+
}
|
|
127438
|
+
}
|
|
127439
|
+
return true;
|
|
127440
|
+
}
|
|
127441
|
+
};
|
|
127442
|
+
};
|
|
127443
|
+
|
|
127419
127444
|
// src/projectList.ts
|
|
127420
127445
|
var PROJECT_LIST_MAX = 20;
|
|
127421
127446
|
var projectLine = (row, position) => `${String(position)}. ${row.title.replace(/\s+/g, " ").trim()}${row.current ? " \u2605" : ""}`;
|
|
@@ -127504,16 +127529,21 @@ var pickSession = (arg, listed, rows) => {
|
|
|
127504
127529
|
var makeChatSetup = (core, deps) => {
|
|
127505
127530
|
const { host, t, adapterFor, commit, deliver, bindingOf: bindingOf2, hasPanel } = core;
|
|
127506
127531
|
const { projectRowsFor, listedProjectsByChat } = deps.rows;
|
|
127507
|
-
const
|
|
127508
|
-
|
|
127509
|
-
|
|
127532
|
+
const pendingMessages = makeBoundedMap(100);
|
|
127533
|
+
const projectPromptCooldown = makeCooldown(3e4, () => Date.now());
|
|
127534
|
+
const loadProjectRows = async (binding) => {
|
|
127510
127535
|
try {
|
|
127511
|
-
|
|
127536
|
+
return await projectRowsFor(chatKeyOf(binding));
|
|
127512
127537
|
} catch (error) {
|
|
127513
127538
|
host.log.warn("chat could not list the projects", { error: describeError(error) });
|
|
127514
127539
|
await deliver(binding, t("panel.loadFailed"));
|
|
127515
|
-
return;
|
|
127540
|
+
return null;
|
|
127516
127541
|
}
|
|
127542
|
+
};
|
|
127543
|
+
const promptProject = async (binding, available) => {
|
|
127544
|
+
const chatKey = chatKeyOf(binding);
|
|
127545
|
+
const rows = available ?? await loadProjectRows(binding);
|
|
127546
|
+
if (rows === null) return;
|
|
127517
127547
|
listedProjectsByChat.set(chatKey, listedProjectIds(rows));
|
|
127518
127548
|
if (rows.length > 0 && hasPanel(binding)) {
|
|
127519
127549
|
try {
|
|
@@ -127533,14 +127563,8 @@ var makeChatSetup = (core, deps) => {
|
|
|
127533
127563
|
return;
|
|
127534
127564
|
}
|
|
127535
127565
|
const chatKey = chatKeyOf(binding);
|
|
127536
|
-
|
|
127537
|
-
|
|
127538
|
-
rows = await projectRowsFor(chatKey);
|
|
127539
|
-
} catch (error) {
|
|
127540
|
-
host.log.warn("chat could not list the projects", { error: describeError(error) });
|
|
127541
|
-
await deliver(binding, t("panel.loadFailed"));
|
|
127542
|
-
return;
|
|
127543
|
-
}
|
|
127566
|
+
const rows = await loadProjectRows(binding);
|
|
127567
|
+
if (rows === null) return;
|
|
127544
127568
|
const picked = pickProject(arg, listedProjectsByChat.get(chatKey), rows);
|
|
127545
127569
|
if (picked === null) {
|
|
127546
127570
|
await deliver(binding, t("repo.notFound", { query: arg }));
|
|
@@ -127572,6 +127596,9 @@ var makeChatSetup = (core, deps) => {
|
|
|
127572
127596
|
listedProjectsByChat.delete(chatKey);
|
|
127573
127597
|
host.log.info("chat picked a project", { bot: binding.displayName, projectId: picked });
|
|
127574
127598
|
await deliver(binding, t("repo.done", { title: target2.title }));
|
|
127599
|
+
const pending = pendingMessages.get(chatKey);
|
|
127600
|
+
pendingMessages.forget((key) => key === chatKey);
|
|
127601
|
+
if (pending !== void 0) await deps.resumeMessage(binding, pending);
|
|
127575
127602
|
};
|
|
127576
127603
|
const handleGroup = async (binding, name, senderId) => {
|
|
127577
127604
|
const adapter = adapterFor(binding.platform);
|
|
@@ -127599,7 +127626,27 @@ var makeChatSetup = (core, deps) => {
|
|
|
127599
127626
|
await deliver(binding, t("group.created", { name }));
|
|
127600
127627
|
await promptProject(bindingOf2(binding, chatId));
|
|
127601
127628
|
};
|
|
127602
|
-
|
|
127629
|
+
const prepareMessage = async (binding, message) => {
|
|
127630
|
+
const chatKey = chatKeyOf(binding);
|
|
127631
|
+
const asked = message.text.trim();
|
|
127632
|
+
if (/^[1-9]\d{0,2}$/u.test(asked) && listedProjectsByChat.has(chatKey)) {
|
|
127633
|
+
await handleRepo(binding, asked);
|
|
127634
|
+
return false;
|
|
127635
|
+
}
|
|
127636
|
+
const rows = await loadProjectRows(binding);
|
|
127637
|
+
if (rows === null) return false;
|
|
127638
|
+
const only = rows.length === 1 ? rows[0] : void 0;
|
|
127639
|
+
if (only !== void 0) {
|
|
127640
|
+
commit("chat-updated", { chatKey, projectId: only.projectId });
|
|
127641
|
+
pendingMessages.forget((key) => key === chatKey);
|
|
127642
|
+
await deliver(binding, t("repo.autoSelected", { title: only.title }));
|
|
127643
|
+
return true;
|
|
127644
|
+
}
|
|
127645
|
+
pendingMessages.set(chatKey, message);
|
|
127646
|
+
if (projectPromptCooldown.tryAcquire(chatKey)) await promptProject(binding, rows);
|
|
127647
|
+
return false;
|
|
127648
|
+
};
|
|
127649
|
+
return { promptProject, handleRepo, handleGroup, prepareMessage };
|
|
127603
127650
|
};
|
|
127604
127651
|
|
|
127605
127652
|
// src/commands.ts
|
|
@@ -127692,7 +127739,6 @@ var parseChatCommand = (input) => {
|
|
|
127692
127739
|
return query === "" ? { kind: "selectTeam" } : { kind: "help" };
|
|
127693
127740
|
}
|
|
127694
127741
|
if (isThreadCommand(input.text, input.chinese)) return { kind: "selectThread" };
|
|
127695
|
-
if (/^\/[a-z][a-z0-9_-]*/i.test(trimmed)) return { kind: "help" };
|
|
127696
127742
|
if (input.chinese) {
|
|
127697
127743
|
const alias = ZH_ALIASES[trimmed];
|
|
127698
127744
|
if (alias !== void 0) return { kind: alias };
|
|
@@ -128396,7 +128442,7 @@ var makeImCore = (input) => {
|
|
|
128396
128442
|
init: emptyState,
|
|
128397
128443
|
apply: foldPluginEvent(input.pluginId)
|
|
128398
128444
|
});
|
|
128399
|
-
const
|
|
128445
|
+
const chatReady = stateHandle.get().then(
|
|
128400
128446
|
(restored) => {
|
|
128401
128447
|
state = restored;
|
|
128402
128448
|
},
|
|
@@ -128404,6 +128450,7 @@ var makeImCore = (input) => {
|
|
|
128404
128450
|
host.log.warn("chat could not restore its saved state", { error: describeError(error) });
|
|
128405
128451
|
}
|
|
128406
128452
|
);
|
|
128453
|
+
const ready = Promise.all([chatReady, input.inboundReady]).then(() => void 0);
|
|
128407
128454
|
let persisting = Promise.resolve();
|
|
128408
128455
|
const commit = (name, data) => {
|
|
128409
128456
|
state = foldImEvent(state, name, data);
|
|
@@ -128935,63 +128982,15 @@ var makeInboundAttachments = (core) => {
|
|
|
128935
128982
|
|
|
128936
128983
|
// src/inbound.ts
|
|
128937
128984
|
import { projectOrNull } from "@ycodium-ai/plugin-api";
|
|
128938
|
-
|
|
128939
|
-
// src/boundedSeen.ts
|
|
128940
|
-
var makeBoundedSeen = (limit) => {
|
|
128941
|
-
const seen = /* @__PURE__ */ new Set();
|
|
128942
|
-
return {
|
|
128943
|
-
has: (key) => seen.has(key),
|
|
128944
|
-
/** 记下这个键:第一次见返回 true;已经记着返回 false(不重排,最早记的先被忘)。 */
|
|
128945
|
-
claim: (key) => {
|
|
128946
|
-
if (seen.has(key)) return false;
|
|
128947
|
-
seen.add(key);
|
|
128948
|
-
if (seen.size > limit) {
|
|
128949
|
-
const oldest = seen.values().next().value;
|
|
128950
|
-
if (oldest !== void 0) seen.delete(oldest);
|
|
128951
|
-
}
|
|
128952
|
-
return true;
|
|
128953
|
-
}
|
|
128954
|
-
};
|
|
128955
|
-
};
|
|
128956
|
-
|
|
128957
|
-
// src/cooldown.ts
|
|
128958
|
-
var makeCooldown = (windowMs, now, maxKeys = Number.POSITIVE_INFINITY) => {
|
|
128959
|
-
const lastAt = /* @__PURE__ */ new Map();
|
|
128960
|
-
return {
|
|
128961
|
-
tryAcquire: (key) => {
|
|
128962
|
-
const current = now();
|
|
128963
|
-
const previous = lastAt.get(key);
|
|
128964
|
-
if (previous !== void 0 && current - previous < windowMs) return false;
|
|
128965
|
-
lastAt.delete(key);
|
|
128966
|
-
lastAt.set(key, current);
|
|
128967
|
-
if (lastAt.size > maxKeys) {
|
|
128968
|
-
for (const [candidate, at] of lastAt) {
|
|
128969
|
-
if (current - at >= windowMs) lastAt.delete(candidate);
|
|
128970
|
-
}
|
|
128971
|
-
while (lastAt.size > maxKeys) {
|
|
128972
|
-
const oldest = lastAt.keys().next().value;
|
|
128973
|
-
if (oldest === void 0) break;
|
|
128974
|
-
lastAt.delete(oldest);
|
|
128975
|
-
}
|
|
128976
|
-
}
|
|
128977
|
-
return true;
|
|
128978
|
-
}
|
|
128979
|
-
};
|
|
128980
|
-
};
|
|
128981
|
-
|
|
128982
|
-
// src/inbound.ts
|
|
128983
|
-
var SEEN_MESSAGE_LIMIT = 256;
|
|
128984
128985
|
var ARCHIVED_REPLY_COOLDOWN_MS = 10 * 6e4;
|
|
128985
128986
|
var UNSUPPORTED_REPLY_COOLDOWN_MS = 6e4;
|
|
128986
128987
|
var NOT_ALLOWED_REPLY_COOLDOWN_MS = 10 * 6e4;
|
|
128987
128988
|
var NOT_ALLOWED_REPLY_KEY_LIMIT = 1e3;
|
|
128988
|
-
var PROJECT_PROMPT_COOLDOWN_MS = 3e4;
|
|
128989
128989
|
var makeInbound = (core, deps) => {
|
|
128990
128990
|
const { host, t, adapterFor, commit, deliver, bindingOf: bindingOf2, bots } = core;
|
|
128991
128991
|
const { enqueueForChat } = deps;
|
|
128992
128992
|
const { handleCommand, targetOf } = deps.commands;
|
|
128993
|
-
const {
|
|
128994
|
-
const { listedProjectsByChat } = deps.rows;
|
|
128993
|
+
const { prepareMessage } = deps.chatSetup;
|
|
128995
128994
|
const { questionFlow, handleButtonClick } = deps.interactions;
|
|
128996
128995
|
const { answerByToken } = deps.approvals;
|
|
128997
128996
|
const { handlePanelClick } = deps.panelWiring;
|
|
@@ -129005,10 +129004,9 @@ var makeInbound = (core, deps) => {
|
|
|
129005
129004
|
() => Date.now(),
|
|
129006
129005
|
NOT_ALLOWED_REPLY_KEY_LIMIT
|
|
129007
129006
|
);
|
|
129008
|
-
const
|
|
129009
|
-
const
|
|
129010
|
-
const
|
|
129011
|
-
const claimCallback = (rowId, callbackId) => callbackId === void 0 || callbackId === "" || !alreadyHandled(`c:${rowId}:${callbackId}`);
|
|
129007
|
+
const { inboundState } = deps;
|
|
129008
|
+
const alreadyHandled = (rowId, key) => !inboundState.claim(rowId, key);
|
|
129009
|
+
const claimCallback = (rowId, callbackId) => callbackId === void 0 || callbackId === "" || !alreadyHandled(rowId, `c:${callbackId}`);
|
|
129012
129010
|
const turnAwayStranger = (target2, sender) => {
|
|
129013
129011
|
host.log.warn("chat ignored a message from someone not on the allow list", {
|
|
129014
129012
|
bot: target2.displayName,
|
|
@@ -129048,6 +129046,61 @@ var makeInbound = (core, deps) => {
|
|
|
129048
129046
|
const threadId = await startTurn(speaker, message);
|
|
129049
129047
|
if (threadId !== null) await markWorking(speaker, threadId, message.messageId);
|
|
129050
129048
|
};
|
|
129049
|
+
const resumeMessage = async (current, message) => {
|
|
129050
|
+
inheritFromParent(current, message.chatId, message.parentChatId);
|
|
129051
|
+
let target2 = {
|
|
129052
|
+
...bindingOf2(current, message.chatId),
|
|
129053
|
+
reply: anchorOfMessage(adapterFor(current.platform), message)
|
|
129054
|
+
};
|
|
129055
|
+
const chatKey = chatKeyOf(target2);
|
|
129056
|
+
if (await handleCommand(target2, message.text, message.senderId)) return;
|
|
129057
|
+
if (target2.projectId === "") {
|
|
129058
|
+
if (!await prepareMessage(target2, message)) return;
|
|
129059
|
+
target2 = { ...bindingOf2(current, message.chatId), reply: target2.reply };
|
|
129060
|
+
}
|
|
129061
|
+
const boundThread = chatOf(core.state, chatKey).threadId;
|
|
129062
|
+
if (boundThread !== null && message.text !== "" && await questionFlow.answerByText(chatKey, boundThread, message.text)) {
|
|
129063
|
+
return;
|
|
129064
|
+
}
|
|
129065
|
+
const project = await projectOrNull(host.projects, target2.projectId);
|
|
129066
|
+
if (project === null || project.archivedAt != null) {
|
|
129067
|
+
if (project === null) {
|
|
129068
|
+
host.log.warn("chat cannot start work: the chat's project is gone", {
|
|
129069
|
+
bot: target2.displayName,
|
|
129070
|
+
projectId: target2.projectId
|
|
129071
|
+
});
|
|
129072
|
+
}
|
|
129073
|
+
if (archivedReplyCooldown.tryAcquire(chatKey)) {
|
|
129074
|
+
await deliver(
|
|
129075
|
+
target2,
|
|
129076
|
+
project === null ? t("reply.projectMissing") : t("reply.projectArchived", { title: project.title })
|
|
129077
|
+
);
|
|
129078
|
+
}
|
|
129079
|
+
return;
|
|
129080
|
+
}
|
|
129081
|
+
const routed = targetOf(target2);
|
|
129082
|
+
const attachmentsOnly = message.text.trim() === "" && message.resources.length > 0;
|
|
129083
|
+
if (routed.kind === "team") {
|
|
129084
|
+
if (message.resources.length > 0) await deliver(target2, t("reply.attachmentsNoTeam"));
|
|
129085
|
+
if (attachmentsOnly) return;
|
|
129086
|
+
const leadThreadId = await startTeamGoal(target2, message);
|
|
129087
|
+
if (leadThreadId !== null) await markWorking(target2, leadThreadId, message.messageId);
|
|
129088
|
+
return;
|
|
129089
|
+
}
|
|
129090
|
+
if (attachmentsOnly) {
|
|
129091
|
+
await receiveAttachmentsOnly(target2, message);
|
|
129092
|
+
return;
|
|
129093
|
+
}
|
|
129094
|
+
const branchChatId = hasWaitingAttachments(chatKey) ? void 0 : message.branchChatId;
|
|
129095
|
+
if (branchChatId === void 0) {
|
|
129096
|
+
await openTurn(target2, message);
|
|
129097
|
+
return;
|
|
129098
|
+
}
|
|
129099
|
+
enqueueForChat(chatKeyOf({ rowId: current.rowId, chatId: branchChatId }), async () => {
|
|
129100
|
+
inheritFromParent(current, branchChatId, message.chatId);
|
|
129101
|
+
await openTurn({ ...bindingOf2(current, branchChatId), reply: target2.reply }, message);
|
|
129102
|
+
});
|
|
129103
|
+
};
|
|
129051
129104
|
const inboundHandlersFor = (bot) => ({
|
|
129052
129105
|
onError: (message) => host.log.warn("chat inbound connection failed", {
|
|
129053
129106
|
platform: bot.platform,
|
|
@@ -129070,7 +129123,7 @@ var makeInbound = (core, deps) => {
|
|
|
129070
129123
|
if (current === void 0) return;
|
|
129071
129124
|
const message = settleChat(current, received);
|
|
129072
129125
|
const arrived = bindingOf2(current, message.chatId);
|
|
129073
|
-
if (alreadyHandled(`m:${
|
|
129126
|
+
if (alreadyHandled(current.rowId, `m:${message.chatId}:${message.messageId}`)) return;
|
|
129074
129127
|
if (message.chatKind !== void 0 && chatOf(core.state, chatKeyOf(arrived)).chatKind !== message.chatKind) {
|
|
129075
129128
|
commit("chat-updated", { chatKey: chatKeyOf(arrived), chatKind: message.chatKind });
|
|
129076
129129
|
}
|
|
@@ -129097,69 +129150,129 @@ var makeInbound = (core, deps) => {
|
|
|
129097
129150
|
});
|
|
129098
129151
|
return;
|
|
129099
129152
|
}
|
|
129100
|
-
enqueueForChat(chatKeyOf(arrived),
|
|
129101
|
-
|
|
129102
|
-
|
|
129103
|
-
|
|
129104
|
-
|
|
129105
|
-
|
|
129106
|
-
|
|
129107
|
-
|
|
129108
|
-
|
|
129109
|
-
|
|
129110
|
-
|
|
129111
|
-
|
|
129112
|
-
|
|
129113
|
-
|
|
129114
|
-
|
|
129115
|
-
|
|
129116
|
-
|
|
129117
|
-
|
|
129118
|
-
|
|
129119
|
-
|
|
129153
|
+
enqueueForChat(chatKeyOf(arrived), () => resumeMessage(current, message));
|
|
129154
|
+
}
|
|
129155
|
+
});
|
|
129156
|
+
return { inboundHandlersFor, resumeMessage };
|
|
129157
|
+
};
|
|
129158
|
+
|
|
129159
|
+
// src/inboundStore.ts
|
|
129160
|
+
import * as NodeFSP from "node:fs/promises";
|
|
129161
|
+
import * as NodePath from "node:path";
|
|
129162
|
+
var SEEN_LIMIT = 1e3;
|
|
129163
|
+
var fileIo = {
|
|
129164
|
+
readFile: (path) => NodeFSP.readFile(path, "utf8"),
|
|
129165
|
+
mkdir: async (path) => {
|
|
129166
|
+
await NodeFSP.mkdir(path, { recursive: true });
|
|
129167
|
+
},
|
|
129168
|
+
writeFile: (path, contents) => NodeFSP.writeFile(path, contents, "utf8"),
|
|
129169
|
+
rename: (from, to) => NodeFSP.rename(from, to)
|
|
129170
|
+
};
|
|
129171
|
+
var isRecord2 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
129172
|
+
var decode = (contents) => {
|
|
129173
|
+
const value2 = JSON.parse(contents);
|
|
129174
|
+
if (!isRecord2(value2) || value2["version"] !== 1 || !isRecord2(value2["bots"]))
|
|
129175
|
+
throw new Error("invalid inbound store");
|
|
129176
|
+
const bots = /* @__PURE__ */ new Map();
|
|
129177
|
+
for (const [rowId, row] of Object.entries(value2["bots"])) {
|
|
129178
|
+
if (!isRecord2(row) || !Array.isArray(row["seenIds"]) || !row["seenIds"].every((id) => typeof id === "string"))
|
|
129179
|
+
throw new Error("invalid inbound bot row");
|
|
129180
|
+
const telegram = row["telegram"];
|
|
129181
|
+
if (telegram !== void 0 && (!isRecord2(telegram) || typeof telegram["tokenHash"] !== "string" || telegram["tokenHash"] === "" || typeof telegram["offset"] !== "number" || !Number.isSafeInteger(telegram["offset"]) || telegram["offset"] < 0))
|
|
129182
|
+
throw new Error("invalid telegram cursor");
|
|
129183
|
+
bots.set(rowId, {
|
|
129184
|
+
seenIds: row["seenIds"].slice(-SEEN_LIMIT),
|
|
129185
|
+
...telegram === void 0 ? {} : {
|
|
129186
|
+
telegram: {
|
|
129187
|
+
tokenHash: telegram["tokenHash"],
|
|
129188
|
+
offset: telegram["offset"]
|
|
129120
129189
|
}
|
|
129121
|
-
|
|
129122
|
-
|
|
129123
|
-
|
|
129124
|
-
|
|
129125
|
-
|
|
129126
|
-
|
|
129127
|
-
|
|
129128
|
-
|
|
129129
|
-
|
|
129130
|
-
|
|
129131
|
-
|
|
129132
|
-
|
|
129133
|
-
|
|
129190
|
+
}
|
|
129191
|
+
});
|
|
129192
|
+
}
|
|
129193
|
+
return bots;
|
|
129194
|
+
};
|
|
129195
|
+
var makeInboundStore = (input) => {
|
|
129196
|
+
const io = input.io ?? fileIo;
|
|
129197
|
+
const path = NodePath.join(input.dataDir, "inbound.json");
|
|
129198
|
+
const temporary = `${path}.tmp`;
|
|
129199
|
+
let bots = /* @__PURE__ */ new Map();
|
|
129200
|
+
let dirty = false;
|
|
129201
|
+
let writing;
|
|
129202
|
+
const warn = (message, error) => input.log.warn(message, { error: describeError(error) });
|
|
129203
|
+
const ready = io.readFile(path).then(
|
|
129204
|
+
(contents) => {
|
|
129205
|
+
try {
|
|
129206
|
+
bots = decode(contents);
|
|
129207
|
+
} catch (error) {
|
|
129208
|
+
warn("chat could not restore inbound state", error);
|
|
129209
|
+
}
|
|
129210
|
+
},
|
|
129211
|
+
(error) => {
|
|
129212
|
+
if (!isRecord2(error) || error["code"] !== "ENOENT")
|
|
129213
|
+
warn("chat could not restore inbound state", error);
|
|
129214
|
+
}
|
|
129215
|
+
);
|
|
129216
|
+
const write = () => {
|
|
129217
|
+
writing ??= Promise.resolve().then(async () => {
|
|
129218
|
+
try {
|
|
129219
|
+
while (dirty) {
|
|
129220
|
+
dirty = false;
|
|
129221
|
+
const contents = JSON.stringify({ version: 1, bots: Object.fromEntries(bots) });
|
|
129222
|
+
try {
|
|
129223
|
+
await io.mkdir(input.dataDir);
|
|
129224
|
+
await io.writeFile(temporary, contents);
|
|
129225
|
+
await io.rename(temporary, path);
|
|
129226
|
+
} catch (error) {
|
|
129227
|
+
dirty = true;
|
|
129228
|
+
warn("chat could not save inbound state", error);
|
|
129229
|
+
break;
|
|
129134
129230
|
}
|
|
129135
|
-
return;
|
|
129136
|
-
}
|
|
129137
|
-
const routed = targetOf(target2);
|
|
129138
|
-
const attachmentsOnly = message.text.trim() === "" && message.resources.length > 0;
|
|
129139
|
-
if (routed.kind === "team") {
|
|
129140
|
-
if (message.resources.length > 0) await deliver(target2, t("reply.attachmentsNoTeam"));
|
|
129141
|
-
if (attachmentsOnly) return;
|
|
129142
|
-
const leadThreadId = await startTeamGoal(target2, message);
|
|
129143
|
-
if (leadThreadId !== null) await markWorking(target2, leadThreadId, message.messageId);
|
|
129144
|
-
return;
|
|
129145
129231
|
}
|
|
129146
|
-
|
|
129147
|
-
|
|
129148
|
-
|
|
129149
|
-
|
|
129150
|
-
|
|
129151
|
-
|
|
129152
|
-
|
|
129153
|
-
|
|
129154
|
-
|
|
129155
|
-
|
|
129156
|
-
|
|
129157
|
-
|
|
129158
|
-
|
|
129159
|
-
}
|
|
129232
|
+
} finally {
|
|
129233
|
+
writing = void 0;
|
|
129234
|
+
}
|
|
129235
|
+
});
|
|
129236
|
+
return writing;
|
|
129237
|
+
};
|
|
129238
|
+
const changed = () => {
|
|
129239
|
+
dirty = true;
|
|
129240
|
+
void write();
|
|
129241
|
+
};
|
|
129242
|
+
const rowOf = (rowId) => {
|
|
129243
|
+
let row = bots.get(rowId);
|
|
129244
|
+
if (row === void 0) {
|
|
129245
|
+
row = { seenIds: [] };
|
|
129246
|
+
bots.set(rowId, row);
|
|
129160
129247
|
}
|
|
129161
|
-
|
|
129162
|
-
|
|
129248
|
+
return row;
|
|
129249
|
+
};
|
|
129250
|
+
return {
|
|
129251
|
+
ready,
|
|
129252
|
+
claim: (rowId, id) => {
|
|
129253
|
+
const row = rowOf(rowId);
|
|
129254
|
+
if (row.seenIds.includes(id)) return false;
|
|
129255
|
+
row.seenIds.push(id);
|
|
129256
|
+
if (row.seenIds.length > SEEN_LIMIT) row.seenIds.shift();
|
|
129257
|
+
changed();
|
|
129258
|
+
return true;
|
|
129259
|
+
},
|
|
129260
|
+
readCursor: (rowId, tokenHash) => {
|
|
129261
|
+
const cursor = bots.get(rowId)?.telegram;
|
|
129262
|
+
return cursor?.tokenHash === tokenHash ? cursor.offset : void 0;
|
|
129263
|
+
},
|
|
129264
|
+
saveCursor: (rowId, tokenHash, offset) => {
|
|
129265
|
+
const row = rowOf(rowId);
|
|
129266
|
+
if (row.telegram?.tokenHash === tokenHash && row.telegram.offset === offset) return;
|
|
129267
|
+
if (row.telegram?.tokenHash !== tokenHash) row.seenIds = [];
|
|
129268
|
+
row.telegram = { tokenHash, offset };
|
|
129269
|
+
changed();
|
|
129270
|
+
},
|
|
129271
|
+
flush: async () => {
|
|
129272
|
+
await ready;
|
|
129273
|
+
if (dirty || writing) await write();
|
|
129274
|
+
}
|
|
129275
|
+
};
|
|
129163
129276
|
};
|
|
129164
129277
|
|
|
129165
129278
|
// src/interactions.ts
|
|
@@ -132203,9 +132316,9 @@ function getDecodeCache(exclude) {
|
|
|
132203
132316
|
}
|
|
132204
132317
|
return cache;
|
|
132205
132318
|
}
|
|
132206
|
-
function
|
|
132319
|
+
function decode2(string, exclude) {
|
|
132207
132320
|
if (typeof exclude !== "string") {
|
|
132208
|
-
exclude =
|
|
132321
|
+
exclude = decode2.defaultChars;
|
|
132209
132322
|
}
|
|
132210
132323
|
const cache = getDecodeCache(exclude);
|
|
132211
132324
|
return string.replace(/(%[a-f0-9]{2})+/gi, function(seq) {
|
|
@@ -132264,9 +132377,9 @@ function decode(string, exclude) {
|
|
|
132264
132377
|
return result;
|
|
132265
132378
|
});
|
|
132266
132379
|
}
|
|
132267
|
-
|
|
132268
|
-
|
|
132269
|
-
var decode_default =
|
|
132380
|
+
decode2.defaultChars = ";/?:@&=+$,#";
|
|
132381
|
+
decode2.componentChars = "";
|
|
132382
|
+
var decode_default = decode2;
|
|
132270
132383
|
|
|
132271
132384
|
// ../../node_modules/.pnpm/mdurl@2.1.0/node_modules/mdurl/lib/encode.mjs
|
|
132272
132385
|
var encodeCache = {};
|
|
@@ -133287,12 +133400,12 @@ var LinkifyIt = class {
|
|
|
133287
133400
|
*
|
|
133288
133401
|
* See [twitter mentions example](https://github.com/markdown-it/linkify-it/blob/master/examples/twitter.mjs).
|
|
133289
133402
|
*/
|
|
133290
|
-
add(schema,
|
|
133291
|
-
if (!
|
|
133403
|
+
add(schema, definition2 = null) {
|
|
133404
|
+
if (!definition2) delete this.__schemas__[schema];
|
|
133292
133405
|
else {
|
|
133293
133406
|
const def = {
|
|
133294
133407
|
normalize: (match, self2) => self2.normalize(match),
|
|
133295
|
-
...
|
|
133408
|
+
...definition2
|
|
133296
133409
|
};
|
|
133297
133410
|
this.__schemas__[schema] = def;
|
|
133298
133411
|
}
|
|
@@ -137801,6 +137914,24 @@ var startLarkInbound = (input) => {
|
|
|
137801
137914
|
};
|
|
137802
137915
|
};
|
|
137803
137916
|
|
|
137917
|
+
// src/boundedSeen.ts
|
|
137918
|
+
var makeBoundedSeen = (limit) => {
|
|
137919
|
+
const seen = /* @__PURE__ */ new Set();
|
|
137920
|
+
return {
|
|
137921
|
+
has: (key) => seen.has(key),
|
|
137922
|
+
/** 记下这个键:第一次见返回 true;已经记着返回 false(不重排,最早记的先被忘)。 */
|
|
137923
|
+
claim: (key) => {
|
|
137924
|
+
if (seen.has(key)) return false;
|
|
137925
|
+
seen.add(key);
|
|
137926
|
+
if (seen.size > limit) {
|
|
137927
|
+
const oldest = seen.values().next().value;
|
|
137928
|
+
if (oldest !== void 0) seen.delete(oldest);
|
|
137929
|
+
}
|
|
137930
|
+
return true;
|
|
137931
|
+
}
|
|
137932
|
+
};
|
|
137933
|
+
};
|
|
137934
|
+
|
|
137804
137935
|
// src/deadline.ts
|
|
137805
137936
|
var withDeadline2 = async (timeoutMs, load) => {
|
|
137806
137937
|
const signal = AbortSignal.timeout(timeoutMs);
|
|
@@ -138928,6 +139059,7 @@ var en_default = {
|
|
|
138928
139059
|
}
|
|
138929
139060
|
},
|
|
138930
139061
|
repo: {
|
|
139062
|
+
autoSelected: "Using project {{title}}.",
|
|
138931
139063
|
needProject: "This chat has no project yet, so I won't start any work. Pick one and I will.",
|
|
138932
139064
|
currentLine: 'This chat works on project "{{title}}".',
|
|
138933
139065
|
noProjects: "There are no projects on this machine yet. Add one in Ycodium first.",
|
|
@@ -139630,6 +139762,7 @@ var zh_CN_default = {
|
|
|
139630
139762
|
}
|
|
139631
139763
|
},
|
|
139632
139764
|
repo: {
|
|
139765
|
+
autoSelected: "\u4F7F\u7528\u9879\u76EE\u300C{{title}}\u300D\u3002",
|
|
139633
139766
|
needProject: "\u8FD9\u4E2A\u804A\u5929\u8FD8\u6CA1\u9009\u9879\u76EE\uFF0C\u9009\u5B9A\u4E4B\u524D\u6211\u4E0D\u5F00\u5DE5\u3002\u9009\u4E00\u4E2A\u5C31\u5F00\u59CB\u3002",
|
|
139634
139767
|
currentLine: "\u8FD9\u4E2A\u804A\u5929\u73B0\u5728\u5728\u9879\u76EE\u300C{{title}}\u300D\u4E0A\u3002",
|
|
139635
139768
|
noProjects: "\u8FD9\u53F0\u673A\u5668\u4E0A\u8FD8\u6CA1\u6709\u9879\u76EE\uFF0C\u5148\u5230 Ycodium \u91CC\u6DFB\u52A0\u4E00\u4E2A\u3002",
|
|
@@ -140069,7 +140202,10 @@ var makeNotifications = (core, deps) => {
|
|
|
140069
140202
|
const said = threadsWithSomethingToReport.delete(threadId);
|
|
140070
140203
|
await ready;
|
|
140071
140204
|
const targets = targetsForProject(threadId, await projectOfThread(threadId));
|
|
140072
|
-
const
|
|
140205
|
+
const owes = Object.values(conclusionDebtsOf(core.state)).some(
|
|
140206
|
+
(debt2) => debt2.threadId === threadId
|
|
140207
|
+
);
|
|
140208
|
+
const { debt, handled, execution } = said || owes || targets.length > 0 ? await conclusions.forTurn(threadId) : { debt: void 0, handled: false, execution: null };
|
|
140073
140209
|
if (debt !== void 0) {
|
|
140074
140210
|
const binding = bindingForChatKey(debt.chatKey);
|
|
140075
140211
|
if (binding !== void 0 && !streamsTo(binding, threadId) && execution?.session?.activeTurnId == null && execution?.latestTurn?.state !== "running" && execution?.latestTurn?.state !== "error" && payload.session?.status !== "error") {
|
|
@@ -141473,7 +141609,7 @@ var makeSessions = (core) => {
|
|
|
141473
141609
|
|
|
141474
141610
|
// src/teamGoals.ts
|
|
141475
141611
|
import * as NodeCrypto4 from "node:crypto";
|
|
141476
|
-
var
|
|
141612
|
+
var isRecord3 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
141477
141613
|
var teamGoalRequestId = (binding, messageId) => {
|
|
141478
141614
|
const identity = JSON.stringify([
|
|
141479
141615
|
"im",
|
|
@@ -141515,7 +141651,7 @@ var makeTeamGoals = (core) => {
|
|
|
141515
141651
|
requestId
|
|
141516
141652
|
}
|
|
141517
141653
|
});
|
|
141518
|
-
if (
|
|
141654
|
+
if (isRecord3(result) && result._tag === "TeamGoalRejection") {
|
|
141519
141655
|
await deliver(
|
|
141520
141656
|
binding,
|
|
141521
141657
|
t(
|
|
@@ -141524,7 +141660,7 @@ var makeTeamGoals = (core) => {
|
|
|
141524
141660
|
);
|
|
141525
141661
|
return null;
|
|
141526
141662
|
}
|
|
141527
|
-
if (!
|
|
141663
|
+
if (!isRecord3(result) || typeof result.leadThreadId !== "string" || result.leadThreadId === "" || result.leadName !== null && typeof result.leadName !== "string") {
|
|
141528
141664
|
throw new Error("team startGoal returned an invalid result");
|
|
141529
141665
|
}
|
|
141530
141666
|
topicRoot?.confirmConsumed();
|
|
@@ -141547,6 +141683,9 @@ var makeTeamGoals = (core) => {
|
|
|
141547
141683
|
return { hasRosterFor, startTeamGoal };
|
|
141548
141684
|
};
|
|
141549
141685
|
|
|
141686
|
+
// src/telegramAdapter.ts
|
|
141687
|
+
import * as NodeCrypto5 from "node:crypto";
|
|
141688
|
+
|
|
141550
141689
|
// src/telegramApi.ts
|
|
141551
141690
|
var API_BASE = "https://api.telegram.org";
|
|
141552
141691
|
var POLL_TIMEOUT_SECONDS = 45;
|
|
@@ -141571,6 +141710,10 @@ var target = (chatId) => {
|
|
|
141571
141710
|
const { chat, thread } = splitChatId(chatId);
|
|
141572
141711
|
return { chat_id: chat, ...thread === null ? {} : { message_thread_id: thread } };
|
|
141573
141712
|
};
|
|
141713
|
+
var replyParameters = (messageId) => {
|
|
141714
|
+
const id = Number(messageId);
|
|
141715
|
+
return messageId === void 0 || !Number.isSafeInteger(id) ? {} : { reply_parameters: { message_id: id, allow_sending_without_reply: true } };
|
|
141716
|
+
};
|
|
141574
141717
|
var chatOnly = (chatId) => ({ chat_id: splitChatId(chatId).chat });
|
|
141575
141718
|
var TelegramApiError = class extends Error {
|
|
141576
141719
|
code;
|
|
@@ -141702,13 +141845,15 @@ var makeTelegramApi = (input) => {
|
|
|
141702
141845
|
}
|
|
141703
141846
|
return envelope.result;
|
|
141704
141847
|
};
|
|
141705
|
-
const upload = async (method, field, chatId, file) => {
|
|
141848
|
+
const upload = async (method, field, chatId, file, replyMessageId) => {
|
|
141706
141849
|
const form = new FormData();
|
|
141707
141850
|
const where = target(chatId);
|
|
141708
141851
|
form.set("chat_id", where.chat_id);
|
|
141709
141852
|
if (where.message_thread_id !== void 0) {
|
|
141710
141853
|
form.set("message_thread_id", String(where.message_thread_id));
|
|
141711
141854
|
}
|
|
141855
|
+
const reply = replyParameters(replyMessageId).reply_parameters;
|
|
141856
|
+
if (reply !== void 0) form.set("reply_parameters", JSON.stringify(reply));
|
|
141712
141857
|
form.set(field, new Blob([new Uint8Array(file.bytes)], { type: file.mimeType }), file.name);
|
|
141713
141858
|
const response = await send(
|
|
141714
141859
|
method,
|
|
@@ -141731,9 +141876,10 @@ var makeTelegramApi = (input) => {
|
|
|
141731
141876
|
(row) => row.map((button) => ({ text: button.text, callback_data: button.data }))
|
|
141732
141877
|
)
|
|
141733
141878
|
});
|
|
141734
|
-
const sendSingle = async (method, chatId, body, rows) => {
|
|
141879
|
+
const sendSingle = async (method, chatId, body, rows, replyMessageId) => {
|
|
141735
141880
|
const sent = await call(method, {
|
|
141736
141881
|
...target(chatId),
|
|
141882
|
+
...replyParameters(replyMessageId),
|
|
141737
141883
|
...body,
|
|
141738
141884
|
...rows === void 0 ? {} : { reply_markup: keyboard(rows) }
|
|
141739
141885
|
});
|
|
@@ -141793,10 +141939,11 @@ var makeTelegramApi = (input) => {
|
|
|
141793
141939
|
},
|
|
141794
141940
|
POLL_CALL_TIMEOUT_MS
|
|
141795
141941
|
),
|
|
141796
|
-
sendMessage: async (chatId, text4, retry) => {
|
|
141797
|
-
for (const chunk of splitForTelegram(text4)) {
|
|
141942
|
+
sendMessage: async (chatId, text4, retry, replyMessageId) => {
|
|
141943
|
+
for (const [index, chunk] of splitForTelegram(text4).entries()) {
|
|
141944
|
+
const reply = index === 0 ? replyMessageId : void 0;
|
|
141798
141945
|
await sendWithRetry(
|
|
141799
|
-
() =>
|
|
141946
|
+
() => sendSingle("sendMessage", chatId, { text: chunk }, void 0, reply),
|
|
141800
141947
|
telegramSendVerdict,
|
|
141801
141948
|
retry
|
|
141802
141949
|
);
|
|
@@ -141806,12 +141953,12 @@ var makeTelegramApi = (input) => {
|
|
|
141806
141953
|
* 发一条消息,回它的 id。调用方保证 `text` 不超过单条上限(边写边更新的回复要自己
|
|
141807
141954
|
* 在上限处翻篇,这里不替它切)。带 `rows` 就挂一块内联键盘。
|
|
141808
141955
|
*/
|
|
141809
|
-
sendOne: (chatId, text4, rows) => sendSingle("sendMessage", chatId, { text: text4 }, rows),
|
|
141956
|
+
sendOne: (chatId, text4, rows, replyMessageId) => sendSingle("sendMessage", chatId, { text: text4 }, rows, replyMessageId),
|
|
141810
141957
|
/**
|
|
141811
141958
|
* 发一条富文本,回它的 id。`markdown` 已是平台要的样子。带 `rows` 就挂一块内联键盘。
|
|
141812
141959
|
* 调用方保证不超富文本单条上限(这里不替它切)。
|
|
141813
141960
|
*/
|
|
141814
|
-
sendRichOne: (chatId, markdown, rows) => sendSingle("sendRichMessage", chatId, { rich_message: { markdown } }, rows),
|
|
141961
|
+
sendRichOne: (chatId, markdown, rows, replyMessageId) => sendSingle("sendRichMessage", chatId, { rich_message: { markdown } }, rows, replyMessageId),
|
|
141815
141962
|
/**
|
|
141816
141963
|
* 改一条已发出的消息。内容没变(`message is not modified`)当成功。`rows` 不给就是
|
|
141817
141964
|
* 去掉按钮:改了文字又要保留按钮的调用方得自己再传一次。
|
|
@@ -141823,20 +141970,21 @@ var makeTelegramApi = (input) => {
|
|
|
141823
141970
|
*/
|
|
141824
141971
|
editRich: (chatId, messageId, markdown, rows = []) => editSingle(chatId, messageId, { rich_message: { markdown } }, rows),
|
|
141825
141972
|
/** 带按钮的审批消息,一行一个按钮;回消息 id,之后才改得了它(平台没给就是 null)。 */
|
|
141826
|
-
sendButtons: (chatId, text4, buttons) => sendSingle(
|
|
141973
|
+
sendButtons: (chatId, text4, buttons, replyMessageId) => sendSingle(
|
|
141827
141974
|
"sendMessage",
|
|
141828
141975
|
chatId,
|
|
141829
141976
|
{ text: text4 },
|
|
141830
|
-
buttons.map((button) => [{ text: button.label, data: button.token }])
|
|
141977
|
+
buttons.map((button) => [{ text: button.label, data: button.token }]),
|
|
141978
|
+
replyMessageId
|
|
141831
141979
|
),
|
|
141832
141980
|
/** 答完点击,不然客户端上那个按钮一直转圈。带 `text` 时点击者会看到一句提示。 */
|
|
141833
141981
|
answerCallback: (callbackQueryId, text4) => call("answerCallbackQuery", {
|
|
141834
141982
|
callback_query_id: callbackQueryId,
|
|
141835
141983
|
...text4 === void 0 ? {} : { text: text4 }
|
|
141836
141984
|
}),
|
|
141837
|
-
sendPhoto: (chatId, photo) => upload("sendPhoto", "photo", chatId, photo),
|
|
141985
|
+
sendPhoto: (chatId, photo, replyMessageId) => upload("sendPhoto", "photo", chatId, photo, replyMessageId),
|
|
141838
141986
|
/** 以文件形式发(不压缩、不限尺寸比例):什么类型都行,音频与视频也走这条。 */
|
|
141839
|
-
sendDocument: (chatId, file) => upload("sendDocument", "document", chatId, file),
|
|
141987
|
+
sendDocument: (chatId, file, replyMessageId) => upload("sendDocument", "document", chatId, file, replyMessageId),
|
|
141840
141988
|
/** 取一个文件的字节。要两步:先换路径,再按路径下载。 */
|
|
141841
141989
|
fetchFile: async (fileId, maxBytes) => {
|
|
141842
141990
|
const file = await call("getFile", {
|
|
@@ -142048,7 +142196,7 @@ var makeTurnWriter = (deps) => {
|
|
|
142048
142196
|
const put = async (text4) => {
|
|
142049
142197
|
const bounded = text4.length <= deps.limit ? text4 : text4.slice(0, deps.limit);
|
|
142050
142198
|
if (live === null) {
|
|
142051
|
-
const id = await deps.messages.send(bounded);
|
|
142199
|
+
const id = await deps.messages.send(bounded, first === null);
|
|
142052
142200
|
if (id === null) throw new Error("telegram sent a message without an id");
|
|
142053
142201
|
live = id;
|
|
142054
142202
|
first ??= id;
|
|
@@ -142188,19 +142336,18 @@ var makeTelegramAdapter = (deps) => {
|
|
|
142188
142336
|
limit: TELEGRAM_TEXT_MAX_CHARS,
|
|
142189
142337
|
...resume === void 0 ? {} : { resume },
|
|
142190
142338
|
messages: {
|
|
142191
|
-
send: (text4) =>
|
|
142192
|
-
|
|
142193
|
-
|
|
142194
|
-
|
|
142195
|
-
|
|
142339
|
+
send: (text4, first) => {
|
|
142340
|
+
const reply = first ? slot.binding.reply?.messageId : void 0;
|
|
142341
|
+
return withRichFallback(
|
|
142342
|
+
toTelegramRichMarkdown(text4),
|
|
142343
|
+
async (markdown) => (await apiFor(slot.binding)).sendRichOne(chatId, markdown, void 0, reply),
|
|
142344
|
+
async () => (await apiFor(slot.binding)).sendOne(chatId, text4, void 0, reply)
|
|
142345
|
+
);
|
|
142346
|
+
},
|
|
142196
142347
|
edit: (messageId, text4) => withRichFallback(
|
|
142197
142348
|
toTelegramRichMarkdown(text4),
|
|
142198
|
-
async (markdown) =>
|
|
142199
|
-
|
|
142200
|
-
},
|
|
142201
|
-
async () => {
|
|
142202
|
-
await (await apiFor(slot.binding)).editMessage(chatId, messageId, text4);
|
|
142203
|
-
}
|
|
142349
|
+
async (markdown) => (await apiFor(slot.binding)).editRich(chatId, messageId, markdown),
|
|
142350
|
+
async () => (await apiFor(slot.binding)).editMessage(chatId, messageId, text4)
|
|
142204
142351
|
)
|
|
142205
142352
|
}
|
|
142206
142353
|
});
|
|
@@ -142208,6 +142355,7 @@ var makeTelegramAdapter = (deps) => {
|
|
|
142208
142355
|
platform: "telegram",
|
|
142209
142356
|
icon: "telegram",
|
|
142210
142357
|
label: "Telegram",
|
|
142358
|
+
quotesReplies: true,
|
|
142211
142359
|
columns: COLUMNS2,
|
|
142212
142360
|
validate: telegramConfigIssues,
|
|
142213
142361
|
isConfigured: (binding) => telegramConfigIssues(binding).length === 0,
|
|
@@ -142216,7 +142364,12 @@ var makeTelegramAdapter = (deps) => {
|
|
|
142216
142364
|
};
|
|
142217
142365
|
const stopped = new Promise((resolve) => stop = resolve);
|
|
142218
142366
|
let running = true;
|
|
142219
|
-
|
|
142367
|
+
const tokenHash = NodeCrypto5.createHash("sha256").update(tokenOf(binding)).digest("hex");
|
|
142368
|
+
let offset = deps.readCursor(binding.rowId, tokenHash);
|
|
142369
|
+
const advanceOffset = (update) => {
|
|
142370
|
+
offset = nextOffset([update], offset ?? 0);
|
|
142371
|
+
deps.saveCursor(binding.rowId, tokenHash, offset);
|
|
142372
|
+
};
|
|
142220
142373
|
let acknowledged = 0;
|
|
142221
142374
|
let backoff = BACKOFF_START_MS;
|
|
142222
142375
|
let botUsername;
|
|
@@ -142229,7 +142382,7 @@ var makeTelegramAdapter = (deps) => {
|
|
|
142229
142382
|
});
|
|
142230
142383
|
const publishAck = () => {
|
|
142231
142384
|
const api = liveApi;
|
|
142232
|
-
if (api === void 0 || offset <= acknowledged) return;
|
|
142385
|
+
if (api === void 0 || offset === void 0 || offset <= acknowledged) return;
|
|
142233
142386
|
const next = offset;
|
|
142234
142387
|
acknowledged = next;
|
|
142235
142388
|
void api.getUpdates(next, 0).catch(() => void 0);
|
|
@@ -142258,6 +142411,12 @@ var makeTelegramAdapter = (deps) => {
|
|
|
142258
142411
|
});
|
|
142259
142412
|
});
|
|
142260
142413
|
}
|
|
142414
|
+
if (offset === void 0) {
|
|
142415
|
+
const backlog = await api.getUpdates(-1, 0);
|
|
142416
|
+
if (!running) return;
|
|
142417
|
+
offset = nextOffset(backlog, 0);
|
|
142418
|
+
deps.saveCursor(binding.rowId, tokenHash, offset);
|
|
142419
|
+
}
|
|
142261
142420
|
acknowledged = offset;
|
|
142262
142421
|
const updates = await api.getUpdates(offset);
|
|
142263
142422
|
if (!running) return;
|
|
@@ -142270,13 +142429,13 @@ var makeTelegramAdapter = (deps) => {
|
|
|
142270
142429
|
if (callback?.data !== void 0) {
|
|
142271
142430
|
const operatorId = callback.from === void 0 ? null : String(callback.from.id);
|
|
142272
142431
|
const notice = callback.data.startsWith(PANEL_DATA_PREFIX) ? panelClick(binding.rowId, callback, operatorId, handlers) : handlers.onButton(callback.data, operatorId, callback.id);
|
|
142273
|
-
|
|
142432
|
+
advanceOffset(update);
|
|
142274
142433
|
await api.answerCallback(callback.id, notice ?? void 0).catch(() => void 0);
|
|
142275
142434
|
continue;
|
|
142276
142435
|
}
|
|
142277
142436
|
const message = update.message;
|
|
142278
142437
|
if (message === void 0) {
|
|
142279
|
-
|
|
142438
|
+
advanceOffset(update);
|
|
142280
142439
|
continue;
|
|
142281
142440
|
}
|
|
142282
142441
|
const resource = resourceOf2(message);
|
|
@@ -142285,7 +142444,7 @@ var makeTelegramAdapter = (deps) => {
|
|
|
142285
142444
|
botUsername
|
|
142286
142445
|
);
|
|
142287
142446
|
if (text4 === null) {
|
|
142288
|
-
|
|
142447
|
+
advanceOffset(update);
|
|
142289
142448
|
continue;
|
|
142290
142449
|
}
|
|
142291
142450
|
const gated = !passesGroupGate2({
|
|
@@ -142299,12 +142458,12 @@ var makeTelegramAdapter = (deps) => {
|
|
|
142299
142458
|
const solo = binding.groupMention === "always" && await isSoloGroup(String(message.chat.id));
|
|
142300
142459
|
if (!running) break;
|
|
142301
142460
|
if (!solo) {
|
|
142302
|
-
|
|
142461
|
+
advanceOffset(update);
|
|
142303
142462
|
continue;
|
|
142304
142463
|
}
|
|
142305
142464
|
}
|
|
142306
142465
|
if (!running) break;
|
|
142307
|
-
|
|
142466
|
+
advanceOffset(update);
|
|
142308
142467
|
const senderId = message.from === void 0 ? null : String(message.from.id);
|
|
142309
142468
|
const senderName = telegramDisplayName(message.from);
|
|
142310
142469
|
const chatKind = message.chat.type === "private" ? "private" : "group";
|
|
@@ -142367,7 +142526,7 @@ var makeTelegramAdapter = (deps) => {
|
|
|
142367
142526
|
},
|
|
142368
142527
|
sendText: async (binding, text4, options) => {
|
|
142369
142528
|
const api = await apiFor(binding);
|
|
142370
|
-
await api.sendMessage(binding.chatId, text4, options?.retry);
|
|
142529
|
+
await api.sendMessage(binding.chatId, text4, options?.retry, binding.reply?.messageId);
|
|
142371
142530
|
},
|
|
142372
142531
|
checkConnection: async (bot) => {
|
|
142373
142532
|
const token = tokenOf(bot);
|
|
@@ -142436,25 +142595,30 @@ var makeTelegramAdapter = (deps) => {
|
|
|
142436
142595
|
sendImage: async (binding, image2) => {
|
|
142437
142596
|
const api = await apiFor(binding);
|
|
142438
142597
|
try {
|
|
142439
|
-
await api.sendPhoto(binding.chatId, image2);
|
|
142598
|
+
await api.sendPhoto(binding.chatId, image2, binding.reply?.messageId);
|
|
142440
142599
|
} catch (error) {
|
|
142441
142600
|
if (!(error instanceof TelegramApiError && error.code === 400)) throw error;
|
|
142442
142601
|
deps.log.info("telegram could not send the picture as a photo, sending it as a file", {
|
|
142443
142602
|
name: image2.name,
|
|
142444
142603
|
reason: error.message
|
|
142445
142604
|
});
|
|
142446
|
-
await api.sendDocument(binding.chatId, image2);
|
|
142605
|
+
await api.sendDocument(binding.chatId, image2, binding.reply?.messageId);
|
|
142447
142606
|
}
|
|
142448
142607
|
},
|
|
142449
142608
|
sendFile: async (binding, file) => {
|
|
142450
142609
|
const api = await apiFor(binding);
|
|
142451
|
-
await api.sendDocument(binding.chatId, file);
|
|
142610
|
+
await api.sendDocument(binding.chatId, file, binding.reply?.messageId);
|
|
142452
142611
|
},
|
|
142453
142612
|
// 单张照片 10 MB、单个文件 50 MB。这两个数来自 Bot API 文档的记忆,本仓库里没有核对过。
|
|
142454
142613
|
outboundLimits: { imageBytes: 10 * 1024 * 1024, fileBytes: 50 * 1024 * 1024 },
|
|
142455
142614
|
askApproval: async (binding, request) => {
|
|
142456
142615
|
const api = await apiFor(binding);
|
|
142457
|
-
return api.sendButtons(
|
|
142616
|
+
return api.sendButtons(
|
|
142617
|
+
binding.chatId,
|
|
142618
|
+
request.body,
|
|
142619
|
+
request.options,
|
|
142620
|
+
binding.reply?.messageId
|
|
142621
|
+
);
|
|
142458
142622
|
},
|
|
142459
142623
|
settleApproval: async (binding, cardId, settlement) => {
|
|
142460
142624
|
const api = await apiFor(binding);
|
|
@@ -142506,7 +142670,7 @@ ${line}`
|
|
|
142506
142670
|
const api = await apiFor(binding);
|
|
142507
142671
|
const rendered = renderPanel(card, 1);
|
|
142508
142672
|
const cardId = await withFloodWait(
|
|
142509
|
-
() => api.sendOne(binding.chatId, rendered.text, rendered.rows)
|
|
142673
|
+
() => api.sendOne(binding.chatId, rendered.text, rendered.rows, binding.reply?.messageId)
|
|
142510
142674
|
);
|
|
142511
142675
|
if (cardId !== null) {
|
|
142512
142676
|
panelKeyboards.set(`${binding.rowId}:${binding.chatId}:${cardId}`, {
|
|
@@ -142531,7 +142695,9 @@ ${line}`
|
|
|
142531
142695
|
open: async (binding, card) => {
|
|
142532
142696
|
const api = await apiFor(binding);
|
|
142533
142697
|
const rendered = renderChoiceCard(card);
|
|
142534
|
-
return withFloodWait(
|
|
142698
|
+
return withFloodWait(
|
|
142699
|
+
() => api.sendOne(binding.chatId, rendered.text, rendered.rows, binding.reply?.messageId)
|
|
142700
|
+
);
|
|
142535
142701
|
},
|
|
142536
142702
|
update: async (binding, cardId, card) => {
|
|
142537
142703
|
const api = await apiFor(binding);
|
|
@@ -142971,7 +143137,7 @@ var registerSettingsRowActions = (ctx, adapters) => {
|
|
|
142971
143137
|
};
|
|
142972
143138
|
|
|
142973
143139
|
// src/settingsView.ts
|
|
142974
|
-
var
|
|
143140
|
+
var isRecord4 = (value2) => typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
142975
143141
|
var hasStoredSecret = (row, key) => {
|
|
142976
143142
|
const value2 = row[key];
|
|
142977
143143
|
return typeof value2 === "string" && value2 !== "";
|
|
@@ -142989,10 +143155,10 @@ var targetTable = () => ({
|
|
|
142989
143155
|
});
|
|
142990
143156
|
var targetViews = (config2) => {
|
|
142991
143157
|
const table2 = config2[DELIVERY_TARGETS_FIELD];
|
|
142992
|
-
if (!
|
|
143158
|
+
if (!isRecord4(table2)) return [];
|
|
142993
143159
|
const columns = deliveryTargetColumns();
|
|
142994
143160
|
return Object.entries(table2).flatMap(([rowId, raw]) => {
|
|
142995
|
-
if (!
|
|
143161
|
+
if (!isRecord4(raw)) return [];
|
|
142996
143162
|
const issues = targetIssues(raw);
|
|
142997
143163
|
const values = Object.fromEntries(
|
|
142998
143164
|
columns.map((column) => [column.key, readString(raw, column.key)])
|
|
@@ -143004,9 +143170,9 @@ var buildSettingsView = (config2, adapters) => {
|
|
|
143004
143170
|
const columns = buildBotColumns(adapters);
|
|
143005
143171
|
const table2 = config2[BOTS_FIELD];
|
|
143006
143172
|
const bots = [];
|
|
143007
|
-
if (
|
|
143173
|
+
if (isRecord4(table2)) {
|
|
143008
143174
|
for (const [rowId, raw] of Object.entries(table2)) {
|
|
143009
|
-
if (!
|
|
143175
|
+
if (!isRecord4(raw)) continue;
|
|
143010
143176
|
const platform = platformOf(raw);
|
|
143011
143177
|
const values = {};
|
|
143012
143178
|
const secrets = {};
|
|
@@ -143069,10 +143235,10 @@ var applyRowEdit = (config2, { field, columns }, edit) => {
|
|
|
143069
143235
|
for (const key of clearSecrets) {
|
|
143070
143236
|
if (!secretColumns.has(key)) return columnError("not-a-secret", key);
|
|
143071
143237
|
}
|
|
143072
|
-
const table2 =
|
|
143238
|
+
const table2 = isRecord4(config2[field]) ? config2[field] : {};
|
|
143073
143239
|
const requested = edit.rowId;
|
|
143074
143240
|
const current = requested === void 0 ? {} : Object.hasOwn(table2, requested) ? table2[requested] : void 0;
|
|
143075
|
-
if (!
|
|
143241
|
+
if (!isRecord4(current)) return { ok: false, code: "unknown-row" };
|
|
143076
143242
|
const rowId = requested ?? nextRowId(table2);
|
|
143077
143243
|
const nextRow = { ...current, ...edit.values };
|
|
143078
143244
|
const clearing = clearSecrets.filter((key) => !Object.hasOwn(secrets, key));
|
|
@@ -143090,7 +143256,7 @@ var applyBotEdit = (config2, adapters, edit) => applyRowEdit(config2, { field: B
|
|
|
143090
143256
|
var applyTargetEdit = (config2, edit) => applyRowEdit(config2, targetTable(), edit);
|
|
143091
143257
|
var removeRow = (config2, field, rowId) => {
|
|
143092
143258
|
const table2 = config2[field];
|
|
143093
|
-
if (!
|
|
143259
|
+
if (!isRecord4(table2) || !Object.hasOwn(table2, rowId)) return null;
|
|
143094
143260
|
const nextTable = { ...table2 };
|
|
143095
143261
|
delete nextTable[rowId];
|
|
143096
143262
|
return { ...config2, [field]: nextTable };
|
|
@@ -143329,7 +143495,7 @@ var makeWechatAdapter = (deps) => {
|
|
|
143329
143495
|
};
|
|
143330
143496
|
|
|
143331
143497
|
// src/wecomUpload.ts
|
|
143332
|
-
import * as
|
|
143498
|
+
import * as NodeCrypto6 from "node:crypto";
|
|
143333
143499
|
var WECOM_CHUNK_BYTES = 512 * 1024;
|
|
143334
143500
|
var WECOM_MAX_CHUNKS = 100;
|
|
143335
143501
|
var WECOM_MIN_UPLOAD_BYTES = 5;
|
|
@@ -143362,7 +143528,7 @@ var uploadWecomMedia = async (input) => {
|
|
|
143362
143528
|
filename: clampName(input.filename),
|
|
143363
143529
|
total_size: bytes.byteLength,
|
|
143364
143530
|
total_chunks: totalChunks,
|
|
143365
|
-
md5:
|
|
143531
|
+
md5: NodeCrypto6.createHash("md5").update(bytes).digest("hex")
|
|
143366
143532
|
});
|
|
143367
143533
|
const uploadId = init.upload_id;
|
|
143368
143534
|
if (typeof uploadId !== "string" || uploadId === "") {
|
|
@@ -143777,7 +143943,7 @@ var runWecomClient = (input) => {
|
|
|
143777
143943
|
};
|
|
143778
143944
|
|
|
143779
143945
|
// src/wecomMedia.ts
|
|
143780
|
-
import * as
|
|
143946
|
+
import * as NodeCrypto7 from "node:crypto";
|
|
143781
143947
|
|
|
143782
143948
|
// src/wecomPadding.ts
|
|
143783
143949
|
var PADDING_BLOCK = 32;
|
|
@@ -143808,7 +143974,7 @@ var decryptWecomMedia = (cipher, aesKey) => {
|
|
|
143808
143974
|
if (cipher.byteLength === 0 || cipher.byteLength % AES_BLOCK !== 0) {
|
|
143809
143975
|
throw new WecomDecryptError("the ciphertext is not a whole number of blocks");
|
|
143810
143976
|
}
|
|
143811
|
-
const decipher =
|
|
143977
|
+
const decipher = NodeCrypto7.createDecipheriv("aes-256-cbc", key, key.subarray(0, IV_BYTES));
|
|
143812
143978
|
decipher.setAutoPadding(false);
|
|
143813
143979
|
const plain = Buffer.concat([decipher.update(cipher), decipher.final()]);
|
|
143814
143980
|
const unpadded = stripPadding(plain);
|
|
@@ -144406,7 +144572,7 @@ import * as NodeHttp2 from "node:http";
|
|
|
144406
144572
|
import * as NodeNet from "node:net";
|
|
144407
144573
|
|
|
144408
144574
|
// src/wecomAppCrypto.ts
|
|
144409
|
-
import * as
|
|
144575
|
+
import * as NodeCrypto8 from "node:crypto";
|
|
144410
144576
|
var AES_KEY_BYTES = 32;
|
|
144411
144577
|
var RANDOM_BYTES = 16;
|
|
144412
144578
|
var WecomAppCryptoError = class extends Error {
|
|
@@ -144429,13 +144595,13 @@ var timingSafeEqualString2 = (a, b) => {
|
|
|
144429
144595
|
const left = Buffer.from(a);
|
|
144430
144596
|
const right = Buffer.from(b);
|
|
144431
144597
|
if (left.length === 0 || left.length !== right.length) return false;
|
|
144432
|
-
return
|
|
144598
|
+
return NodeCrypto8.timingSafeEqual(left, right);
|
|
144433
144599
|
};
|
|
144434
|
-
var computeSignature = (token, timestamp, nonce, encrypt) =>
|
|
144600
|
+
var computeSignature = (token, timestamp, nonce, encrypt) => NodeCrypto8.createHash("sha1").update([token, timestamp, nonce, encrypt].sort().join("")).digest("hex");
|
|
144435
144601
|
var verifySignature = (token, timestamp, nonce, encrypt, signature) => timingSafeEqualString2(computeSignature(token, timestamp, nonce, encrypt), signature);
|
|
144436
144602
|
var decrypt = (encodingAESKey, encryptText, expectReceiveId) => {
|
|
144437
144603
|
const { key, iv } = parseEncodingAESKey(encodingAESKey);
|
|
144438
|
-
const decipher =
|
|
144604
|
+
const decipher = NodeCrypto8.createDecipheriv("aes-256-cbc", key, iv);
|
|
144439
144605
|
decipher.setAutoPadding(false);
|
|
144440
144606
|
let deciphered;
|
|
144441
144607
|
try {
|
|
@@ -144494,10 +144660,10 @@ var createWecomAppCrypto = (input) => {
|
|
|
144494
144660
|
decrypt: (encryptText) => decrypt(encodingAESKey, encryptText, corpId).message
|
|
144495
144661
|
};
|
|
144496
144662
|
};
|
|
144497
|
-
var deriveCallbackPathSecret = (token, encodingAESKey) =>
|
|
144663
|
+
var deriveCallbackPathSecret = (token, encodingAESKey) => NodeCrypto8.createHash("sha256").update(`${token.trim()}:${encodingAESKey.trim()}`).digest("hex").slice(0, 24);
|
|
144498
144664
|
|
|
144499
144665
|
// src/wecomAppParse.ts
|
|
144500
|
-
var
|
|
144666
|
+
var isRecord5 = (value2) => value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
|
|
144501
144667
|
var isXmlFormat = (raw) => {
|
|
144502
144668
|
const trimmed = raw.trim();
|
|
144503
144669
|
return trimmed.startsWith("<") && trimmed.endsWith(">");
|
|
@@ -144543,7 +144709,7 @@ var parseWecomAppPlainMessage = (raw) => {
|
|
|
144543
144709
|
} catch {
|
|
144544
144710
|
return null;
|
|
144545
144711
|
}
|
|
144546
|
-
if (!
|
|
144712
|
+
if (!isRecord5(data)) return null;
|
|
144547
144713
|
const fromRaw = data["from"];
|
|
144548
144714
|
const textRaw = data["text"];
|
|
144549
144715
|
const imageRaw = data["image"];
|
|
@@ -144552,10 +144718,10 @@ var parseWecomAppPlainMessage = (raw) => {
|
|
|
144552
144718
|
msgtype: String(data["msgtype"] ?? data["MsgType"] ?? "").toLowerCase(),
|
|
144553
144719
|
createTime: data["createTime"] !== void 0 ? String(data["createTime"]) : data["CreateTime"] !== void 0 ? String(data["CreateTime"]) : void 0,
|
|
144554
144720
|
agentId: data["agentid"] !== void 0 ? String(data["agentid"]) : data["AgentID"] !== void 0 ? String(data["AgentID"]) : void 0,
|
|
144555
|
-
from:
|
|
144721
|
+
from: isRecord5(fromRaw) ? { userid: typeof fromRaw["userid"] === "string" ? fromRaw["userid"] : void 0 } : typeof data["FromUserName"] === "string" ? { userid: data["FromUserName"] } : void 0,
|
|
144556
144722
|
to: typeof data["to"] === "string" ? data["to"] : void 0,
|
|
144557
|
-
text:
|
|
144558
|
-
image:
|
|
144723
|
+
text: isRecord5(textRaw) ? { content: typeof textRaw["content"] === "string" ? textRaw["content"] : void 0 } : void 0,
|
|
144724
|
+
image: isRecord5(imageRaw) ? { url: typeof imageRaw["url"] === "string" ? imageRaw["url"] : void 0 } : void 0,
|
|
144559
144725
|
mediaId: typeof data["mediaid"] === "string" ? data["mediaid"] : void 0,
|
|
144560
144726
|
recognition: typeof data["recognition"] === "string" ? data["recognition"] : void 0,
|
|
144561
144727
|
event: String(data["event"] ?? data["eventtype"] ?? "").toLowerCase() || void 0,
|
|
@@ -145221,10 +145387,16 @@ var makeWecomAppAdapter = (deps) => {
|
|
|
145221
145387
|
};
|
|
145222
145388
|
|
|
145223
145389
|
// src/index.ts
|
|
145224
|
-
var
|
|
145390
|
+
var definition = {
|
|
145225
145391
|
id: "im",
|
|
145226
|
-
apiVersion:
|
|
145227
|
-
activate: async (ctx) => {
|
|
145392
|
+
apiVersion: 19,
|
|
145393
|
+
activate: async (ctx, inboundIo) => {
|
|
145394
|
+
const inboundState = makeInboundStore({
|
|
145395
|
+
dataDir: ctx.paths.dataDir,
|
|
145396
|
+
log: ctx.log,
|
|
145397
|
+
io: inboundIo
|
|
145398
|
+
});
|
|
145399
|
+
ctx.onDispose(inboundState.flush);
|
|
145228
145400
|
const { t, setLanguage } = makeLiveTranslate(
|
|
145229
145401
|
parseReplyLanguage(ctx.config[REPLY_LANGUAGE_FIELD])
|
|
145230
145402
|
);
|
|
@@ -145246,6 +145418,8 @@ var imPlugin = definePlugin({
|
|
|
145246
145418
|
// Telegram 在不少网络里要绕代理,而绕不绕、绕哪个是按行配的 —— 这是插件面上
|
|
145247
145419
|
// `ctx.proxies` 的第一个真实消费者。
|
|
145248
145420
|
fetchVia: (proxy) => ctx.proxies.fetch(proxy),
|
|
145421
|
+
readCursor: inboundState.readCursor,
|
|
145422
|
+
saveCursor: inboundState.saveCursor,
|
|
145249
145423
|
translate: t,
|
|
145250
145424
|
log: {
|
|
145251
145425
|
info: (message, fields) => ctx.log.info(message, fields),
|
|
@@ -145302,7 +145476,8 @@ var imPlugin = definePlugin({
|
|
|
145302
145476
|
config: () => ctx.config,
|
|
145303
145477
|
derivedState: ctx.derivedState,
|
|
145304
145478
|
t,
|
|
145305
|
-
adapters
|
|
145479
|
+
adapters,
|
|
145480
|
+
inboundReady: inboundState.ready
|
|
145306
145481
|
});
|
|
145307
145482
|
const acknowledgements = makeAcknowledgements(core);
|
|
145308
145483
|
const failures = makeFailureNotices(core);
|
|
@@ -145353,6 +145528,7 @@ var imPlugin = definePlugin({
|
|
|
145353
145528
|
});
|
|
145354
145529
|
const chatSetup = makeChatSetup(core, {
|
|
145355
145530
|
rows: projectRows,
|
|
145531
|
+
resumeMessage: (bot, message) => inbound.resumeMessage(bot, message),
|
|
145356
145532
|
openPicker: (chatKey, rows, reply) => panelWiring.panel.openProjects(chatKey, rows, reply)
|
|
145357
145533
|
});
|
|
145358
145534
|
const commands = makeCommands(core, {
|
|
@@ -145365,10 +145541,10 @@ var imPlugin = definePlugin({
|
|
|
145365
145541
|
openPanel: (chatKey, reply) => panelWiring.panel.open(chatKey, reply)
|
|
145366
145542
|
});
|
|
145367
145543
|
const inbound = makeInbound(core, {
|
|
145544
|
+
inboundState,
|
|
145368
145545
|
enqueueForChat: chatQueue.enqueueForChat,
|
|
145369
145546
|
commands,
|
|
145370
145547
|
chatSetup,
|
|
145371
|
-
rows: projectRows,
|
|
145372
145548
|
interactions,
|
|
145373
145549
|
approvals,
|
|
145374
145550
|
panelWiring,
|
|
@@ -145412,8 +145588,11 @@ var imPlugin = definePlugin({
|
|
|
145412
145588
|
}
|
|
145413
145589
|
ctx.log.info("chat plugin active", { bots, connecting });
|
|
145414
145590
|
}
|
|
145415
|
-
}
|
|
145591
|
+
};
|
|
145592
|
+
var activateImPlugin = definition.activate;
|
|
145593
|
+
var imPlugin = definePlugin(definition);
|
|
145416
145594
|
var index_default = imPlugin;
|
|
145417
145595
|
export {
|
|
145596
|
+
activateImPlugin,
|
|
145418
145597
|
index_default as default
|
|
145419
145598
|
};
|