ylib-wecom-openclaw-plugin 2026.4.29
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/README.md +596 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +99 -0
- package/dist/src/accounts.d.ts +57 -0
- package/dist/src/accounts.js +247 -0
- package/dist/src/agent/api-client.d.ts +95 -0
- package/dist/src/agent/api-client.js +425 -0
- package/dist/src/agent/handler.d.ts +64 -0
- package/dist/src/agent/handler.js +731 -0
- package/dist/src/agent/index.d.ts +5 -0
- package/dist/src/agent/index.js +21 -0
- package/dist/src/agent/webhook.d.ts +25 -0
- package/dist/src/agent/webhook.js +294 -0
- package/dist/src/agent/xml.d.ts +21 -0
- package/dist/src/agent/xml.js +43 -0
- package/dist/src/channel.d.ts +5 -0
- package/dist/src/channel.js +815 -0
- package/dist/src/chat-queue.d.ts +31 -0
- package/dist/src/chat-queue.js +53 -0
- package/dist/src/config-schema.d.ts +587 -0
- package/dist/src/config-schema.js +146 -0
- package/dist/src/const.d.ts +128 -0
- package/dist/src/const.js +168 -0
- package/dist/src/dm-policy.d.ts +29 -0
- package/dist/src/dm-policy.js +146 -0
- package/dist/src/dynamic-agent.d.ts +37 -0
- package/dist/src/dynamic-agent.js +67 -0
- package/dist/src/dynamic-routing.d.ts +65 -0
- package/dist/src/dynamic-routing.js +62 -0
- package/dist/src/endpoint-dispatch.d.ts +54 -0
- package/dist/src/endpoint-dispatch.js +967 -0
- package/dist/src/endpoint-event-adapter.d.ts +15 -0
- package/dist/src/endpoint-event-adapter.js +427 -0
- package/dist/src/group-policy.d.ts +30 -0
- package/dist/src/group-policy.js +126 -0
- package/dist/src/http.d.ts +27 -0
- package/dist/src/http.js +168 -0
- package/dist/src/im-runtime-telemetry.d.ts +25 -0
- package/dist/src/im-runtime-telemetry.js +68 -0
- package/dist/src/interface.d.ts +192 -0
- package/dist/src/interface.js +5 -0
- package/dist/src/markdown-chunk.d.ts +1 -0
- package/dist/src/markdown-chunk.js +396 -0
- package/dist/src/mcp/index.d.ts +6 -0
- package/dist/src/mcp/index.js +28 -0
- package/dist/src/mcp/interceptors/biz-error.d.ts +11 -0
- package/dist/src/mcp/interceptors/biz-error.js +73 -0
- package/dist/src/mcp/interceptors/doc-auth-error.d.ts +10 -0
- package/dist/src/mcp/interceptors/doc-auth-error.js +235 -0
- package/dist/src/mcp/interceptors/index.d.ts +35 -0
- package/dist/src/mcp/interceptors/index.js +143 -0
- package/dist/src/mcp/interceptors/msg-media.d.ts +11 -0
- package/dist/src/mcp/interceptors/msg-media.js +201 -0
- package/dist/src/mcp/interceptors/smartpage-create.d.ts +30 -0
- package/dist/src/mcp/interceptors/smartpage-create.js +252 -0
- package/dist/src/mcp/interceptors/smartpage-export.d.ts +17 -0
- package/dist/src/mcp/interceptors/smartpage-export.js +135 -0
- package/dist/src/mcp/interceptors/smartsheet-upload.d.ts +22 -0
- package/dist/src/mcp/interceptors/smartsheet-upload.js +388 -0
- package/dist/src/mcp/interceptors/types.d.ts +64 -0
- package/dist/src/mcp/interceptors/types.js +8 -0
- package/dist/src/mcp/schema.d.ts +11 -0
- package/dist/src/mcp/schema.js +115 -0
- package/dist/src/mcp/tool.d.ts +63 -0
- package/dist/src/mcp/tool.js +318 -0
- package/dist/src/mcp/transport.d.ts +94 -0
- package/dist/src/mcp/transport.js +702 -0
- package/dist/src/media-handler.d.ts +55 -0
- package/dist/src/media-handler.js +306 -0
- package/dist/src/media-uploader.d.ts +142 -0
- package/dist/src/media-uploader.js +446 -0
- package/dist/src/message-parser.d.ts +104 -0
- package/dist/src/message-parser.js +232 -0
- package/dist/src/message-sender.d.ts +54 -0
- package/dist/src/message-sender.js +210 -0
- package/dist/src/monitor.d.ts +69 -0
- package/dist/src/monitor.js +1846 -0
- package/dist/src/onboarding.d.ts +8 -0
- package/dist/src/onboarding.js +248 -0
- package/dist/src/openclaw-compat.d.ts +148 -0
- package/dist/src/openclaw-compat.js +839 -0
- package/dist/src/proactive-markdown-send.d.ts +14 -0
- package/dist/src/proactive-markdown-send.js +205 -0
- package/dist/src/reqid-store.d.ts +23 -0
- package/dist/src/reqid-store.js +136 -0
- package/dist/src/runtime.d.ts +2 -0
- package/dist/src/runtime.js +7 -0
- package/dist/src/shared/command-auth.d.ts +23 -0
- package/dist/src/shared/command-auth.js +112 -0
- package/dist/src/shared/xml-parser.d.ts +46 -0
- package/dist/src/shared/xml-parser.js +228 -0
- package/dist/src/state-dir-resolve.d.ts +2 -0
- package/dist/src/state-dir-resolve.js +33 -0
- package/dist/src/state-manager.d.ts +115 -0
- package/dist/src/state-manager.js +413 -0
- package/dist/src/target.d.ts +35 -0
- package/dist/src/target.js +71 -0
- package/dist/src/template-card-manager.d.ts +55 -0
- package/dist/src/template-card-manager.js +316 -0
- package/dist/src/template-card-parser.d.ts +37 -0
- package/dist/src/template-card-parser.js +672 -0
- package/dist/src/timeout.d.ts +20 -0
- package/dist/src/timeout.js +57 -0
- package/dist/src/types/account.d.ts +29 -0
- package/dist/src/types/account.js +5 -0
- package/dist/src/types/config.d.ts +98 -0
- package/dist/src/types/config.js +8 -0
- package/dist/src/types/constants.d.ts +42 -0
- package/dist/src/types/constants.js +45 -0
- package/dist/src/types/index.d.ts +7 -0
- package/dist/src/types/index.js +17 -0
- package/dist/src/types/message.d.ts +238 -0
- package/dist/src/types/message.js +6 -0
- package/dist/src/utils.d.ts +148 -0
- package/dist/src/utils.js +92 -0
- package/dist/src/version.d.ts +2 -0
- package/dist/src/version.js +28 -0
- package/dist/src/webhook/command-auth.d.ts +47 -0
- package/dist/src/webhook/command-auth.js +137 -0
- package/dist/src/webhook/gateway.d.ts +36 -0
- package/dist/src/webhook/gateway.js +297 -0
- package/dist/src/webhook/handler.d.ts +19 -0
- package/dist/src/webhook/handler.js +481 -0
- package/dist/src/webhook/helpers.d.ts +157 -0
- package/dist/src/webhook/helpers.js +936 -0
- package/dist/src/webhook/http.d.ts +27 -0
- package/dist/src/webhook/http.js +168 -0
- package/dist/src/webhook/index.d.ts +11 -0
- package/dist/src/webhook/index.js +43 -0
- package/dist/src/webhook/media.d.ts +30 -0
- package/dist/src/webhook/media.js +152 -0
- package/dist/src/webhook/monitor.d.ts +59 -0
- package/dist/src/webhook/monitor.js +1672 -0
- package/dist/src/webhook/state.d.ts +220 -0
- package/dist/src/webhook/state.js +568 -0
- package/dist/src/webhook/target.d.ts +41 -0
- package/dist/src/webhook/target.js +165 -0
- package/dist/src/webhook/types.d.ts +348 -0
- package/dist/src/webhook/types.js +36 -0
- package/dist/src/webhook/video-frame.d.ts +13 -0
- package/dist/src/webhook/video-frame.js +108 -0
- package/openclaw.plugin.json +19 -0
- package/package.json +96 -0
- package/schema.json +534 -0
- package/scripts/generate-schema.mjs +33 -0
- package/skills/wecom-contact/SKILL.md +162 -0
- package/skills/wecom-doc/SKILL.md +162 -0
- package/skills/wecom-doc/references/create-doc.md +56 -0
- package/skills/wecom-doc/references/edit-doc-content.md +68 -0
- package/skills/wecom-doc/references/get-doc-content.md +88 -0
- package/skills/wecom-doc/references/smartpage-create.md +125 -0
- package/skills/wecom-doc/references/smartpage-export.md +160 -0
- package/skills/wecom-meeting/SKILL.md +441 -0
- package/skills/wecom-meeting/references/example-full.md +30 -0
- package/skills/wecom-meeting/references/example-reminder.md +46 -0
- package/skills/wecom-meeting/references/example-security.md +22 -0
- package/skills/wecom-meeting/references/response-get-meeting-info.md +148 -0
- package/skills/wecom-msg/SKILL.md +157 -0
- package/skills/wecom-msg/references/api-get-messages.md +93 -0
- package/skills/wecom-msg/references/api-get-msg-chat-list.md +58 -0
- package/skills/wecom-msg/references/api-get-msg-media.md +44 -0
- package/skills/wecom-msg/references/api-send-message.md +39 -0
- package/skills/wecom-preflight/SKILL.md +141 -0
- package/skills/wecom-schedule/SKILL.md +161 -0
- package/skills/wecom-schedule/references/api-check-availability.md +56 -0
- package/skills/wecom-schedule/references/api-create-schedule.md +38 -0
- package/skills/wecom-schedule/references/api-get-schedule-detail.md +81 -0
- package/skills/wecom-schedule/references/api-update-schedule.md +32 -0
- package/skills/wecom-schedule/references/ref-reminders.md +24 -0
- package/skills/wecom-send-media/SKILL.md +68 -0
- package/skills/wecom-send-template-card/SKILL.md +157 -0
- package/skills/wecom-send-template-card/references/api-template-card-types.md +358 -0
- package/skills/wecom-smartsheet/SKILL.md +164 -0
- package/skills/wecom-smartsheet/references/smartsheet-cell-value-formats.md +163 -0
- package/skills/wecom-smartsheet/references/smartsheet-field-types.md +44 -0
- package/skills/wecom-smartsheet/references/smartsheet-get-records.md +96 -0
- package/skills/wecom-smartsheet/references/webhook-examples.md +185 -0
- package/skills/wecom-smartsheet/references/webhook-fallback.md +184 -0
- package/skills/wecom-todo/SKILL.md +392 -0
- package/skills/wecom-todo/examples/workflows.md +163 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* WeCom Agent 模块导出
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
8
|
+
}) : (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
o[k2] = m[k];
|
|
11
|
+
}));
|
|
12
|
+
exports.__esModule = true;
|
|
13
|
+
var handler_js_1 = require("./handler.js");
|
|
14
|
+
__createBinding(exports, handler_js_1, "handleAgentWebhook");
|
|
15
|
+
__createBinding(exports, handler_js_1, "type");
|
|
16
|
+
var api_client_js_1 = require("./api-client.js");
|
|
17
|
+
__createBinding(exports, api_client_js_1, "getAccessToken");
|
|
18
|
+
__createBinding(exports, api_client_js_1, "sendText");
|
|
19
|
+
__createBinding(exports, api_client_js_1, "uploadMedia");
|
|
20
|
+
__createBinding(exports, api_client_js_1, "sendMedia");
|
|
21
|
+
__createBinding(exports, api_client_js_1, "downloadMedia");
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Webhook HTTP 入口
|
|
3
|
+
*
|
|
4
|
+
* 职责:
|
|
5
|
+
* 1. 管理 AgentWebhookTarget 注册表(多账号共用同一 path 时按签名选中)
|
|
6
|
+
* 2. GET → echostr URL 验证
|
|
7
|
+
* 3. POST → XML body 解密 → 调用 handleAgentWebhook
|
|
8
|
+
*/
|
|
9
|
+
/// <reference types="node" />
|
|
10
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
11
|
+
import type { OpenClawConfig, PluginRuntime } from "ylib-openclaw/plugin-sdk";
|
|
12
|
+
import type { ResolvedAgentAccount } from "../types/index.js";
|
|
13
|
+
export declare type AgentWebhookTarget = {
|
|
14
|
+
agent: ResolvedAgentAccount;
|
|
15
|
+
config: OpenClawConfig;
|
|
16
|
+
runtime: {
|
|
17
|
+
log?: (msg: string) => void;
|
|
18
|
+
error?: (msg: string) => void;
|
|
19
|
+
};
|
|
20
|
+
path: string;
|
|
21
|
+
};
|
|
22
|
+
export declare function registerAgentWebhookTarget(target: AgentWebhookTarget): void;
|
|
23
|
+
export declare function deregisterAgentWebhookTarget(accountId: string): void;
|
|
24
|
+
export declare function createWecomAgentWebhookHandler(runtime: PluginRuntime): (req: IncomingMessage, res: ServerResponse) => Promise<boolean | void>;
|
|
25
|
+
export declare function handleWecomAgentWebhookRequest(req: IncomingMessage, res: ServerResponse, runtime: PluginRuntime): Promise<boolean | void>;
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Agent Webhook HTTP 入口
|
|
4
|
+
*
|
|
5
|
+
* 职责:
|
|
6
|
+
* 1. 管理 AgentWebhookTarget 注册表(多账号共用同一 path 时按签名选中)
|
|
7
|
+
* 2. GET → echostr URL 验证
|
|
8
|
+
* 3. POST → XML body 解密 → 调用 handleAgentWebhook
|
|
9
|
+
*/
|
|
10
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
11
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
12
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
13
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
14
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
15
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
16
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
20
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
21
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
22
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
23
|
+
function step(op) {
|
|
24
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
25
|
+
while (_) try {
|
|
26
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
27
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
28
|
+
switch (op[0]) {
|
|
29
|
+
case 0: case 1: t = op; break;
|
|
30
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
31
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
32
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
33
|
+
default:
|
|
34
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
35
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
36
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
37
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
38
|
+
if (t[2]) _.ops.pop();
|
|
39
|
+
_.trys.pop(); continue;
|
|
40
|
+
}
|
|
41
|
+
op = body.call(thisArg, _);
|
|
42
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
43
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
47
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
48
|
+
};
|
|
49
|
+
exports.__esModule = true;
|
|
50
|
+
exports.handleWecomAgentWebhookRequest = exports.createWecomAgentWebhookHandler = exports.deregisterAgentWebhookTarget = exports.registerAgentWebhookTarget = void 0;
|
|
51
|
+
var node_crypto_1 = __importDefault(require("node:crypto"));
|
|
52
|
+
var aibot_node_sdk_1 = require("@wecom/aibot-node-sdk");
|
|
53
|
+
var xml_js_1 = require("./xml.js");
|
|
54
|
+
var xml_parser_js_1 = require("../shared/xml-parser.js");
|
|
55
|
+
var index_js_1 = require("./index.js");
|
|
56
|
+
var const_js_1 = require("../const.js");
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// Target Registry
|
|
59
|
+
// ============================================================================
|
|
60
|
+
var agentTargets = new Map();
|
|
61
|
+
function registerAgentWebhookTarget(target) {
|
|
62
|
+
var _a;
|
|
63
|
+
var list = (_a = agentTargets.get(target.path)) !== null && _a !== void 0 ? _a : [];
|
|
64
|
+
list.push(target);
|
|
65
|
+
agentTargets.set(target.path, list);
|
|
66
|
+
}
|
|
67
|
+
exports.registerAgentWebhookTarget = registerAgentWebhookTarget;
|
|
68
|
+
function deregisterAgentWebhookTarget(accountId) {
|
|
69
|
+
for (var _i = 0, agentTargets_1 = agentTargets; _i < agentTargets_1.length; _i++) {
|
|
70
|
+
var _a = agentTargets_1[_i], path = _a[0], list = _a[1];
|
|
71
|
+
var filtered = list.filter(function (t) { return t.agent.accountId !== accountId; });
|
|
72
|
+
if (filtered.length === 0) {
|
|
73
|
+
agentTargets["delete"](path);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
agentTargets.set(path, filtered);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.deregisterAgentWebhookTarget = deregisterAgentWebhookTarget;
|
|
81
|
+
// ============================================================================
|
|
82
|
+
// Helpers
|
|
83
|
+
// ============================================================================
|
|
84
|
+
function normalizeWebhookPath(raw) {
|
|
85
|
+
var trimmed = raw.trim();
|
|
86
|
+
if (!trimmed)
|
|
87
|
+
return "/";
|
|
88
|
+
var withSlash = trimmed.startsWith("/") ? trimmed : "/" + trimmed;
|
|
89
|
+
if (withSlash.length > 1 && withSlash.endsWith("/"))
|
|
90
|
+
return withSlash.slice(0, -1);
|
|
91
|
+
return withSlash;
|
|
92
|
+
}
|
|
93
|
+
function resolvePath(req) {
|
|
94
|
+
var _a;
|
|
95
|
+
var url = new URL((_a = req.url) !== null && _a !== void 0 ? _a : "/", "http://localhost");
|
|
96
|
+
return normalizeWebhookPath(url.pathname || "/");
|
|
97
|
+
}
|
|
98
|
+
function resolveQueryParams(req) {
|
|
99
|
+
var _a;
|
|
100
|
+
var url = new URL((_a = req.url) !== null && _a !== void 0 ? _a : "/", "http://localhost");
|
|
101
|
+
return url.searchParams;
|
|
102
|
+
}
|
|
103
|
+
function resolveSignatureParam(params) {
|
|
104
|
+
var _a, _b, _c;
|
|
105
|
+
return ((_c = (_b = (_a = params.get("msg_signature")) !== null && _a !== void 0 ? _a : params.get("msgsignature")) !== null && _b !== void 0 ? _b : params.get("signature")) !== null && _c !== void 0 ? _c : "");
|
|
106
|
+
}
|
|
107
|
+
function readTextBody(req, maxBytes) {
|
|
108
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
109
|
+
var chunks, total;
|
|
110
|
+
return __generator(this, function (_a) {
|
|
111
|
+
switch (_a.label) {
|
|
112
|
+
case 0:
|
|
113
|
+
chunks = [];
|
|
114
|
+
total = 0;
|
|
115
|
+
return [4 /*yield*/, new Promise(function (resolve) {
|
|
116
|
+
req.on("data", function (chunk) {
|
|
117
|
+
total += chunk.length;
|
|
118
|
+
if (total > maxBytes) {
|
|
119
|
+
resolve({ ok: false, error: "payload too large" });
|
|
120
|
+
req.destroy();
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
chunks.push(chunk);
|
|
124
|
+
});
|
|
125
|
+
req.on("end", function () {
|
|
126
|
+
resolve({ ok: true, value: Buffer.concat(chunks).toString("utf8") });
|
|
127
|
+
});
|
|
128
|
+
req.on("error", function (err) {
|
|
129
|
+
resolve({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
130
|
+
});
|
|
131
|
+
})];
|
|
132
|
+
case 1: return [2 /*return*/, _a.sent()];
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
function normalizeAgentIdValue(value) {
|
|
138
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
139
|
+
return value;
|
|
140
|
+
var raw = String(value !== null && value !== void 0 ? value : "").trim();
|
|
141
|
+
if (!raw)
|
|
142
|
+
return undefined;
|
|
143
|
+
var parsed = Number(raw);
|
|
144
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
145
|
+
}
|
|
146
|
+
// ============================================================================
|
|
147
|
+
// Main HTTP handler
|
|
148
|
+
// ============================================================================
|
|
149
|
+
function createWecomAgentWebhookHandler(runtime) {
|
|
150
|
+
return function (req, res) {
|
|
151
|
+
return handleWecomAgentWebhookRequest(req, res, runtime);
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
exports.createWecomAgentWebhookHandler = createWecomAgentWebhookHandler;
|
|
155
|
+
function handleWecomAgentWebhookRequest(req, res, runtime) {
|
|
156
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
157
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
158
|
+
var path, reqId, isAgentPath, targets, query, timestamp, nonce, signature, echostr_1, matched_1, reason, selected_1, wc, plain, rawBody, encrypted, matched, reason, selected, decrypted, parsed, wc, inboundAgentId, core;
|
|
159
|
+
return __generator(this, function (_l) {
|
|
160
|
+
switch (_l.label) {
|
|
161
|
+
case 0:
|
|
162
|
+
path = resolvePath(req);
|
|
163
|
+
reqId = node_crypto_1["default"].randomUUID().slice(0, 8);
|
|
164
|
+
isAgentPath = path === const_js_1.WEBHOOK_PATHS.AGENT ||
|
|
165
|
+
path === const_js_1.WEBHOOK_PATHS.AGENT_PLUGIN ||
|
|
166
|
+
path.startsWith(const_js_1.WEBHOOK_PATHS.AGENT + "/") ||
|
|
167
|
+
path.startsWith(const_js_1.WEBHOOK_PATHS.AGENT_PLUGIN + "/");
|
|
168
|
+
targets = (_a = agentTargets.get(path)) !== null && _a !== void 0 ? _a : [];
|
|
169
|
+
if (targets.length === 0) {
|
|
170
|
+
if (isAgentPath) {
|
|
171
|
+
res.statusCode = 404;
|
|
172
|
+
res.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
173
|
+
res.end("agent not configured - Agent 模式未配置");
|
|
174
|
+
return [2 /*return*/, true];
|
|
175
|
+
}
|
|
176
|
+
return [2 /*return*/, false];
|
|
177
|
+
}
|
|
178
|
+
query = resolveQueryParams(req);
|
|
179
|
+
timestamp = (_b = query.get("timestamp")) !== null && _b !== void 0 ? _b : "";
|
|
180
|
+
nonce = (_c = query.get("nonce")) !== null && _c !== void 0 ? _c : "";
|
|
181
|
+
signature = resolveSignatureParam(query);
|
|
182
|
+
// ── GET: echostr URL 验证 ──────────────────────────────────────────
|
|
183
|
+
if (req.method === "GET") {
|
|
184
|
+
echostr_1 = (_d = query.get("echostr")) !== null && _d !== void 0 ? _d : "";
|
|
185
|
+
matched_1 = targets.filter(function (t) {
|
|
186
|
+
var wc = new aibot_node_sdk_1.WecomCrypto(t.agent.token, t.agent.encodingAESKey, t.agent.corpId);
|
|
187
|
+
return wc.verifySignature(signature, timestamp, nonce, echostr_1);
|
|
188
|
+
});
|
|
189
|
+
if (matched_1.length !== 1) {
|
|
190
|
+
reason = matched_1.length === 0 ? "account_not_found" : "account_conflict";
|
|
191
|
+
res.statusCode = 401;
|
|
192
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
193
|
+
res.end(JSON.stringify({ error: reason, message: "Agent callback " + reason + ": signature verification failed." }));
|
|
194
|
+
return [2 /*return*/, true];
|
|
195
|
+
}
|
|
196
|
+
selected_1 = matched_1[0];
|
|
197
|
+
try {
|
|
198
|
+
wc = new aibot_node_sdk_1.WecomCrypto(selected_1.agent.token, selected_1.agent.encodingAESKey, selected_1.agent.corpId);
|
|
199
|
+
plain = wc.decrypt(echostr_1);
|
|
200
|
+
res.statusCode = 200;
|
|
201
|
+
res.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
202
|
+
res.end(plain);
|
|
203
|
+
return [2 /*return*/, true];
|
|
204
|
+
}
|
|
205
|
+
catch (_m) {
|
|
206
|
+
res.statusCode = 400;
|
|
207
|
+
res.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
208
|
+
res.end("decrypt failed - 解密失败,请检查 EncodingAESKey");
|
|
209
|
+
return [2 /*return*/, true];
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// ── POST: XML 消息回调 ─────────────────────────────────────────────
|
|
213
|
+
if (req.method !== "POST")
|
|
214
|
+
return [2 /*return*/, false];
|
|
215
|
+
return [4 /*yield*/, readTextBody(req, const_js_1.LIMITS.MAX_REQUEST_BODY_SIZE)];
|
|
216
|
+
case 1:
|
|
217
|
+
rawBody = _l.sent();
|
|
218
|
+
if (!rawBody.ok) {
|
|
219
|
+
res.statusCode = 400;
|
|
220
|
+
res.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
221
|
+
res.end(rawBody.error || "invalid payload");
|
|
222
|
+
return [2 /*return*/, true];
|
|
223
|
+
}
|
|
224
|
+
encrypted = "";
|
|
225
|
+
try {
|
|
226
|
+
encrypted = xml_js_1.extractEncryptFromXml(rawBody.value);
|
|
227
|
+
}
|
|
228
|
+
catch (_o) {
|
|
229
|
+
res.statusCode = 400;
|
|
230
|
+
res.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
231
|
+
res.end("invalid xml - 缺少 Encrypt 字段");
|
|
232
|
+
return [2 /*return*/, true];
|
|
233
|
+
}
|
|
234
|
+
matched = targets.filter(function (t) {
|
|
235
|
+
var wc = new aibot_node_sdk_1.WecomCrypto(t.agent.token, t.agent.encodingAESKey, t.agent.corpId);
|
|
236
|
+
return wc.verifySignature(signature, timestamp, nonce, encrypted);
|
|
237
|
+
});
|
|
238
|
+
if (matched.length !== 1) {
|
|
239
|
+
reason = matched.length === 0 ? "account_not_found" : "account_conflict";
|
|
240
|
+
res.statusCode = 401;
|
|
241
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
242
|
+
res.end(JSON.stringify({ error: reason, message: "Agent callback " + reason + ": signature verification failed." }));
|
|
243
|
+
return [2 /*return*/, true];
|
|
244
|
+
}
|
|
245
|
+
selected = matched[0];
|
|
246
|
+
decrypted = "";
|
|
247
|
+
parsed = null;
|
|
248
|
+
try {
|
|
249
|
+
wc = new aibot_node_sdk_1.WecomCrypto(selected.agent.token, selected.agent.encodingAESKey, selected.agent.corpId);
|
|
250
|
+
decrypted = wc.decrypt(encrypted);
|
|
251
|
+
parsed = xml_parser_js_1.parseXml(decrypted);
|
|
252
|
+
}
|
|
253
|
+
catch (_p) {
|
|
254
|
+
res.statusCode = 400;
|
|
255
|
+
res.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
256
|
+
res.end("decrypt failed - 解密失败,请检查 EncodingAESKey");
|
|
257
|
+
return [2 /*return*/, true];
|
|
258
|
+
}
|
|
259
|
+
if (!parsed) {
|
|
260
|
+
res.statusCode = 400;
|
|
261
|
+
res.setHeader("Content-Type", "text/plain; charset=utf-8");
|
|
262
|
+
res.end("invalid xml - XML 解析失败");
|
|
263
|
+
return [2 /*return*/, true];
|
|
264
|
+
}
|
|
265
|
+
inboundAgentId = normalizeAgentIdValue(xml_parser_js_1.extractAgentId(parsed));
|
|
266
|
+
if (inboundAgentId !== undefined &&
|
|
267
|
+
selected.agent.agentId !== undefined &&
|
|
268
|
+
inboundAgentId !== selected.agent.agentId) {
|
|
269
|
+
(_f = (_e = selected.runtime).error) === null || _f === void 0 ? void 0 : _f.call(_e, "[wecom] inbound(agent): reqId=" + reqId + " accountId=" + selected.agent.accountId + " agentId_mismatch expected=" + selected.agent.agentId + " actual=" + inboundAgentId);
|
|
270
|
+
}
|
|
271
|
+
core = runtime;
|
|
272
|
+
(_h = (_g = selected.runtime).log) === null || _h === void 0 ? void 0 : _h.call(_g, "[wecom] inbound(agent): reqId=" + reqId + " method=POST remote=" + ((_k = (_j = req.socket) === null || _j === void 0 ? void 0 : _j.remoteAddress) !== null && _k !== void 0 ? _k : "unknown") + " accountId=" + selected.agent.accountId);
|
|
273
|
+
return [2 /*return*/, index_js_1.handleAgentWebhook({
|
|
274
|
+
req: req,
|
|
275
|
+
res: res,
|
|
276
|
+
verifiedPost: {
|
|
277
|
+
timestamp: timestamp,
|
|
278
|
+
nonce: nonce,
|
|
279
|
+
signature: signature,
|
|
280
|
+
encrypted: encrypted,
|
|
281
|
+
decrypted: decrypted,
|
|
282
|
+
parsed: parsed
|
|
283
|
+
},
|
|
284
|
+
agent: selected.agent,
|
|
285
|
+
config: selected.config,
|
|
286
|
+
core: core,
|
|
287
|
+
log: selected.runtime.log,
|
|
288
|
+
error: selected.runtime.error
|
|
289
|
+
})];
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
exports.handleWecomAgentWebhookRequest = handleWecomAgentWebhookRequest;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeCom XML 加解密辅助函数
|
|
3
|
+
* 用于 Agent 模式处理 XML 格式回调
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* 从 XML 密文中提取 Encrypt 字段
|
|
7
|
+
*/
|
|
8
|
+
export declare function extractEncryptFromXml(xml: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* 从 XML 中提取 ToUserName (CorpID)
|
|
11
|
+
*/
|
|
12
|
+
export declare function extractToUserNameFromXml(xml: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* 构建加密 XML 响应
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildEncryptedXmlResponse(params: {
|
|
17
|
+
encrypt: string;
|
|
18
|
+
signature: string;
|
|
19
|
+
timestamp: string;
|
|
20
|
+
nonce: string;
|
|
21
|
+
}): string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* WeCom XML 加解密辅助函数
|
|
4
|
+
* 用于 Agent 模式处理 XML 格式回调
|
|
5
|
+
*/
|
|
6
|
+
exports.__esModule = true;
|
|
7
|
+
exports.buildEncryptedXmlResponse = exports.extractToUserNameFromXml = exports.extractEncryptFromXml = void 0;
|
|
8
|
+
/**
|
|
9
|
+
* 从 XML 密文中提取 Encrypt 字段
|
|
10
|
+
*/
|
|
11
|
+
function extractEncryptFromXml(xml) {
|
|
12
|
+
var match = /<Encrypt><!\[CDATA\[(.*?)\]\]><\/Encrypt>/s.exec(xml);
|
|
13
|
+
if (!(match === null || match === void 0 ? void 0 : match[1])) {
|
|
14
|
+
// 尝试不带 CDATA 的格式
|
|
15
|
+
var altMatch = /<Encrypt>(.*?)<\/Encrypt>/s.exec(xml);
|
|
16
|
+
if (!(altMatch === null || altMatch === void 0 ? void 0 : altMatch[1])) {
|
|
17
|
+
throw new Error("Invalid XML: missing Encrypt field");
|
|
18
|
+
}
|
|
19
|
+
return altMatch[1];
|
|
20
|
+
}
|
|
21
|
+
return match[1];
|
|
22
|
+
}
|
|
23
|
+
exports.extractEncryptFromXml = extractEncryptFromXml;
|
|
24
|
+
/**
|
|
25
|
+
* 从 XML 中提取 ToUserName (CorpID)
|
|
26
|
+
*/
|
|
27
|
+
function extractToUserNameFromXml(xml) {
|
|
28
|
+
var _a;
|
|
29
|
+
var match = /<ToUserName><!\[CDATA\[(.*?)\]\]><\/ToUserName>/s.exec(xml);
|
|
30
|
+
if (!(match === null || match === void 0 ? void 0 : match[1])) {
|
|
31
|
+
var altMatch = /<ToUserName>(.*?)<\/ToUserName>/s.exec(xml);
|
|
32
|
+
return (_a = altMatch === null || altMatch === void 0 ? void 0 : altMatch[1]) !== null && _a !== void 0 ? _a : "";
|
|
33
|
+
}
|
|
34
|
+
return match[1];
|
|
35
|
+
}
|
|
36
|
+
exports.extractToUserNameFromXml = extractToUserNameFromXml;
|
|
37
|
+
/**
|
|
38
|
+
* 构建加密 XML 响应
|
|
39
|
+
*/
|
|
40
|
+
function buildEncryptedXmlResponse(params) {
|
|
41
|
+
return "<xml>\n<Encrypt><![CDATA[" + params.encrypt + "]]></Encrypt>\n<MsgSignature><![CDATA[" + params.signature + "]]></MsgSignature>\n<TimeStamp>" + params.timestamp + "</TimeStamp>\n<Nonce><![CDATA[" + params.nonce + "]]></Nonce>\n</xml>";
|
|
42
|
+
}
|
|
43
|
+
exports.buildEncryptedXmlResponse = buildEncryptedXmlResponse;
|