@openclaw/feishu 2026.5.2-beta.2 → 2026.5.3-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accounts-Ba3-WP1z.js +423 -0
- package/dist/api.js +2280 -0
- package/dist/app-registration-B8qc1MCM.js +184 -0
- package/dist/audio-preflight.runtime-BPlzkO3l.js +7 -0
- package/dist/card-interaction-BfRLgvw_.js +96 -0
- package/dist/channel-CSD_Jt8I.js +1668 -0
- package/dist/channel-entry.js +22 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel.runtime-DYsXcD36.js +700 -0
- package/dist/client-DBVoQL5w.js +157 -0
- package/dist/contract-api.js +9 -0
- package/dist/conversation-id-DWS3Ep2A.js +139 -0
- package/dist/directory.static-f3EeoRJd.js +44 -0
- package/dist/drive-C5eJLJr7.js +883 -0
- package/dist/index.js +68 -0
- package/dist/monitor-CT189QfR.js +60 -0
- package/dist/monitor.account-dJV2jO8C.js +4990 -0
- package/dist/monitor.state-DYM02ipp.js +100 -0
- package/dist/policy-D6c-wMPl.js +118 -0
- package/dist/probe-BNzzU_uR.js +149 -0
- package/dist/rolldown-runtime-DUslC3ob.js +14 -0
- package/dist/runtime-CG0DuRCy.js +8 -0
- package/dist/runtime-api.js +14 -0
- package/dist/secret-contract-Dm4Z_zQN.js +119 -0
- package/dist/secret-contract-api.js +2 -0
- package/dist/security-audit-DqJdocrN.js +11 -0
- package/dist/security-audit-shared-ByuMx9cJ.js +38 -0
- package/dist/security-contract-api.js +2 -0
- package/dist/send-DowxxbpH.js +1218 -0
- package/dist/session-conversation-B4nrW-vo.js +27 -0
- package/dist/session-key-api.js +2 -0
- package/dist/setup-api.js +2 -0
- package/dist/setup-entry.js +15 -0
- package/dist/subagent-hooks-C3UhPVLV.js +227 -0
- package/dist/subagent-hooks-api.js +23 -0
- package/dist/targets-JMFJRKSe.js +48 -0
- package/dist/thread-bindings-BmS6TLes.js +222 -0
- package/package.json +15 -6
- package/api.ts +0 -31
- package/channel-entry.ts +0 -20
- package/channel-plugin-api.ts +0 -1
- package/contract-api.ts +0 -16
- package/index.ts +0 -82
- package/runtime-api.ts +0 -55
- package/secret-contract-api.ts +0 -5
- package/security-contract-api.ts +0 -1
- package/session-key-api.ts +0 -1
- package/setup-api.ts +0 -3
- package/setup-entry.test.ts +0 -14
- package/setup-entry.ts +0 -13
- package/src/accounts.test.ts +0 -459
- package/src/accounts.ts +0 -326
- package/src/app-registration.ts +0 -331
- package/src/approval-auth.test.ts +0 -24
- package/src/approval-auth.ts +0 -25
- package/src/async.test.ts +0 -35
- package/src/async.ts +0 -104
- package/src/audio-preflight.runtime.ts +0 -9
- package/src/bitable.test.ts +0 -131
- package/src/bitable.ts +0 -762
- package/src/bot-content.ts +0 -474
- package/src/bot-group-name.test.ts +0 -108
- package/src/bot-runtime-api.ts +0 -12
- package/src/bot-sender-name.ts +0 -125
- package/src/bot.broadcast.test.ts +0 -463
- package/src/bot.card-action.test.ts +0 -577
- package/src/bot.checkBotMentioned.test.ts +0 -265
- package/src/bot.helpers.test.ts +0 -118
- package/src/bot.stripBotMention.test.ts +0 -126
- package/src/bot.test.ts +0 -3040
- package/src/bot.ts +0 -1559
- package/src/card-action.ts +0 -447
- package/src/card-interaction.test.ts +0 -129
- package/src/card-interaction.ts +0 -159
- package/src/card-test-helpers.ts +0 -47
- package/src/card-ux-approval.ts +0 -65
- package/src/card-ux-launcher.test.ts +0 -99
- package/src/card-ux-launcher.ts +0 -121
- package/src/card-ux-shared.ts +0 -33
- package/src/channel-runtime-api.ts +0 -16
- package/src/channel.runtime.ts +0 -47
- package/src/channel.test.ts +0 -959
- package/src/channel.ts +0 -1313
- package/src/chat-schema.ts +0 -25
- package/src/chat.test.ts +0 -196
- package/src/chat.ts +0 -188
- package/src/client.test.ts +0 -433
- package/src/client.ts +0 -290
- package/src/comment-dispatcher-runtime-api.ts +0 -6
- package/src/comment-dispatcher.test.ts +0 -169
- package/src/comment-dispatcher.ts +0 -107
- package/src/comment-handler-runtime-api.ts +0 -3
- package/src/comment-handler.test.ts +0 -486
- package/src/comment-handler.ts +0 -309
- package/src/comment-reaction.test.ts +0 -166
- package/src/comment-reaction.ts +0 -259
- package/src/comment-shared.test.ts +0 -182
- package/src/comment-shared.ts +0 -406
- package/src/comment-target.ts +0 -44
- package/src/config-schema.test.ts +0 -309
- package/src/config-schema.ts +0 -333
- package/src/conversation-id.test.ts +0 -18
- package/src/conversation-id.ts +0 -199
- package/src/dedup-runtime-api.ts +0 -1
- package/src/dedup.ts +0 -141
- package/src/directory.static.ts +0 -61
- package/src/directory.test.ts +0 -136
- package/src/directory.ts +0 -124
- package/src/doc-schema.ts +0 -182
- package/src/docx-batch-insert.test.ts +0 -91
- package/src/docx-batch-insert.ts +0 -223
- package/src/docx-color-text.ts +0 -154
- package/src/docx-table-ops.test.ts +0 -53
- package/src/docx-table-ops.ts +0 -316
- package/src/docx-types.ts +0 -38
- package/src/docx.account-selection.test.ts +0 -79
- package/src/docx.test.ts +0 -685
- package/src/docx.ts +0 -1616
- package/src/drive-schema.ts +0 -92
- package/src/drive.test.ts +0 -1219
- package/src/drive.ts +0 -829
- package/src/dynamic-agent.ts +0 -137
- package/src/event-types.ts +0 -45
- package/src/external-keys.test.ts +0 -20
- package/src/external-keys.ts +0 -19
- package/src/lifecycle.test-support.ts +0 -220
- package/src/media.test.ts +0 -900
- package/src/media.ts +0 -861
- package/src/mention-target.types.ts +0 -5
- package/src/mention.ts +0 -114
- package/src/message-action-contract.ts +0 -13
- package/src/monitor-state-runtime-api.ts +0 -7
- package/src/monitor-transport-runtime-api.ts +0 -7
- package/src/monitor.account.ts +0 -468
- package/src/monitor.acp-init-failure.lifecycle.test-support.ts +0 -219
- package/src/monitor.bot-identity.ts +0 -86
- package/src/monitor.bot-menu-handler.ts +0 -165
- package/src/monitor.bot-menu.lifecycle.test-support.ts +0 -224
- package/src/monitor.bot-menu.test.ts +0 -178
- package/src/monitor.broadcast.reply-once.lifecycle.test-support.ts +0 -264
- package/src/monitor.card-action.lifecycle.test-support.ts +0 -373
- package/src/monitor.cleanup.test.ts +0 -376
- package/src/monitor.comment-notice-handler.ts +0 -105
- package/src/monitor.comment.test.ts +0 -937
- package/src/monitor.comment.ts +0 -1386
- package/src/monitor.lifecycle.test.ts +0 -4
- package/src/monitor.message-handler.ts +0 -339
- package/src/monitor.reaction.lifecycle.test-support.ts +0 -68
- package/src/monitor.reaction.test.ts +0 -713
- package/src/monitor.startup.test.ts +0 -192
- package/src/monitor.startup.ts +0 -74
- package/src/monitor.state.defaults.test.ts +0 -46
- package/src/monitor.state.ts +0 -170
- package/src/monitor.synthetic-error.ts +0 -18
- package/src/monitor.test-mocks.ts +0 -45
- package/src/monitor.transport.ts +0 -424
- package/src/monitor.ts +0 -100
- package/src/monitor.webhook-e2e.test.ts +0 -272
- package/src/monitor.webhook-security.test.ts +0 -264
- package/src/monitor.webhook.test-helpers.ts +0 -116
- package/src/outbound-runtime-api.ts +0 -1
- package/src/outbound.test.ts +0 -935
- package/src/outbound.ts +0 -718
- package/src/perm-schema.ts +0 -52
- package/src/perm.ts +0 -170
- package/src/pins.ts +0 -108
- package/src/policy.test.ts +0 -334
- package/src/policy.ts +0 -236
- package/src/post.test.ts +0 -105
- package/src/post.ts +0 -275
- package/src/probe.test.ts +0 -275
- package/src/probe.ts +0 -166
- package/src/processing-claims.ts +0 -59
- package/src/qr-terminal.ts +0 -1
- package/src/reactions.ts +0 -123
- package/src/reasoning-preview.test.ts +0 -59
- package/src/reasoning-preview.ts +0 -20
- package/src/reply-dispatcher-runtime-api.ts +0 -7
- package/src/reply-dispatcher.test.ts +0 -1144
- package/src/reply-dispatcher.ts +0 -650
- package/src/runtime.ts +0 -9
- package/src/secret-contract.ts +0 -145
- package/src/secret-input.ts +0 -1
- package/src/security-audit-shared.ts +0 -69
- package/src/security-audit.test.ts +0 -61
- package/src/security-audit.ts +0 -1
- package/src/send-result.ts +0 -29
- package/src/send-target.test.ts +0 -80
- package/src/send-target.ts +0 -35
- package/src/send.reply-fallback.test.ts +0 -292
- package/src/send.test.ts +0 -550
- package/src/send.ts +0 -800
- package/src/sequential-key.test.ts +0 -72
- package/src/sequential-key.ts +0 -28
- package/src/sequential-queue.test.ts +0 -92
- package/src/sequential-queue.ts +0 -16
- package/src/session-conversation.ts +0 -42
- package/src/session-route.ts +0 -48
- package/src/setup-core.ts +0 -51
- package/src/setup-surface.test.ts +0 -174
- package/src/setup-surface.ts +0 -581
- package/src/streaming-card.test.ts +0 -190
- package/src/streaming-card.ts +0 -490
- package/src/subagent-hooks.test.ts +0 -603
- package/src/subagent-hooks.ts +0 -397
- package/src/targets.ts +0 -97
- package/src/test-support/lifecycle-test-support.ts +0 -453
- package/src/thread-bindings.test.ts +0 -143
- package/src/thread-bindings.ts +0 -330
- package/src/tool-account-routing.test.ts +0 -187
- package/src/tool-account.test.ts +0 -44
- package/src/tool-account.ts +0 -93
- package/src/tool-factory-test-harness.ts +0 -79
- package/src/tool-result.test.ts +0 -32
- package/src/tool-result.ts +0 -16
- package/src/tools-config.test.ts +0 -21
- package/src/tools-config.ts +0 -22
- package/src/types.ts +0 -104
- package/src/typing.test.ts +0 -144
- package/src/typing.ts +0 -214
- package/src/wiki-schema.ts +0 -55
- package/src/wiki.ts +0 -227
- package/subagent-hooks-api.ts +0 -31
- package/tsconfig.json +0 -16
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
2
|
+
import { renderQrTerminal } from "openclaw/plugin-sdk/media-runtime";
|
|
3
|
+
//#region extensions/feishu/src/app-registration.ts
|
|
4
|
+
/**
|
|
5
|
+
* Feishu app registration via OAuth device-code flow.
|
|
6
|
+
*
|
|
7
|
+
* Migrated from feishu-plugin-cli's `feishu-auth.ts` and `install-prompts.ts`.
|
|
8
|
+
* Replaces axios with native fetch, removes inquirer/ora/chalk in favor of
|
|
9
|
+
* the openclaw WizardPrompter surface.
|
|
10
|
+
*/
|
|
11
|
+
const FEISHU_ACCOUNTS_URL = "https://accounts.feishu.cn";
|
|
12
|
+
const LARK_ACCOUNTS_URL = "https://accounts.larksuite.com";
|
|
13
|
+
const REGISTRATION_PATH = "/oauth/v1/app/registration";
|
|
14
|
+
const REQUEST_TIMEOUT_MS = 1e4;
|
|
15
|
+
function accountsBaseUrl(domain) {
|
|
16
|
+
return domain === "lark" ? LARK_ACCOUNTS_URL : FEISHU_ACCOUNTS_URL;
|
|
17
|
+
}
|
|
18
|
+
async function postRegistration(baseUrl, body) {
|
|
19
|
+
return await fetchFeishuJson({
|
|
20
|
+
url: `${baseUrl}${REGISTRATION_PATH}`,
|
|
21
|
+
init: {
|
|
22
|
+
method: "POST",
|
|
23
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
24
|
+
body: new URLSearchParams(body).toString(),
|
|
25
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
26
|
+
},
|
|
27
|
+
auditContext: "feishu.app-registration.post"
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
async function fetchFeishuJson(params) {
|
|
31
|
+
const { response, release } = await fetchWithSsrFGuard({
|
|
32
|
+
url: params.url,
|
|
33
|
+
init: params.init,
|
|
34
|
+
policy: { allowedHostnames: [new URL(params.url).hostname] },
|
|
35
|
+
auditContext: params.auditContext
|
|
36
|
+
});
|
|
37
|
+
try {
|
|
38
|
+
return await response.json();
|
|
39
|
+
} finally {
|
|
40
|
+
await release();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Step 1: Initialize registration and verify the environment supports
|
|
45
|
+
* `client_secret` auth.
|
|
46
|
+
*
|
|
47
|
+
* @throws If the environment does not support `client_secret`.
|
|
48
|
+
*/
|
|
49
|
+
async function initAppRegistration(domain = "feishu") {
|
|
50
|
+
if (!(await postRegistration(accountsBaseUrl(domain), { action: "init" })).supported_auth_methods?.includes("client_secret")) throw new Error("Current environment does not support client_secret auth method");
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Step 2: Begin the device-code flow. Returns a device code and a QR URL
|
|
54
|
+
* that the user should scan with Feishu/Lark mobile app.
|
|
55
|
+
*/
|
|
56
|
+
async function beginAppRegistration(domain = "feishu") {
|
|
57
|
+
const res = await postRegistration(accountsBaseUrl(domain), {
|
|
58
|
+
action: "begin",
|
|
59
|
+
archetype: "PersonalAgent",
|
|
60
|
+
auth_method: "client_secret",
|
|
61
|
+
request_user_info: "open_id"
|
|
62
|
+
});
|
|
63
|
+
const qrUrl = new URL(res.verification_uri_complete);
|
|
64
|
+
qrUrl.searchParams.set("from", "oc_onboard");
|
|
65
|
+
qrUrl.searchParams.set("tp", "ob_cli_app");
|
|
66
|
+
return {
|
|
67
|
+
deviceCode: res.device_code,
|
|
68
|
+
qrUrl: qrUrl.toString(),
|
|
69
|
+
userCode: res.user_code,
|
|
70
|
+
interval: res.interval || 5,
|
|
71
|
+
expireIn: res.expire_in || 600
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Step 3: Poll for authorization result until success, denial, expiry, or
|
|
76
|
+
* timeout. Automatically handles domain switching when `tenant_brand` is
|
|
77
|
+
* detected as "lark".
|
|
78
|
+
*/
|
|
79
|
+
async function pollAppRegistration(params) {
|
|
80
|
+
const { deviceCode, expireIn, initialDomain = "feishu", abortSignal, tp } = params;
|
|
81
|
+
let currentInterval = params.interval;
|
|
82
|
+
let domain = initialDomain;
|
|
83
|
+
let domainSwitched = false;
|
|
84
|
+
const deadline = Date.now() + expireIn * 1e3;
|
|
85
|
+
while (Date.now() < deadline) {
|
|
86
|
+
if (abortSignal?.aborted) return { status: "timeout" };
|
|
87
|
+
const baseUrl = accountsBaseUrl(domain);
|
|
88
|
+
let pollRes;
|
|
89
|
+
try {
|
|
90
|
+
pollRes = await postRegistration(baseUrl, {
|
|
91
|
+
action: "poll",
|
|
92
|
+
device_code: deviceCode,
|
|
93
|
+
...tp ? { tp } : {}
|
|
94
|
+
});
|
|
95
|
+
} catch {
|
|
96
|
+
await sleep(currentInterval * 1e3);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (pollRes.user_info?.tenant_brand) {
|
|
100
|
+
const isLark = pollRes.user_info.tenant_brand === "lark";
|
|
101
|
+
if (!domainSwitched && isLark) {
|
|
102
|
+
domain = "lark";
|
|
103
|
+
domainSwitched = true;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (pollRes.client_id && pollRes.client_secret) return {
|
|
108
|
+
status: "success",
|
|
109
|
+
result: {
|
|
110
|
+
appId: pollRes.client_id,
|
|
111
|
+
appSecret: pollRes.client_secret,
|
|
112
|
+
domain,
|
|
113
|
+
openId: pollRes.user_info?.open_id
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
if (pollRes.error) if (pollRes.error === "authorization_pending") {} else if (pollRes.error === "slow_down") currentInterval += 5;
|
|
117
|
+
else if (pollRes.error === "access_denied") return { status: "access_denied" };
|
|
118
|
+
else if (pollRes.error === "expired_token") return { status: "expired" };
|
|
119
|
+
else return {
|
|
120
|
+
status: "error",
|
|
121
|
+
message: `${pollRes.error}: ${pollRes.error_description ?? "unknown"}`
|
|
122
|
+
};
|
|
123
|
+
await sleep(currentInterval * 1e3);
|
|
124
|
+
}
|
|
125
|
+
return { status: "timeout" };
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Print QR code directly to stdout.
|
|
129
|
+
*
|
|
130
|
+
* QR codes must be printed without any surrounding box/border decoration,
|
|
131
|
+
* otherwise the pattern is corrupted and cannot be scanned.
|
|
132
|
+
*/
|
|
133
|
+
async function printQrCode(url) {
|
|
134
|
+
const output = await renderQrTerminal(url, { small: true });
|
|
135
|
+
process.stdout.write(output.endsWith("\n") ? output : `${output}\n`);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Fetch the app owner's open_id using the application.v6.application.get API.
|
|
139
|
+
*
|
|
140
|
+
* Used during setup to auto-populate security policy allowlists.
|
|
141
|
+
* Returns undefined on any failure (fail-open).
|
|
142
|
+
*/
|
|
143
|
+
async function getAppOwnerOpenId(params) {
|
|
144
|
+
const baseUrl = params.domain === "lark" ? "https://open.larksuite.com" : "https://open.feishu.cn";
|
|
145
|
+
try {
|
|
146
|
+
const tokenData = await fetchFeishuJson({
|
|
147
|
+
url: `${baseUrl}/open-apis/auth/v3/tenant_access_token/internal`,
|
|
148
|
+
init: {
|
|
149
|
+
method: "POST",
|
|
150
|
+
headers: { "Content-Type": "application/json" },
|
|
151
|
+
body: JSON.stringify({
|
|
152
|
+
app_id: params.appId,
|
|
153
|
+
app_secret: params.appSecret
|
|
154
|
+
}),
|
|
155
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
156
|
+
},
|
|
157
|
+
auditContext: "feishu.app-registration.owner-token"
|
|
158
|
+
});
|
|
159
|
+
if (!tokenData.tenant_access_token) return;
|
|
160
|
+
const appData = await fetchFeishuJson({
|
|
161
|
+
url: `${baseUrl}/open-apis/application/v6/applications/${params.appId}?user_id_type=open_id`,
|
|
162
|
+
init: {
|
|
163
|
+
method: "GET",
|
|
164
|
+
headers: {
|
|
165
|
+
Authorization: `Bearer ${tokenData.tenant_access_token}`,
|
|
166
|
+
"Content-Type": "application/json"
|
|
167
|
+
},
|
|
168
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
169
|
+
},
|
|
170
|
+
auditContext: "feishu.app-registration.owner-app"
|
|
171
|
+
});
|
|
172
|
+
if (appData.code !== 0) return;
|
|
173
|
+
const app = appData.data?.app;
|
|
174
|
+
const owner = app?.owner;
|
|
175
|
+
return (owner?.owner_type ?? owner?.type) === 2 && owner?.owner_id ? owner.owner_id : app?.creator_id ?? owner?.owner_id;
|
|
176
|
+
} catch {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function sleep(ms) {
|
|
181
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
182
|
+
}
|
|
183
|
+
//#endregion
|
|
184
|
+
export { beginAppRegistration, getAppOwnerOpenId, initAppRegistration, pollAppRegistration, printQrCode };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { transcribeFirstAudio as transcribeFirstAudio$1 } from "openclaw/plugin-sdk/media-runtime";
|
|
2
|
+
//#region extensions/feishu/src/audio-preflight.runtime.ts
|
|
3
|
+
async function transcribeFirstAudio(...args) {
|
|
4
|
+
return await transcribeFirstAudio$1(...args);
|
|
5
|
+
}
|
|
6
|
+
//#endregion
|
|
7
|
+
export { transcribeFirstAudio };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { f as isRecord } from "./accounts-Ba3-WP1z.js";
|
|
2
|
+
//#region extensions/feishu/src/card-interaction.ts
|
|
3
|
+
const FEISHU_CARD_INTERACTION_VERSION = "ocf1";
|
|
4
|
+
function isInteractionKind(value) {
|
|
5
|
+
return value === "button" || value === "quick" || value === "meta";
|
|
6
|
+
}
|
|
7
|
+
function isMetadataValue(value) {
|
|
8
|
+
return value === null || value === void 0 || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
9
|
+
}
|
|
10
|
+
function createFeishuCardInteractionEnvelope(envelope) {
|
|
11
|
+
return {
|
|
12
|
+
oc: FEISHU_CARD_INTERACTION_VERSION,
|
|
13
|
+
...envelope
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function buildFeishuCardActionTextFallback(event) {
|
|
17
|
+
const actionValue = event.action.value;
|
|
18
|
+
if (isRecord(actionValue)) {
|
|
19
|
+
if (typeof actionValue.text === "string") return actionValue.text;
|
|
20
|
+
if (typeof actionValue.command === "string") return actionValue.command;
|
|
21
|
+
return JSON.stringify(actionValue);
|
|
22
|
+
}
|
|
23
|
+
return String(actionValue);
|
|
24
|
+
}
|
|
25
|
+
function decodeFeishuCardAction(params) {
|
|
26
|
+
const { event, now = Date.now() } = params;
|
|
27
|
+
const actionValue = event.action.value;
|
|
28
|
+
if (!isRecord(actionValue) || actionValue.oc !== "ocf1") return {
|
|
29
|
+
kind: "legacy",
|
|
30
|
+
text: buildFeishuCardActionTextFallback(event)
|
|
31
|
+
};
|
|
32
|
+
if (!isInteractionKind(actionValue.k) || typeof actionValue.a !== "string" || !actionValue.a) return {
|
|
33
|
+
kind: "invalid",
|
|
34
|
+
reason: "malformed"
|
|
35
|
+
};
|
|
36
|
+
if (actionValue.q !== void 0 && typeof actionValue.q !== "string") return {
|
|
37
|
+
kind: "invalid",
|
|
38
|
+
reason: "malformed"
|
|
39
|
+
};
|
|
40
|
+
if (actionValue.m !== void 0) {
|
|
41
|
+
if (!isRecord(actionValue.m)) return {
|
|
42
|
+
kind: "invalid",
|
|
43
|
+
reason: "malformed"
|
|
44
|
+
};
|
|
45
|
+
for (const value of Object.values(actionValue.m)) if (!isMetadataValue(value)) return {
|
|
46
|
+
kind: "invalid",
|
|
47
|
+
reason: "malformed"
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (actionValue.c !== void 0) {
|
|
51
|
+
if (!isRecord(actionValue.c)) return {
|
|
52
|
+
kind: "invalid",
|
|
53
|
+
reason: "malformed"
|
|
54
|
+
};
|
|
55
|
+
if (actionValue.c.u !== void 0 && typeof actionValue.c.u !== "string") return {
|
|
56
|
+
kind: "invalid",
|
|
57
|
+
reason: "malformed"
|
|
58
|
+
};
|
|
59
|
+
if (actionValue.c.h !== void 0 && typeof actionValue.c.h !== "string") return {
|
|
60
|
+
kind: "invalid",
|
|
61
|
+
reason: "malformed"
|
|
62
|
+
};
|
|
63
|
+
if (actionValue.c.s !== void 0 && typeof actionValue.c.s !== "string") return {
|
|
64
|
+
kind: "invalid",
|
|
65
|
+
reason: "malformed"
|
|
66
|
+
};
|
|
67
|
+
if (actionValue.c.e !== void 0 && !Number.isFinite(actionValue.c.e)) return {
|
|
68
|
+
kind: "invalid",
|
|
69
|
+
reason: "malformed"
|
|
70
|
+
};
|
|
71
|
+
if (actionValue.c.t !== void 0 && actionValue.c.t !== "p2p" && actionValue.c.t !== "group") return {
|
|
72
|
+
kind: "invalid",
|
|
73
|
+
reason: "malformed"
|
|
74
|
+
};
|
|
75
|
+
if (typeof actionValue.c.e === "number" && actionValue.c.e < now) return {
|
|
76
|
+
kind: "invalid",
|
|
77
|
+
reason: "stale"
|
|
78
|
+
};
|
|
79
|
+
const expectedUser = actionValue.c.u?.trim();
|
|
80
|
+
if (expectedUser && expectedUser !== (event.operator.open_id ?? "").trim()) return {
|
|
81
|
+
kind: "invalid",
|
|
82
|
+
reason: "wrong_user"
|
|
83
|
+
};
|
|
84
|
+
const expectedChat = actionValue.c.h?.trim();
|
|
85
|
+
if (expectedChat && expectedChat !== (event.context.chat_id ?? "").trim()) return {
|
|
86
|
+
kind: "invalid",
|
|
87
|
+
reason: "wrong_conversation"
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
kind: "structured",
|
|
92
|
+
envelope: actionValue
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { decodeFeishuCardAction as i, buildFeishuCardActionTextFallback as n, createFeishuCardInteractionEnvelope as r, FEISHU_CARD_INTERACTION_VERSION as t };
|