Merge 9491ec9bdb into 4583f88626
This commit is contained in:
commit
8f1231bfce
@ -239,6 +239,18 @@ WhatsApp can automatically send emoji reactions to incoming messages immediately
|
|||||||
- `"mentions"`: React only when bot is @mentioned
|
- `"mentions"`: React only when bot is @mentioned
|
||||||
- `"never"`: Never react in groups
|
- `"never"`: Never react in groups
|
||||||
|
|
||||||
|
**Per-session override:**
|
||||||
|
The global and per-account configurations can be overridden for specific sessions (DMs or Groups) using session configuration (in `sessions.json`).
|
||||||
|
- `ackReaction`: `"always" | "mentions" | "never"`
|
||||||
|
- `"always"`: Enables reactions (overrides global off/never).
|
||||||
|
- `"never"`: Disables reactions (overrides global on/always/mentions).
|
||||||
|
- `"mentions"`: Enforces **strict** mention-only reactions (requires actual @mention, ignores group activation state).
|
||||||
|
- Useful for disabling reactions in specific DMs (`"never"`) or forcing them in specific groups.
|
||||||
|
|
||||||
|
> **Note:** Setting `"mentions"` on a DM session effectively disables reactions for that DM, since direct messages don't have @mentions. Use `"always"` or `"never"` for DMs.
|
||||||
|
>
|
||||||
|
> **Note:** Unlike the global `group: "mentions"` setting which respects group activation state, the session-level `"mentions"` override is strict and always requires an actual @mention.
|
||||||
|
|
||||||
**Per-account override:**
|
**Per-account override:**
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|||||||
@ -225,6 +225,77 @@ describe("shouldAckReactionForWhatsApp", () => {
|
|||||||
}),
|
}),
|
||||||
).toBe(false);
|
).toBe(false);
|
||||||
});
|
});
|
||||||
|
it("honors session overrides", () => {
|
||||||
|
// Session: NEVER overrides Global: ALWAYS
|
||||||
|
expect(
|
||||||
|
shouldAckReactionForWhatsApp({
|
||||||
|
emoji: "👀",
|
||||||
|
isDirect: false,
|
||||||
|
isGroup: true,
|
||||||
|
directEnabled: true,
|
||||||
|
groupMode: "always",
|
||||||
|
wasMentioned: false,
|
||||||
|
groupActivated: false,
|
||||||
|
sessionMode: "never",
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
|
||||||
|
// Session: ALWAYS overrides Global: NEVER
|
||||||
|
expect(
|
||||||
|
shouldAckReactionForWhatsApp({
|
||||||
|
emoji: "👀",
|
||||||
|
isDirect: false,
|
||||||
|
isGroup: true,
|
||||||
|
directEnabled: true,
|
||||||
|
groupMode: "never",
|
||||||
|
wasMentioned: false,
|
||||||
|
groupActivated: false,
|
||||||
|
sessionMode: "always",
|
||||||
|
}),
|
||||||
|
).toBe(true);
|
||||||
|
|
||||||
|
// Session: MENTIONS in DM (effectively OFF unless mentioned, which is false)
|
||||||
|
expect(
|
||||||
|
shouldAckReactionForWhatsApp({
|
||||||
|
emoji: "👀",
|
||||||
|
isDirect: true,
|
||||||
|
isGroup: false,
|
||||||
|
directEnabled: true, // Globally enabled
|
||||||
|
groupMode: "mentions",
|
||||||
|
wasMentioned: false,
|
||||||
|
groupActivated: false,
|
||||||
|
sessionMode: "mentions", // Override to strict mentions
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
|
||||||
|
// Session: MENTIONS in Group (works if mentioned)
|
||||||
|
expect(
|
||||||
|
shouldAckReactionForWhatsApp({
|
||||||
|
emoji: "👀",
|
||||||
|
isDirect: false,
|
||||||
|
isGroup: true,
|
||||||
|
directEnabled: true,
|
||||||
|
groupMode: "never", // Global OFF
|
||||||
|
wasMentioned: true, // But mentioned
|
||||||
|
groupActivated: false,
|
||||||
|
sessionMode: "mentions", // Session override ON (if mentioned)
|
||||||
|
}),
|
||||||
|
).toBe(true);
|
||||||
|
|
||||||
|
// Session: MENTIONS is strict - does NOT bypass via groupActivated
|
||||||
|
expect(
|
||||||
|
shouldAckReactionForWhatsApp({
|
||||||
|
emoji: "👀",
|
||||||
|
isDirect: false,
|
||||||
|
isGroup: true,
|
||||||
|
directEnabled: true,
|
||||||
|
groupMode: "always",
|
||||||
|
wasMentioned: false, // Not mentioned
|
||||||
|
groupActivated: true, // But group is activated
|
||||||
|
sessionMode: "mentions", // Explicit mentions = strict, no bypass
|
||||||
|
}),
|
||||||
|
).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("removeAckReactionAfterReply", () => {
|
describe("removeAckReactionAfterReply", () => {
|
||||||
|
|||||||
@ -36,8 +36,28 @@ export function shouldAckReactionForWhatsApp(params: {
|
|||||||
groupMode: WhatsAppAckReactionMode;
|
groupMode: WhatsAppAckReactionMode;
|
||||||
wasMentioned: boolean;
|
wasMentioned: boolean;
|
||||||
groupActivated: boolean;
|
groupActivated: boolean;
|
||||||
|
sessionMode?: "always" | "mentions" | "never";
|
||||||
}): boolean {
|
}): boolean {
|
||||||
if (!params.emoji) return false;
|
if (!params.emoji) return false;
|
||||||
|
|
||||||
|
// Session override
|
||||||
|
if (params.sessionMode === "never") return false;
|
||||||
|
if (params.sessionMode === "always") return true;
|
||||||
|
if (params.sessionMode === "mentions") {
|
||||||
|
// Strict mention-only: explicit session override should not bypass via activation
|
||||||
|
return shouldAckReaction({
|
||||||
|
scope: "group-mentions",
|
||||||
|
isDirect: params.isDirect,
|
||||||
|
isGroup: params.isGroup,
|
||||||
|
isMentionableGroup: true,
|
||||||
|
requireMention: true,
|
||||||
|
canDetectMention: true,
|
||||||
|
effectiveWasMentioned: params.wasMentioned,
|
||||||
|
// Note: intentionally not passing shouldBypassMention here
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config fallback
|
||||||
if (params.isDirect) return params.directEnabled;
|
if (params.isDirect) return params.directEnabled;
|
||||||
if (!params.isGroup) return false;
|
if (!params.isGroup) return false;
|
||||||
if (params.groupMode === "never") return false;
|
if (params.groupMode === "never") return false;
|
||||||
|
|||||||
@ -54,6 +54,7 @@ export type SessionEntry = {
|
|||||||
authProfileOverride?: string;
|
authProfileOverride?: string;
|
||||||
authProfileOverrideSource?: "auto" | "user";
|
authProfileOverrideSource?: "auto" | "user";
|
||||||
authProfileOverrideCompactionCount?: number;
|
authProfileOverrideCompactionCount?: number;
|
||||||
|
ackReaction?: "always" | "mentions" | "never";
|
||||||
groupActivation?: "mention" | "always";
|
groupActivation?: "mention" | "always";
|
||||||
groupActivationNeedsSystemIntro?: boolean;
|
groupActivationNeedsSystemIntro?: boolean;
|
||||||
sendPolicy?: "allow" | "deny";
|
sendPolicy?: "allow" | "deny";
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import type { loadConfig } from "../../../config/config.js";
|
import type { loadConfig } from "../../../config/config.js";
|
||||||
|
import { loadSessionStore, resolveStorePath } from "../../../config/sessions.js";
|
||||||
import { logVerbose } from "../../../globals.js";
|
import { logVerbose } from "../../../globals.js";
|
||||||
import { shouldAckReactionForWhatsApp } from "../../../channels/ack-reactions.js";
|
import { shouldAckReactionForWhatsApp } from "../../../channels/ack-reactions.js";
|
||||||
import { sendReactionWhatsApp } from "../../outbound.js";
|
import { sendReactionWhatsApp } from "../../outbound.js";
|
||||||
@ -25,6 +26,16 @@ export function maybeSendAckReaction(params: {
|
|||||||
const groupMode = ackConfig?.group ?? "mentions";
|
const groupMode = ackConfig?.group ?? "mentions";
|
||||||
const conversationIdForCheck = params.msg.conversationId ?? params.msg.from;
|
const conversationIdForCheck = params.msg.conversationId ?? params.msg.from;
|
||||||
|
|
||||||
|
// Load session to check for per-session ackReaction override.
|
||||||
|
// Note: loadSessionStore uses an in-memory cache (45s TTL) so this is not
|
||||||
|
// doing disk I/O on every message in typical usage patterns.
|
||||||
|
const storePath = resolveStorePath(params.cfg.session?.store, {
|
||||||
|
agentId: params.agentId,
|
||||||
|
});
|
||||||
|
const store = loadSessionStore(storePath);
|
||||||
|
const sessionEntry = store[params.sessionKey];
|
||||||
|
const sessionMode = sessionEntry?.ackReaction;
|
||||||
|
|
||||||
const activation =
|
const activation =
|
||||||
params.msg.chatType === "group"
|
params.msg.chatType === "group"
|
||||||
? resolveGroupActivationFor({
|
? resolveGroupActivationFor({
|
||||||
@ -41,6 +52,7 @@ export function maybeSendAckReaction(params: {
|
|||||||
isGroup: params.msg.chatType === "group",
|
isGroup: params.msg.chatType === "group",
|
||||||
directEnabled,
|
directEnabled,
|
||||||
groupMode,
|
groupMode,
|
||||||
|
sessionMode,
|
||||||
wasMentioned: params.msg.wasMentioned === true,
|
wasMentioned: params.msg.wasMentioned === true,
|
||||||
groupActivated: activation === "always",
|
groupActivated: activation === "always",
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user