default requireMention to true

This commit is contained in:
jaydenfyi 2026-01-25 21:35:48 +08:00
parent ad828b9f0b
commit 11d00f663c
5 changed files with 82 additions and 29 deletions

View File

@ -38,7 +38,7 @@ Details: [Plugins](/plugin)
- If both are set, config takes precedence (env fallback is default-account only).
4) Start the gateway.
**⚠️ Important:** Add `requireMention: true` and access control (`allowFrom` or `allowedRoles`) to prevent the bot from replying to all chat messages.
**⚠️ Important:** Add access control (`allowFrom` or `allowedRoles`) to prevent unauthorized users from triggering the bot. `requireMention` defaults to `true`.
Minimal config:
@ -51,7 +51,6 @@ Minimal config:
accessToken: "oauth:abc123...", // OAuth Access Token (or use CLAWDBOT_TWITCH_ACCESS_TOKEN env var)
clientId: "xyz789...", // Client ID from Token Generator
channel: "vevisk", // Which Twitch channel's chat to join
requireMention: true, // (recommended) Only reply when mentioned
allowFrom: ["123456789"] // (recommended) Your Twitch user ID only
}
}
@ -106,7 +105,6 @@ If both env and config are set, config takes precedence.
{
channels: {
twitch: {
requireMention: true, // (recommended) Only respond when mentioned
allowFrom: ["123456789"], // (recommended) Your Twitch user ID only
allowedRoles: ["moderator"] // Or restrict to roles
}
@ -223,7 +221,9 @@ Users in `allowFrom` bypass role checks:
}
```
### Require @mention
### Disable @mention requirement
By default, `requireMention` is `true`. To disable and respond to all messages:
```json5
{
@ -231,7 +231,7 @@ Users in `allowFrom` bypass role checks:
twitch: {
accounts: {
default: {
requireMention: true
requireMention: false
}
}
}
@ -287,7 +287,7 @@ If you see "token refresh disabled (no refresh token)":
- `obtainmentTimestamp` - Token obtained timestamp
- `allowFrom` - User ID allowlist
- `allowedRoles` - Role-based access control (`"moderator" | "owner" | "vip" | "subscriber" | "all"`)
- `requireMention` - Require @mention (default: `false`)
- `requireMention` - Require @mention (default: `true`)
**Provider options:**
- `channels.twitch.enabled` - Enable/disable channel startup
@ -310,7 +310,6 @@ Full example:
channel: "vevisk",
clientSecret: "secret123...",
refreshToken: "refresh456...",
requireMention: true,
allowFrom: ["123456789"],
allowedRoles: ["moderator", "vip"],
accounts: {
@ -325,8 +324,7 @@ Full example:
expiresIn: 14400,
obtainmentTimestamp: 1706092800000,
allowFrom: ["123456789", "987654321"],
allowedRoles: ["moderator"],
requireMention: true
allowedRoles: ["moderator"]
}
}
}

View File

