fix: unify control command handling
This commit is contained in:
@@ -21,12 +21,13 @@ import type { ThinkLevel, VerboseLevel } from "../thinking.js";
|
||||
import type { ReplyPayload } from "../types.js";
|
||||
import { isAbortTrigger, setAbortMemory } from "./abort.js";
|
||||
import { stripMentions } from "./mentions.js";
|
||||
import type { InlineDirectives } from "./directive-handling.js";
|
||||
|
||||
export type CommandContext = {
|
||||
surface: string;
|
||||
isWhatsAppSurface: boolean;
|
||||
ownerList: string[];
|
||||
isOwnerSender: boolean;
|
||||
isAuthorizedSender: boolean;
|
||||
senderE164?: string;
|
||||
abortKey?: string;
|
||||
rawBodyNormalized: string;
|
||||
@@ -41,8 +42,16 @@ export function buildCommandContext(params: {
|
||||
sessionKey?: string;
|
||||
isGroup: boolean;
|
||||
triggerBodyNormalized: string;
|
||||
commandAuthorized: boolean;
|
||||
}): CommandContext {
|
||||
const { ctx, cfg, sessionKey, isGroup, triggerBodyNormalized } = params;
|
||||
const {
|
||||
ctx,
|
||||
cfg,
|
||||
sessionKey,
|
||||
isGroup,
|
||||
triggerBodyNormalized,
|
||||
commandAuthorized,
|
||||
} = params;
|
||||
const surface = (ctx.Surface ?? "").trim().toLowerCase();
|
||||
const isWhatsAppSurface =
|
||||
surface === "whatsapp" ||
|
||||
@@ -80,14 +89,13 @@ export function buildCommandContext(params: {
|
||||
const ownerList = ownerCandidates
|
||||
.map((entry) => normalizeE164(entry))
|
||||
.filter((entry): entry is string => Boolean(entry));
|
||||
const isOwnerSender =
|
||||
Boolean(senderE164) && ownerList.includes(senderE164 ?? "");
|
||||
const isAuthorizedSender = commandAuthorized;
|
||||
|
||||
return {
|
||||
surface,
|
||||
isWhatsAppSurface,
|
||||
ownerList,
|
||||
isOwnerSender,
|
||||
isAuthorizedSender,
|
||||
senderE164: senderE164 || undefined,
|
||||
abortKey,
|
||||
rawBodyNormalized,
|
||||
@@ -101,6 +109,7 @@ export async function handleCommands(params: {
|
||||
ctx: MsgContext;
|
||||
cfg: ClawdbotConfig;
|
||||
command: CommandContext;
|
||||
directives: InlineDirectives;
|
||||
sessionEntry?: SessionEntry;
|
||||
sessionStore?: Record<string, SessionEntry>;
|
||||
sessionKey?: string;
|
||||
@@ -122,6 +131,7 @@ export async function handleCommands(params: {
|
||||
const {
|
||||
cfg,
|
||||
command,
|
||||
directives,
|
||||
sessionEntry,
|
||||
sessionStore,
|
||||
sessionKey,
|
||||
@@ -151,9 +161,9 @@ export async function handleCommands(params: {
|
||||
reply: { text: "⚙️ Group activation only applies to group chats." },
|
||||
};
|
||||
}
|
||||
if (!command.isOwnerSender) {
|
||||
if (!command.isAuthorizedSender) {
|
||||
logVerbose(
|
||||
`Ignoring /activation from non-owner in group: ${command.senderE164 || "<unknown>"}`,
|
||||
`Ignoring /activation from unauthorized sender in group: ${command.senderE164 || "<unknown>"}`,
|
||||
);
|
||||
return { shouldContinue: false };
|
||||
}
|
||||
@@ -179,9 +189,9 @@ export async function handleCommands(params: {
|
||||
}
|
||||
|
||||
if (sendPolicyCommand.hasCommand) {
|
||||
if (!command.isOwnerSender) {
|
||||
if (!command.isAuthorizedSender) {
|
||||
logVerbose(
|
||||
`Ignoring /send from non-owner: ${command.senderE164 || "<unknown>"}`,
|
||||
`Ignoring /send from unauthorized sender: ${command.senderE164 || "<unknown>"}`,
|
||||
);
|
||||
return { shouldContinue: false };
|
||||
}
|
||||
@@ -220,9 +230,9 @@ export async function handleCommands(params: {
|
||||
command.commandBodyNormalized === "restart" ||
|
||||
command.commandBodyNormalized.startsWith("/restart ")
|
||||
) {
|
||||
if (isGroup && !command.isOwnerSender) {
|
||||
if (!command.isAuthorizedSender) {
|
||||
logVerbose(
|
||||
`Ignoring /restart from non-owner in group: ${command.senderE164 || "<unknown>"}`,
|
||||
`Ignoring /restart from unauthorized sender: ${command.senderE164 || "<unknown>"}`,
|
||||
);
|
||||
return { shouldContinue: false };
|
||||
}
|
||||
@@ -235,14 +245,15 @@ export async function handleCommands(params: {
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
const statusRequested =
|
||||
directives.hasStatusDirective ||
|
||||
command.commandBodyNormalized === "/status" ||
|
||||
command.commandBodyNormalized === "status" ||
|
||||
command.commandBodyNormalized.startsWith("/status ")
|
||||
) {
|
||||
if (isGroup && !command.isOwnerSender) {
|
||||
command.commandBodyNormalized.startsWith("/status ");
|
||||
if (statusRequested) {
|
||||
if (!command.isAuthorizedSender) {
|
||||
logVerbose(
|
||||
`Ignoring /status from non-owner in group: ${command.senderE164 || "<unknown>"}`,
|
||||
`Ignoring /status from unauthorized sender: ${command.senderE164 || "<unknown>"}`,
|
||||
);
|
||||
return { shouldContinue: false };
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import type { ReplyPayload } from "../types.js";
|
||||
import {
|
||||
type ElevatedLevel,
|
||||
extractElevatedDirective,
|
||||
extractStatusDirective,
|
||||
extractThinkDirective,
|
||||
extractVerboseDirective,
|
||||
type ThinkLevel,
|
||||
@@ -49,6 +50,7 @@ export type InlineDirectives = {
|
||||
hasElevatedDirective: boolean;
|
||||
elevatedLevel?: ElevatedLevel;
|
||||
rawElevatedLevel?: string;
|
||||
hasStatusDirective: boolean;
|
||||
hasModelDirective: boolean;
|
||||
rawModelDirective?: string;
|
||||
hasQueueDirective: boolean;
|
||||
@@ -83,11 +85,15 @@ export function parseInlineDirectives(body: string): InlineDirectives {
|
||||
rawLevel: rawElevatedLevel,
|
||||
hasDirective: hasElevatedDirective,
|
||||
} = extractElevatedDirective(verboseCleaned);
|
||||
const {
|
||||
cleaned: statusCleaned,
|
||||
hasDirective: hasStatusDirective,
|
||||
} = extractStatusDirective(elevatedCleaned);
|
||||
const {
|
||||
cleaned: modelCleaned,
|
||||
rawModel,
|
||||
hasDirective: hasModelDirective,
|
||||
} = extractModelDirective(elevatedCleaned);
|
||||
} = extractModelDirective(statusCleaned);
|
||||
const {
|
||||
cleaned: queueCleaned,
|
||||
queueMode,
|
||||
@@ -114,6 +120,7 @@ export function parseInlineDirectives(body: string): InlineDirectives {
|
||||
hasElevatedDirective,
|
||||
elevatedLevel,
|
||||
rawElevatedLevel,
|
||||
hasStatusDirective,
|
||||
hasModelDirective,
|
||||
rawModelDirective: rawModel,
|
||||
hasQueueDirective,
|
||||
|
||||
@@ -74,4 +74,19 @@ export function extractElevatedDirective(body?: string): {
|
||||
};
|
||||
}
|
||||
|
||||
export function extractStatusDirective(body?: string): {
|
||||
cleaned: string;
|
||||
hasDirective: boolean;
|
||||
} {
|
||||
if (!body) return { cleaned: "", hasDirective: false };
|
||||
const match = body.match(/(?:^|\s)\/status(?=$|\s|:)\b/i);
|
||||
const cleaned = match
|
||||
? body.replace(match[0], "").replace(/\s+/g, " ").trim()
|
||||
: body.trim();
|
||||
return {
|
||||
cleaned,
|
||||
hasDirective: !!match,
|
||||
};
|
||||
}
|
||||
|
||||
export type { ElevatedLevel, ThinkLevel, VerboseLevel };
|
||||
|
||||
Reference in New Issue
Block a user