mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-04 11:44:04 +00:00
fix(slack): validate inbound timestamp parsing
This commit is contained in:
@@ -707,6 +707,18 @@ describe("slack prepareSlackMessage inbound contract", () => {
|
||||
expect(prepared?.ackReactionPromise).toBeNull();
|
||||
});
|
||||
|
||||
it("does not coerce malformed Slack timestamps into inbound event times", async () => {
|
||||
const prepared = await prepareWithDefaultCtx(
|
||||
createSlackMessage({
|
||||
ts: "0x10",
|
||||
}),
|
||||
);
|
||||
|
||||
assertPrepared(prepared);
|
||||
expect(prepared.ctxPayload.Timestamp).toBeUndefined();
|
||||
expect(prepared.ctxPayload.MessageSid).toBe("0x10");
|
||||
});
|
||||
|
||||
it("primes Slack status reactions when channel replies are message-tool-only", async () => {
|
||||
const slackCtx = createInboundSlackCtx({
|
||||
cfg: {
|
||||
|
||||
@@ -83,6 +83,7 @@ const SLACK_HISTORY_MEDIA_MAX_ATTACHMENTS = 4;
|
||||
const SLACK_HISTORY_MEDIA_MAX_BYTES = 10 * 1024 * 1024;
|
||||
const SLACK_HISTORY_MEDIA_IDLE_TIMEOUT_MS = 1_000;
|
||||
const SLACK_HISTORY_MEDIA_TOTAL_TIMEOUT_MS = 3_000;
|
||||
const SLACK_TIMESTAMP_RE = /^\d+(?:\.\d+)?$/;
|
||||
|
||||
function recordString(
|
||||
record: Record<string, unknown> | undefined,
|
||||
@@ -104,6 +105,15 @@ function recordNullableString(
|
||||
return normalizeOptionalString(record[key]);
|
||||
}
|
||||
|
||||
function resolveSlackTimestampMs(ts: string | undefined): number | undefined {
|
||||
const trimmed = ts?.trim();
|
||||
if (!trimmed || !SLACK_TIMESTAMP_RE.test(trimmed)) {
|
||||
return undefined;
|
||||
}
|
||||
const parsed = Number(trimmed);
|
||||
return Number.isFinite(parsed) ? Math.round(parsed * 1000) : undefined;
|
||||
}
|
||||
|
||||
function mergeSlackAssistantThreadContext(
|
||||
primary: Omit<SlackAssistantThreadContext, "updatedAt"> | undefined,
|
||||
fallback: Omit<SlackAssistantThreadContext, "updatedAt"> | undefined,
|
||||
@@ -969,7 +979,7 @@ export async function prepareSlackMessage(params: {
|
||||
client: ctx.app.client,
|
||||
})
|
||||
: null;
|
||||
const timestamp = message.ts ? Math.round(Number(message.ts) * 1000) : undefined;
|
||||
const timestamp = resolveSlackTimestampMs(message.ts);
|
||||
const senderName = pendingBody ? await resolveSenderName() : undefined;
|
||||
await recordDroppedChannelInboundHistory({
|
||||
input: {
|
||||
@@ -1145,7 +1155,7 @@ export async function prepareSlackMessage(params: {
|
||||
const body = formatInboundEnvelope({
|
||||
channel: "Slack",
|
||||
from: envelopeFrom,
|
||||
timestamp: message.ts ? Math.round(Number(message.ts) * 1000) : undefined,
|
||||
timestamp: resolveSlackTimestampMs(message.ts),
|
||||
body: textWithId,
|
||||
chatType,
|
||||
sender: { name: senderName, id: senderId },
|
||||
@@ -1238,7 +1248,7 @@ export async function prepareSlackMessage(params: {
|
||||
channel: "slack",
|
||||
accountId: route.accountId,
|
||||
messageId: message.ts,
|
||||
timestamp: message.ts ? Math.round(Number(message.ts) * 1000) : undefined,
|
||||
timestamp: resolveSlackTimestampMs(message.ts),
|
||||
from: slackFrom,
|
||||
sender: {
|
||||
id: senderId,
|
||||
@@ -1335,7 +1345,7 @@ export async function prepareSlackMessage(params: {
|
||||
entry: {
|
||||
sender: senderName,
|
||||
body: rawBody,
|
||||
timestamp: message.ts ? Math.round(Number(message.ts) * 1000) : undefined,
|
||||
timestamp: resolveSlackTimestampMs(message.ts),
|
||||
messageId: message.ts,
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user