mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-04 16:30:30 +00:00
refactor: centralize inbound mention policy
This commit is contained in:
@@ -594,6 +594,45 @@ describe("preflightDiscordMessage", () => {
|
||||
expect(result).not.toBeNull();
|
||||
});
|
||||
|
||||
it("still drops bot control commands without a real mention when allowBots=mentions", async () => {
|
||||
const channelId = "channel-bot-command-no-mention";
|
||||
const guildId = "guild-bot-command-no-mention";
|
||||
const message = createDiscordMessage({
|
||||
id: "m-bot-command-no-mention",
|
||||
channelId,
|
||||
content: "/new incident room",
|
||||
author: {
|
||||
id: "relay-bot-1",
|
||||
bot: true,
|
||||
username: "Relay",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await runMentionOnlyBotPreflight({ channelId, guildId, message });
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("still allows bot control commands with an explicit mention when allowBots=mentions", async () => {
|
||||
const channelId = "channel-bot-command-with-mention";
|
||||
const guildId = "guild-bot-command-with-mention";
|
||||
const message = createDiscordMessage({
|
||||
id: "m-bot-command-with-mention",
|
||||
channelId,
|
||||
content: "<@openclaw-bot> /new incident room",
|
||||
mentionedUsers: [{ id: "openclaw-bot" }],
|
||||
author: {
|
||||
id: "relay-bot-1",
|
||||
bot: true,
|
||||
username: "Relay",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await runMentionOnlyBotPreflight({ channelId, guildId, message });
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
});
|
||||
|
||||
it("treats @everyone as a mention when requireMention is true", async () => {
|
||||
const channelId = "channel-everyone-mention";
|
||||
const guildId = "guild-everyone-mention";
|
||||
|
||||
@@ -3,9 +3,10 @@ import { Routes, type APIMessage } from "discord-api-types/v10";
|
||||
import { formatAllowlistMatchMeta } from "openclaw/plugin-sdk/allow-from";
|
||||
import {
|
||||
buildMentionRegexes,
|
||||
implicitMentionKindWhen,
|
||||
logInboundDrop,
|
||||
matchesMentionWithExplicit,
|
||||
resolveMentionGatingWithBypass,
|
||||
resolveInboundMentionDecision,
|
||||
} from "openclaw/plugin-sdk/channel-inbound";
|
||||
import { resolveControlCommandGate } from "openclaw/plugin-sdk/command-auth-native";
|
||||
import { hasControlCommand } from "openclaw/plugin-sdk/command-detection";
|
||||
@@ -181,10 +182,10 @@ function resolveDiscordMentionState(params: {
|
||||
referencedAuthorId?: string;
|
||||
senderIsPluralKit: boolean;
|
||||
transcript?: string;
|
||||
}): { implicitMention: boolean; wasMentioned: boolean } {
|
||||
}) {
|
||||
if (params.isDirectMessage) {
|
||||
return {
|
||||
implicitMention: false,
|
||||
implicitMentionKinds: [],
|
||||
wasMentioned: false,
|
||||
};
|
||||
}
|
||||
@@ -203,12 +204,15 @@ function resolveDiscordMentionState(params: {
|
||||
},
|
||||
transcript: params.transcript,
|
||||
});
|
||||
const implicitMention = Boolean(
|
||||
params.botId && params.referencedAuthorId && params.referencedAuthorId === params.botId,
|
||||
const implicitMentionKinds = implicitMentionKindWhen(
|
||||
"reply_to_bot",
|
||||
Boolean(params.botId) &&
|
||||
Boolean(params.referencedAuthorId) &&
|
||||
params.referencedAuthorId === params.botId,
|
||||
);
|
||||
|
||||
return {
|
||||
implicitMention,
|
||||
implicitMentionKinds,
|
||||
wasMentioned,
|
||||
};
|
||||
}
|
||||
@@ -887,7 +891,7 @@ export async function preflightDiscordMessage(
|
||||
}
|
||||
|
||||
const mentionText = hasTypedText ? baseText : "";
|
||||
const { implicitMention, wasMentioned } = resolveDiscordMentionState({
|
||||
const { implicitMentionKinds, wasMentioned } = resolveDiscordMentionState({
|
||||
authorIsBot: Boolean(author.bot),
|
||||
botId,
|
||||
hasAnyMention,
|
||||
@@ -946,23 +950,27 @@ export async function preflightDiscordMessage(
|
||||
}
|
||||
|
||||
const canDetectMention = Boolean(botId) || mentionRegexes.length > 0;
|
||||
const mentionGate = resolveMentionGatingWithBypass({
|
||||
isGroup: isGuildMessage,
|
||||
requireMention: Boolean(shouldRequireMention),
|
||||
canDetectMention,
|
||||
wasMentioned,
|
||||
implicitMention,
|
||||
hasAnyMention,
|
||||
allowTextCommands,
|
||||
hasControlCommand: hasControlCommandInMessage,
|
||||
commandAuthorized,
|
||||
const mentionDecision = resolveInboundMentionDecision({
|
||||
facts: {
|
||||
canDetectMention,
|
||||
wasMentioned,
|
||||
hasAnyMention,
|
||||
implicitMentionKinds,
|
||||
},
|
||||
policy: {
|
||||
isGroup: isGuildMessage,
|
||||
requireMention: Boolean(shouldRequireMention),
|
||||
allowTextCommands,
|
||||
hasControlCommand: hasControlCommandInMessage,
|
||||
commandAuthorized,
|
||||
},
|
||||
});
|
||||
const effectiveWasMentioned = mentionGate.effectiveWasMentioned;
|
||||
const effectiveWasMentioned = mentionDecision.effectiveWasMentioned;
|
||||
logDebug(
|
||||
`[discord-preflight] shouldRequireMention=${shouldRequireMention} baseRequireMention=${shouldRequireMentionByConfig} boundThreadSession=${isBoundThreadSession} mentionGate.shouldSkip=${mentionGate.shouldSkip} wasMentioned=${wasMentioned}`,
|
||||
`[discord-preflight] shouldRequireMention=${shouldRequireMention} baseRequireMention=${shouldRequireMentionByConfig} boundThreadSession=${isBoundThreadSession} mentionDecision.shouldSkip=${mentionDecision.shouldSkip} wasMentioned=${wasMentioned}`,
|
||||
);
|
||||
if (isGuildMessage && shouldRequireMention) {
|
||||
if (botId && mentionGate.shouldSkip) {
|
||||
if (botId && mentionDecision.shouldSkip) {
|
||||
logDebug(`[discord-preflight] drop: no-mention`);
|
||||
logVerbose(`discord: drop guild message (mention required, botId=${botId})`);
|
||||
logger.info(
|
||||
@@ -983,7 +991,7 @@ export async function preflightDiscordMessage(
|
||||
}
|
||||
|
||||
if (author.bot && !sender.isPluralKit && allowBotsMode === "mentions") {
|
||||
const botMentioned = isDirectMessage || wasMentioned || implicitMention;
|
||||
const botMentioned = isDirectMessage || wasMentioned || mentionDecision.implicitMention;
|
||||
if (!botMentioned) {
|
||||
logDebug(`[discord-preflight] drop: bot message missing mention (allowBots=mentions)`);
|
||||
logVerbose("discord: drop bot message (allowBots=mentions, missing mention)");
|
||||
@@ -998,7 +1006,7 @@ export async function preflightDiscordMessage(
|
||||
ignoreOtherMentions &&
|
||||
hasUserOrRoleMention &&
|
||||
!wasMentioned &&
|
||||
!implicitMention
|
||||
!mentionDecision.implicitMention
|
||||
) {
|
||||
logDebug(`[discord-preflight] drop: other-mention`);
|
||||
logVerbose(
|
||||
@@ -1103,7 +1111,7 @@ export async function preflightDiscordMessage(
|
||||
shouldRequireMention,
|
||||
hasAnyMention,
|
||||
allowTextCommands,
|
||||
shouldBypassMention: mentionGate.shouldBypassMention,
|
||||
shouldBypassMention: mentionDecision.shouldBypassMention,
|
||||
effectiveWasMentioned,
|
||||
canDetectMention,
|
||||
historyEntry,
|
||||
|
||||
Reference in New Issue
Block a user