@openclaw/feishu 2026.3.12 → 2026.3.13
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/package.json +1 -1
- package/src/accounts.test.ts +21 -16
- package/src/bot.ts +20 -11
- package/src/config-schema.test.ts +14 -24
- package/src/dedup.ts +103 -0
- package/src/media.test.ts +38 -61
- package/src/media.ts +64 -76
- package/src/monitor.account.ts +19 -18
- package/src/monitor.reaction.test.ts +106 -64
- package/src/monitor.startup.test.ts +16 -30
- package/src/monitor.transport.ts +104 -6
- package/src/monitor.webhook-e2e.test.ts +214 -0
- package/src/monitor.webhook-security.test.ts +9 -97
- package/src/monitor.webhook.test-helpers.ts +98 -0
- package/src/outbound.test.ts +11 -16
- package/src/probe.test.ts +112 -113
- package/src/reactions.ts +20 -27
- package/src/reply-dispatcher.test.ts +65 -143
- package/src/reply-dispatcher.ts +37 -40
- package/src/send.reply-fallback.test.ts +50 -40
- package/src/send.ts +91 -82
package/src/send.ts
CHANGED
|
@@ -43,6 +43,10 @@ function isWithdrawnReplyError(err: unknown): boolean {
|
|
|
43
43
|
type FeishuCreateMessageClient = {
|
|
44
44
|
im: {
|
|
45
45
|
message: {
|
|
46
|
+
reply: (opts: {
|
|
47
|
+
path: { message_id: string };
|
|
48
|
+
data: { content: string; msg_type: string; reply_in_thread?: true };
|
|
49
|
+
}) => Promise<{ code?: number; msg?: string; data?: { message_id?: string } }>;
|
|
46
50
|
create: (opts: {
|
|
47
51
|
params: { receive_id_type: "chat_id" | "email" | "open_id" | "union_id" | "user_id" };
|
|
48
52
|
data: { receive_id: string; content: string; msg_type: string };
|
|
@@ -51,6 +55,30 @@ type FeishuCreateMessageClient = {
|
|
|
51
55
|
};
|
|
52
56
|
};
|
|
53
57
|
|
|
58
|
+
type FeishuMessageSender = {
|
|
59
|
+
id?: string;
|
|
60
|
+
id_type?: string;
|
|
61
|
+
sender_type?: string;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
type FeishuMessageGetItem = {
|
|
65
|
+
message_id?: string;
|
|
66
|
+
chat_id?: string;
|
|
67
|
+
chat_type?: FeishuChatType;
|
|
68
|
+
msg_type?: string;
|
|
69
|
+
body?: { content?: string };
|
|
70
|
+
sender?: FeishuMessageSender;
|
|
71
|
+
create_time?: string;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
type FeishuGetMessageResponse = {
|
|
75
|
+
code?: number;
|
|
76
|
+
msg?: string;
|
|
77
|
+
data?: FeishuMessageGetItem & {
|
|
78
|
+
items?: FeishuMessageGetItem[];
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
|
|
54
82
|
/** Send a direct message as a fallback when a reply target is unavailable. */
|
|
55
83
|
async function sendFallbackDirect(
|
|
56
84
|
client: FeishuCreateMessageClient,
|
|
@@ -74,6 +102,50 @@ async function sendFallbackDirect(
|
|
|
74
102
|
return toFeishuSendResult(response, params.receiveId);
|
|
75
103
|
}
|
|
76
104
|
|
|
105
|
+
async function sendReplyOrFallbackDirect(
|
|
106
|
+
client: FeishuCreateMessageClient,
|
|
107
|
+
params: {
|
|
108
|
+
replyToMessageId?: string;
|
|
109
|
+
replyInThread?: boolean;
|
|
110
|
+
content: string;
|
|
111
|
+
msgType: string;
|
|
112
|
+
directParams: {
|
|
113
|
+
receiveId: string;
|
|
114
|
+
receiveIdType: "chat_id" | "email" | "open_id" | "union_id" | "user_id";
|
|
115
|
+
content: string;
|
|
116
|
+
msgType: string;
|
|
117
|
+
};
|
|
118
|
+
directErrorPrefix: string;
|
|
119
|
+
replyErrorPrefix: string;
|
|
120
|
+
},
|
|
121
|
+
): Promise<FeishuSendResult> {
|
|
122
|
+
if (!params.replyToMessageId) {
|
|
123
|
+
return sendFallbackDirect(client, params.directParams, params.directErrorPrefix);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
let response: { code?: number; msg?: string; data?: { message_id?: string } };
|
|
127
|
+
try {
|
|
128
|
+
response = await client.im.message.reply({
|
|
129
|
+
path: { message_id: params.replyToMessageId },
|
|
130
|
+
data: {
|
|
131
|
+
content: params.content,
|
|
132
|
+
msg_type: params.msgType,
|
|
133
|
+
...(params.replyInThread ? { reply_in_thread: true } : {}),
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
} catch (err) {
|
|
137
|
+
if (!isWithdrawnReplyError(err)) {
|
|
138
|
+
throw err;
|
|
139
|
+
}
|
|
140
|
+
return sendFallbackDirect(client, params.directParams, params.directErrorPrefix);
|
|
141
|
+
}
|
|
142
|
+
if (shouldFallbackFromReplyTarget(response)) {
|
|
143
|
+
return sendFallbackDirect(client, params.directParams, params.directErrorPrefix);
|
|
144
|
+
}
|
|
145
|
+
assertFeishuMessageApiSuccess(response, params.replyErrorPrefix);
|
|
146
|
+
return toFeishuSendResult(response, params.directParams.receiveId);
|
|
147
|
+
}
|
|
148
|
+
|
|
77
149
|
function parseInteractiveCardContent(parsed: unknown): string {
|
|
78
150
|
if (!parsed || typeof parsed !== "object") {
|
|
79
151
|
return "[Interactive Card]";
|
|
@@ -166,36 +238,7 @@ export async function getMessageFeishu(params: {
|
|
|
166
238
|
try {
|
|
167
239
|
const response = (await client.im.message.get({
|
|
168
240
|
path: { message_id: messageId },
|
|
169
|
-
})) as
|
|
170
|
-
code?: number;
|
|
171
|
-
msg?: string;
|
|
172
|
-
data?: {
|
|
173
|
-
items?: Array<{
|
|
174
|
-
message_id?: string;
|
|
175
|
-
chat_id?: string;
|
|
176
|
-
chat_type?: FeishuChatType;
|
|
177
|
-
msg_type?: string;
|
|
178
|
-
body?: { content?: string };
|
|
179
|
-
sender?: {
|
|
180
|
-
id?: string;
|
|
181
|
-
id_type?: string;
|
|
182
|
-
sender_type?: string;
|
|
183
|
-
};
|
|
184
|
-
create_time?: string;
|
|
185
|
-
}>;
|
|
186
|
-
message_id?: string;
|
|
187
|
-
chat_id?: string;
|
|
188
|
-
chat_type?: FeishuChatType;
|
|
189
|
-
msg_type?: string;
|
|
190
|
-
body?: { content?: string };
|
|
191
|
-
sender?: {
|
|
192
|
-
id?: string;
|
|
193
|
-
id_type?: string;
|
|
194
|
-
sender_type?: string;
|
|
195
|
-
};
|
|
196
|
-
create_time?: string;
|
|
197
|
-
};
|
|
198
|
-
};
|
|
241
|
+
})) as FeishuGetMessageResponse;
|
|
199
242
|
|
|
200
243
|
if (response.code !== 0) {
|
|
201
244
|
return null;
|
|
@@ -290,32 +333,15 @@ export async function sendMessageFeishu(
|
|
|
290
333
|
const { content, msgType } = buildFeishuPostMessagePayload({ messageText });
|
|
291
334
|
|
|
292
335
|
const directParams = { receiveId, receiveIdType, content, msgType };
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
...(replyInThread ? { reply_in_thread: true } : {}),
|
|
303
|
-
},
|
|
304
|
-
});
|
|
305
|
-
} catch (err) {
|
|
306
|
-
if (!isWithdrawnReplyError(err)) {
|
|
307
|
-
throw err;
|
|
308
|
-
}
|
|
309
|
-
return sendFallbackDirect(client, directParams, "Feishu send failed");
|
|
310
|
-
}
|
|
311
|
-
if (shouldFallbackFromReplyTarget(response)) {
|
|
312
|
-
return sendFallbackDirect(client, directParams, "Feishu send failed");
|
|
313
|
-
}
|
|
314
|
-
assertFeishuMessageApiSuccess(response, "Feishu reply failed");
|
|
315
|
-
return toFeishuSendResult(response, receiveId);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
return sendFallbackDirect(client, directParams, "Feishu send failed");
|
|
336
|
+
return sendReplyOrFallbackDirect(client, {
|
|
337
|
+
replyToMessageId,
|
|
338
|
+
replyInThread,
|
|
339
|
+
content,
|
|
340
|
+
msgType,
|
|
341
|
+
directParams,
|
|
342
|
+
directErrorPrefix: "Feishu send failed",
|
|
343
|
+
replyErrorPrefix: "Feishu reply failed",
|
|
344
|
+
});
|
|
319
345
|
}
|
|
320
346
|
|
|
321
347
|
export type SendFeishuCardParams = {
|
|
@@ -334,32 +360,15 @@ export async function sendCardFeishu(params: SendFeishuCardParams): Promise<Feis
|
|
|
334
360
|
const content = JSON.stringify(card);
|
|
335
361
|
|
|
336
362
|
const directParams = { receiveId, receiveIdType, content, msgType: "interactive" };
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
...(replyInThread ? { reply_in_thread: true } : {}),
|
|
347
|
-
},
|
|
348
|
-
});
|
|
349
|
-
} catch (err) {
|
|
350
|
-
if (!isWithdrawnReplyError(err)) {
|
|
351
|
-
throw err;
|
|
352
|
-
}
|
|
353
|
-
return sendFallbackDirect(client, directParams, "Feishu card send failed");
|
|
354
|
-
}
|
|
355
|
-
if (shouldFallbackFromReplyTarget(response)) {
|
|
356
|
-
return sendFallbackDirect(client, directParams, "Feishu card send failed");
|
|
357
|
-
}
|
|
358
|
-
assertFeishuMessageApiSuccess(response, "Feishu card reply failed");
|
|
359
|
-
return toFeishuSendResult(response, receiveId);
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
return sendFallbackDirect(client, directParams, "Feishu card send failed");
|
|
363
|
+
return sendReplyOrFallbackDirect(client, {
|
|
364
|
+
replyToMessageId,
|
|
365
|
+
replyInThread,
|
|
366
|
+
content,
|
|
367
|
+
msgType: "interactive",
|
|
368
|
+
directParams,
|
|
369
|
+
directErrorPrefix: "Feishu card send failed",
|
|
370
|
+
replyErrorPrefix: "Feishu card reply failed",
|
|
371
|
+
});
|
|
363
372
|
}
|
|
364
373
|
|
|
365
374
|
export async function updateCardFeishu(params: {
|