mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-30 09:30:59 +00:00
fix: align poll duration parsing with strict guard
This commit is contained in:
@@ -48,6 +48,16 @@ describe("readNumberParam", () => {
|
||||
expect(readNumberParam(params, "messageId")).toBe(42);
|
||||
});
|
||||
|
||||
it("keeps partial parse behavior by default", () => {
|
||||
const params = { messageId: "42abc" };
|
||||
expect(readNumberParam(params, "messageId")).toBe(42);
|
||||
});
|
||||
|
||||
it("rejects partial numeric strings when strict is enabled", () => {
|
||||
const params = { messageId: "42abc" };
|
||||
expect(readNumberParam(params, "messageId", { strict: true })).toBeUndefined();
|
||||
});
|
||||
|
||||
it("truncates when integer is true", () => {
|
||||
const params = { messageId: "42.9" };
|
||||
expect(readNumberParam(params, "messageId", { integer: true })).toBe(42);
|
||||
|
||||
@@ -129,9 +129,9 @@ export function readStringOrNumberParam(
|
||||
export function readNumberParam(
|
||||
params: Record<string, unknown>,
|
||||
key: string,
|
||||
options: { required?: boolean; label?: string; integer?: boolean } = {},
|
||||
options: { required?: boolean; label?: string; integer?: boolean; strict?: boolean } = {},
|
||||
): number | undefined {
|
||||
const { required = false, label = key, integer = false } = options;
|
||||
const { required = false, label = key, integer = false, strict = false } = options;
|
||||
const raw = readParamRaw(params, key);
|
||||
let value: number | undefined;
|
||||
if (typeof raw === "number" && Number.isFinite(raw)) {
|
||||
@@ -139,7 +139,7 @@ export function readNumberParam(
|
||||
} else if (typeof raw === "string") {
|
||||
const trimmed = raw.trim();
|
||||
if (trimmed) {
|
||||
const parsed = Number.parseFloat(trimmed);
|
||||
const parsed = strict ? Number(trimmed) : Number.parseFloat(trimmed);
|
||||
if (Number.isFinite(parsed)) {
|
||||
value = parsed;
|
||||
}
|
||||
|
||||
@@ -348,6 +348,25 @@ describe("handleDiscordMessageAction", () => {
|
||||
allowMultiselect: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "rejects partially numeric poll duration for discord poll adapter params",
|
||||
input: {
|
||||
action: "poll" as const,
|
||||
params: {
|
||||
to: "channel:123",
|
||||
pollQuestion: "Ready?",
|
||||
pollOption: ["Yes", "No"],
|
||||
pollDurationHours: "24h",
|
||||
},
|
||||
},
|
||||
expected: {
|
||||
action: "poll",
|
||||
to: "channel:123",
|
||||
question: "Ready?",
|
||||
answers: ["Yes", "No"],
|
||||
durationHours: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "forwards accountId for thread replies",
|
||||
input: {
|
||||
@@ -734,6 +753,30 @@ describe("telegramMessageActions", () => {
|
||||
accountId: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "poll rejects partially numeric duration strings before telegram action handoff",
|
||||
action: "poll" as const,
|
||||
params: {
|
||||
to: "123",
|
||||
pollQuestion: "Ready?",
|
||||
pollOption: ["Yes", "No"],
|
||||
pollDurationSeconds: "60s",
|
||||
},
|
||||
expectedPayload: {
|
||||
action: "poll",
|
||||
to: "123",
|
||||
question: "Ready?",
|
||||
answers: ["Yes", "No"],
|
||||
allowMultiselect: undefined,
|
||||
durationHours: undefined,
|
||||
durationSeconds: undefined,
|
||||
replyToMessageId: undefined,
|
||||
messageThreadId: undefined,
|
||||
isAnonymous: undefined,
|
||||
silent: undefined,
|
||||
accountId: undefined,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "topic-create maps to createForumTopic",
|
||||
action: "topic-create" as const,
|
||||
|
||||
@@ -91,6 +91,7 @@ export async function handleDiscordMessageAction(
|
||||
const allowMultiselect = readBooleanParam(params, "pollMulti");
|
||||
const durationHours = readNumberParam(params, "pollDurationHours", {
|
||||
integer: true,
|
||||
strict: true,
|
||||
});
|
||||
return await handleDiscordAction(
|
||||
{
|
||||
|
||||
@@ -159,9 +159,11 @@ export const telegramMessageActions: ChannelMessageActionAdapter = {
|
||||
const answers = readStringArrayParam(params, "pollOption", { required: true });
|
||||
const durationHours = readNumberParam(params, "pollDurationHours", {
|
||||
integer: true,
|
||||
strict: true,
|
||||
});
|
||||
const durationSeconds = readNumberParam(params, "pollDurationSeconds", {
|
||||
integer: true,
|
||||
strict: true,
|
||||
});
|
||||
const replyToMessageId = readNumberParam(params, "replyTo", { integer: true });
|
||||
const messageThreadId = readNumberParam(params, "threadId", { integer: true });
|
||||
|
||||
@@ -584,9 +584,11 @@ async function handlePollAction(ctx: ResolvedActionContext): Promise<MessageActi
|
||||
const isAnonymous = resolveTelegramPollVisibility({ pollAnonymous, pollPublic });
|
||||
const durationHours = readNumberParam(params, "pollDurationHours", {
|
||||
integer: true,
|
||||
strict: true,
|
||||
});
|
||||
const durationSeconds = readNumberParam(params, "pollDurationSeconds", {
|
||||
integer: true,
|
||||
strict: true,
|
||||
});
|
||||
const maxSelections = resolvePollMaxSelections(options.length, allowMultiselect);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user