Skip to content

Commit 0563470

Browse files
committed
fix(feishu): bound quick action launcher expiry
1 parent 536c009 commit 0563470

2 files changed

Lines changed: 34 additions & 1 deletion

File tree

extensions/feishu/src/card-ux-launcher.test.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,25 @@ describe("feishu quick-action launcher", () => {
8888
expectFirstSentCardUsesFillWidthOnly(sendCardFeishuMock);
8989
});
9090

91+
it("does not send launcher cards when expiry would exceed a valid Date", async () => {
92+
const runtime: RuntimeEnv = createRuntimeEnv();
93+
94+
const handled = await maybeHandleFeishuQuickActionMenu({
95+
cfg,
96+
eventKey: "quick-actions",
97+
operatorOpenId: "u123",
98+
accountId: "main",
99+
runtime,
100+
now: 8_640_000_000_000_000,
101+
});
102+
103+
expect(handled).toBe(false);
104+
expect(sendCardFeishuMock).not.toHaveBeenCalled();
105+
expect(runtime.log).toHaveBeenCalledWith(
106+
"feishu[main]: failed to open quick-action launcher for u123: invalid expiry clock",
107+
);
108+
});
109+
91110
it("falls back to legacy menu handling when launcher send fails", async () => {
92111
sendCardFeishuMock.mockRejectedValueOnce(new Error("network"));
93112
const runtime: RuntimeEnv = createRuntimeEnv();

extensions/feishu/src/card-ux-launcher.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import {
2+
asDateTimestampMs,
3+
resolveExpiresAtMsFromDurationMs,
4+
} from "openclaw/plugin-sdk/number-runtime";
15
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
26
import type { ClawdbotConfig, RuntimeEnv } from "../runtime-api.js";
37
import { createFeishuCardInteractionEnvelope } from "./card-interaction.js";
@@ -96,7 +100,17 @@ export async function maybeHandleFeishuQuickActionMenu(params: {
96100
return false;
97101
}
98102

99-
const expiresAt = (params.now ?? Date.now()) + FEISHU_QUICK_ACTION_CARD_TTL_MS;
103+
const now = asDateTimestampMs(params.now ?? Date.now());
104+
const expiresAt =
105+
now === undefined
106+
? undefined
107+
: resolveExpiresAtMsFromDurationMs(FEISHU_QUICK_ACTION_CARD_TTL_MS, { nowMs: now });
108+
if (expiresAt === undefined) {
109+
params.runtime?.log?.(
110+
`feishu[${params.accountId ?? "default"}]: failed to open quick-action launcher for ${params.operatorOpenId}: invalid expiry clock`,
111+
);
112+
return false;
113+
}
100114
try {
101115
await sendCardFeishu({
102116
cfg: params.cfg,

0 commit comments

Comments
 (0)