mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-18 15:41:39 +00:00
* fix(telegram): rewrite allow-always alias for any whitespace separator * fix(telegram): require absolute approval alias suffix --------- Co-authored-by: moguangyu5-design <moguangyu5-design@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com>
135 lines
4.6 KiB
TypeScript
135 lines
4.6 KiB
TypeScript
// Telegram tests cover approval callback data plugin behavior.
|
|
import { buildApprovalResolutionRef } from "openclaw/plugin-sdk/approval-reference-runtime";
|
|
import { describe, expect, it } from "vitest";
|
|
import {
|
|
buildTelegramApprovalCallbackData,
|
|
fitsTelegramCallbackData,
|
|
parseTelegramApprovalCallbackData,
|
|
rewriteTelegramApprovalDecisionAlias,
|
|
sanitizeTelegramCallbackData,
|
|
} from "./approval-callback-data.js";
|
|
|
|
describe("approval callback data", () => {
|
|
it("enforces Telegram callback byte boundaries", () => {
|
|
expect(fitsTelegramCallbackData("x".repeat(63))).toBe(true);
|
|
expect(fitsTelegramCallbackData("x".repeat(64))).toBe(true);
|
|
expect(fitsTelegramCallbackData("x".repeat(65))).toBe(false);
|
|
});
|
|
|
|
it("rewrites /approve allow-always callbacks to always", () => {
|
|
const approvalId = `plugin:${"a".repeat(36)}`;
|
|
expect(rewriteTelegramApprovalDecisionAlias(`/approve ${approvalId} allow-always`)).toBe(
|
|
`/approve ${approvalId} always`,
|
|
);
|
|
});
|
|
|
|
it("rewrites allow-always callbacks separated by any whitespace", () => {
|
|
const approvalId = `plugin:${"a".repeat(36)}`;
|
|
expect(rewriteTelegramApprovalDecisionAlias(`/approve\t${approvalId}\tallow-always`)).toBe(
|
|
`/approve\t${approvalId}\talways`,
|
|
);
|
|
});
|
|
|
|
it.each(["\n", "\r\n"])("does not corrupt callbacks ending in a line terminator", (ending) => {
|
|
const value = `/approve plugin:abc allow-always${ending}`;
|
|
expect(rewriteTelegramApprovalDecisionAlias(value)).toBe(value);
|
|
});
|
|
|
|
it("keeps rewritten allow-always callbacks when canonical form would overflow", () => {
|
|
const approvalId = `plugin:${"a".repeat(36)}`;
|
|
expect(sanitizeTelegramCallbackData(`/approve ${approvalId} allow-always`)).toBe(
|
|
`/approve ${approvalId} always`,
|
|
);
|
|
});
|
|
|
|
it("keeps 64-byte callbacks and drops 65-byte callbacks through sanitize", () => {
|
|
expect(sanitizeTelegramCallbackData("x".repeat(64))).toBe("x".repeat(64));
|
|
expect(sanitizeTelegramCallbackData("x".repeat(65))).toBeUndefined();
|
|
});
|
|
|
|
it.each([
|
|
["exec", "allow-once", "tga1:e:o:approval:with:delimiters"],
|
|
["exec", "allow-always", "tga1:e:a:approval:with:delimiters"],
|
|
["plugin", "deny", "tga1:p:d:approval:with:delimiters"],
|
|
] as const)("round-trips explicit %s %s actions", (approvalKind, decision, callbackData) => {
|
|
const action = {
|
|
type: "approval" as const,
|
|
approvalId: "approval:with:delimiters",
|
|
approvalKind,
|
|
decision,
|
|
};
|
|
|
|
expect(buildTelegramApprovalCallbackData(action)).toBe(callbackData);
|
|
expect(parseTelegramApprovalCallbackData(callbackData)).toEqual(action);
|
|
});
|
|
|
|
it("does not infer approval kind from id spelling", () => {
|
|
const callbackData = buildTelegramApprovalCallbackData({
|
|
type: "approval",
|
|
approvalId: "plugin:still-an-exec-id",
|
|
approvalKind: "exec",
|
|
decision: "deny",
|
|
});
|
|
|
|
expect(parseTelegramApprovalCallbackData(callbackData)).toEqual({
|
|
type: "approval",
|
|
approvalId: "plugin:still-an-exec-id",
|
|
approvalKind: "exec",
|
|
decision: "deny",
|
|
});
|
|
});
|
|
|
|
it("preserves unicode approval ids exactly", () => {
|
|
const action = {
|
|
type: "approval" as const,
|
|
approvalId: "approval/🦀/%/:",
|
|
approvalKind: "plugin" as const,
|
|
decision: "allow-once" as const,
|
|
};
|
|
const callbackData = buildTelegramApprovalCallbackData(action);
|
|
|
|
expect(parseTelegramApprovalCallbackData(callbackData)).toEqual(action);
|
|
});
|
|
|
|
it("uses the canonical id at the Unicode byte boundary and compacts beyond it", () => {
|
|
const exactId = "\u{1F4F1}".repeat(13);
|
|
const compactedId = "\u{1F4F1}".repeat(14);
|
|
expect(
|
|
buildTelegramApprovalCallbackData({
|
|
type: "approval",
|
|
approvalId: exactId,
|
|
approvalKind: "exec",
|
|
decision: "deny",
|
|
}),
|
|
).toBe(`tga1:e:d:${exactId}`);
|
|
|
|
const compacted = buildTelegramApprovalCallbackData({
|
|
type: "approval",
|
|
approvalId: compactedId,
|
|
approvalKind: "exec",
|
|
decision: "deny",
|
|
});
|
|
expect(compacted).toHaveLength(52);
|
|
expect(parseTelegramApprovalCallbackData(compacted)).toEqual({
|
|
type: "approval",
|
|
approvalId: buildApprovalResolutionRef({
|
|
approvalId: compactedId,
|
|
approvalKind: "exec",
|
|
}),
|
|
approvalKind: "exec",
|
|
decision: "deny",
|
|
});
|
|
});
|
|
|
|
it.each([
|
|
"tga2:e:o:approval-1",
|
|
"tga1:x:o:approval-1",
|
|
"tga1:e:x:approval-1",
|
|
"tga1:e:o:",
|
|
"tga1:e:o",
|
|
`tga1:e:o:${"x".repeat(56)}`,
|
|
])("rejects malformed private approval callback data: %s", (callbackData) => {
|
|
expect(parseTelegramApprovalCallbackData(callbackData)).toBeNull();
|
|
});
|
|
});
|