@ -20,7 +20,7 @@ Onboarding: select Twitch and confirm the install prompt to fetch the plugin aut
Minimal config (simplified single-account):
**⚠️ Important:** Strongly recommended to add `requireMention` and access control (`allowFrom` or `allowedRoles`) to prevent the bot from replying to all chat messages.
**⚠️ Important:** `requireMention` defaults to `true`. Add access control (`allowFrom` or `allowedRoles`) to prevent unauthorized users from triggering the bot.
```json5
{
@ -31,16 +31,15 @@ Minimal config (simplified single-account):
accessToken: "oauth:abc123...", // OAuth Access Token (add oauth: prefix)
clientId: "xyz789...", // Client ID from Token Generator
channel: "vevisk", // Channel to join
requireMention: true, // (recommended) Only reply when mentioned
allowFrom: ["123456789"], // (recommended) Your Twitch user ID only (Convert your twitch username to ID at https://www.streamweasels.com/tools/convert-twitch-username-%20to-user-id/)
},
},
}
```
**Recommended access control options:**
**Access control options:**
- `requireMention: true` - Only respond when the bot is mentioned with `@botname`
- `requireMention: false` - Disable the default mention requirement to respond to all messages
- `allowFrom: ["your_user_id"]` - Restrict to your Twitch user ID only (find your ID at https://www.twitchangles.com/xqc or similar)
- `allowedRoles: ["moderator", "vip", "subscriber"]` - Restrict to specific roles

View File

@ -16,9 +16,44 @@ describe("checkTwitchAccessControl", () => {
};
describe("when no restrictions are configured", () => {
it("allows all messages", () => {
it("allows messages that mention the bot (default requireMention)", () => {
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
};
const result = checkTwitchAccessControl({
message: mockMessage,
message,
account: mockAccount,
botUsername: "testbot",
});
expect(result.allowed).toBe(true);
});
});
describe("requireMention default", () => {
it("defaults to true when undefined", () => {
const message: TwitchChatMessage = {
...mockMessage,
message: "hello bot",
};
const result = checkTwitchAccessControl({
message,
account: mockAccount,
botUsername: "testbot",
});
expect(result.allowed).toBe(false);
expect(result.reason).toContain("does not mention the bot");
});
it("allows mention when requireMention is undefined", () => {
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
};
const result = checkTwitchAccessControl({
message,
account: mockAccount,
botUsername: "testbot",
});
@ -85,9 +120,13 @@ describe("checkTwitchAccessControl", () => {
...mockAccount,
allowFrom: ["123456", "789012"],
};
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
};
const result = checkTwitchAccessControl({
message: mockMessage,
message,
account,
botUsername: "testbot",
});
@ -101,9 +140,13 @@ describe("checkTwitchAccessControl", () => {
...mockAccount,
allowFrom: ["789012"],
};
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
};
const result = checkTwitchAccessControl({
message: mockMessage,
message,
account,
botUsername: "testbot",
});
@ -116,7 +159,11 @@ describe("checkTwitchAccessControl", () => {
...mockAccount,
allowFrom: ["123456"],
};
const message = { ...mockMessage, userId: undefined };
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
userId: undefined,
};
const result = checkTwitchAccessControl({
message,
@ -135,6 +182,7 @@ describe("checkTwitchAccessControl", () => {
};
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
isOwner: false,
};
@ -154,6 +202,7 @@ describe("checkTwitchAccessControl", () => {
};
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
userId: "123456",
isMod: true,
};
@ -175,6 +224,7 @@ describe("checkTwitchAccessControl", () => {
};
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
userId: "123456",
isMod: false,
};
@ -197,6 +247,7 @@ describe("checkTwitchAccessControl", () => {
};
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
isMod: true,
};
@ -216,6 +267,7 @@ describe("checkTwitchAccessControl", () => {
};
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
isVip: true,
isMod: false,
isSub: false,
@ -236,6 +288,7 @@ describe("checkTwitchAccessControl", () => {
};
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
isMod: false,
};
@ -253,9 +306,13 @@ describe("checkTwitchAccessControl", () => {
...mockAccount,
allowedRoles: ["all"],
};
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
};
const result = checkTwitchAccessControl({
message: mockMessage,
message,
account,
botUsername: "testbot",
});
@ -270,6 +327,7 @@ describe("checkTwitchAccessControl", () => {
};
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
isMod: true,
};
@ -288,6 +346,7 @@ describe("checkTwitchAccessControl", () => {
};
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
isSub: true,
};
@ -306,6 +365,7 @@ describe("checkTwitchAccessControl", () => {
};
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
isOwner: true,
};
@ -324,6 +384,7 @@ describe("checkTwitchAccessControl", () => {
};
const message: TwitchChatMessage = {
...mockMessage,
message: "@testbot hello",
isVip: true,
};
@ -365,7 +426,8 @@ describe("checkTwitchAccessControl", () => {
};
const message: TwitchChatMessage = {
...mockMessage,
isOwner: false, // Not owner, but in allowlist
message: "@testbot hello",
isOwner: false,
};
const result = checkTwitchAccessControl({

View File

@ -38,7 +38,7 @@ export function checkTwitchAccessControl(params: {
}): TwitchAccessControlResult {
const { message, account, botUsername } = params;
if (account.requireMention) {
if (account.requireMention ?? true) {
const mentions = extractMentions(message.message);
if (!mentions.includes(botUsername.toLowerCase())) {
return {

View File

@ -269,10 +269,9 @@ const dmPolicy: ChannelOnboardingDmPolicy = {
return "disabled";
},
setPolicy: (cfg, policy) => {
// Map policy to Twitch roles
const allowedRoles: TwitchRole[] =
policy === "open" ? ["all"] : policy === "allowlist" ? [] : ["moderator"];
return setTwitchAccessControl(cfg as ClawdbotConfig, allowedRoles, false);
return setTwitchAccessControl(cfg as ClawdbotConfig, allowedRoles, true);
},
promptAllowFrom: async ({ cfg, prompter }) => {
const account = getAccountConfig(cfg, DEFAULT_ACCOUNT_ID);
@ -378,12 +377,7 @@ export const twitchOnboardingAdapter: ChannelOnboardingAdapter = {
? ["moderator", "vip"]
: [];
const requireMention = accessConfig.policy === "open";
const cfgWithAccessControl = setTwitchAccessControl(
cfgWithAllowFrom,
allowedRoles,
requireMention,
);
const cfgWithAccessControl = setTwitchAccessControl(cfgWithAllowFrom, allowedRoles, true);
return { cfg: cfgWithAccessControl };
}
}