diff --git a/CHANGELOG.md b/CHANGELOG.md index df916c37a..c9a79493f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ - UI: add optional `ui.seamColor` accent to tint the Talk Mode side bubble (macOS/iOS/Android). - Nix mode: opt-in declarative config + read-only settings UI when `CLAWDIS_NIX_MODE=1` (thanks @joshp123 for the persistence — earned my trust; I'll merge these going forward). - Agent runtime: accept legacy `Z_AI_API_KEY` for Z.AI provider auth (maps to `ZAI_API_KEY`). -- Groups: add per-group mention gating defaults/overrides for Telegram/WhatsApp/iMessage via `*.groups` with `"*"` defaults. +- Groups: add per-group mention gating defaults/overrides for Telegram/WhatsApp/iMessage via `*.groups` with `"*"` defaults; Discord now supports `discord.guilds."*"` as a default. - Discord: add user-installed slash command handling with per-user sessions and auto-registration (#94) — thanks @thewilloftheshadow. - Discord: add DM enable/allowlist plus guild channel/user/guild allowlists with id/name matching. - Signal: add `signal-cli` JSON-RPC support for send/receive via the Signal provider. diff --git a/docs/configuration.md b/docs/configuration.md index 014b0915a..be6c2cf1c 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -208,6 +208,7 @@ Configure the Discord bot by setting the bot token and optional gating: groupChannels: ["clawd-dm"] // optional group DM allowlist }, guilds: { + "*": { requireMention: true }, // default per-guild mention gating "123456789012345678": { // guild id (preferred) or slug slug: "friends-of-clawd", requireMention: false, // per-guild default @@ -225,6 +226,7 @@ Configure the Discord bot by setting the bot token and optional gating: Clawdis starts Discord only when a `discord` config section exists. The token is resolved from `DISCORD_BOT_TOKEN` or `discord.token` (unless `discord.enabled` is `false`). Use `user:` (DM) or `channel:` (guild channel) when specifying delivery targets for cron/CLI commands. Guild slugs are lowercase with spaces replaced by `-`; channel keys use the slugged channel name (no leading `#`). Prefer guild ids as keys to avoid rename ambiguity. +Use `discord.guilds."*"` for default per-guild settings. ### `imessage` (imsg CLI) diff --git a/docs/discord.md b/docs/discord.md index 7851c620e..9c6a4b139 100644 --- a/docs/discord.md +++ b/docs/discord.md @@ -63,6 +63,7 @@ Note: Guild context `[from:]` lines include `author.tag` + `id` to make ping-rea groupChannels: ["clawd-dm"] }, guilds: { + "*": { requireMention: true }, "123456789012345678": { slug: "friends-of-clawd", requireMention: false, @@ -82,6 +83,7 @@ Note: Guild context `[from:]` lines include `author.tag` + `id` to make ping-rea - `dm.groupEnabled`: enable group DMs (default `false`). - `dm.groupChannels`: optional allowlist for group DM channel ids or slugs. - `guilds`: per-guild rules keyed by guild id (preferred) or slug. +- `guilds."*"`: default per-guild settings applied when no explicit entry exists. - `guilds..slug`: optional friendly slug used for display names. - `guilds..users`: optional per-guild user allowlist (ids or names). - `guilds..channels`: channel rules (keys are channel slugs or ids). diff --git a/docs/groups.md b/docs/groups.md index 5c5fe3983..d63014ad3 100644 --- a/docs/groups.md +++ b/docs/groups.md @@ -51,6 +51,7 @@ Group messages require a mention unless overridden per group. Defaults live per Notes: - `mentionPatterns` are case-insensitive regexes. - Surfaces that provide explicit mentions still pass; patterns are a fallback. +- Discord defaults live in `discord.guilds."*"` (overridable per guild/channel). ## Activation (owner-only) Group owners can toggle per-group activation: diff --git a/src/discord/monitor.test.ts b/src/discord/monitor.test.ts index 5d1d087d5..220fb14a7 100644 --- a/src/discord/monitor.test.ts +++ b/src/discord/monitor.test.ts @@ -75,6 +75,18 @@ describe("discord guild/channel resolution", () => { expect(resolved?.slug).toBe("friends-of-clawd"); }); + it("falls back to wildcard guild entry", () => { + const guildEntries = makeEntries({ + "*": { requireMention: false }, + }); + const resolved = resolveDiscordGuildEntry({ + guild: fakeGuild("123", "Friends of Clawd"), + guildEntries, + }); + expect(resolved?.id).toBe("123"); + expect(resolved?.requireMention).toBe(false); + }); + it("resolves channel config by slug", () => { const guildInfo: DiscordGuildEntryResolved = { channels: { diff --git a/src/discord/monitor.ts b/src/discord/monitor.ts index 13bdf052d..c34c338ec 100644 --- a/src/discord/monitor.ts +++ b/src/discord/monitor.ts @@ -833,6 +833,16 @@ export function resolveDiscordGuildEntry(params: { channels: entry.channels, }; } + const wildcard = guildEntries["*"]; + if (wildcard) { + return { + id: guildId, + slug: wildcard.slug ?? guildSlug, + requireMention: wildcard.requireMention, + users: wildcard.users, + channels: wildcard.channels, + }; + } return null; }