feat: add discord guild wildcard defaults

This commit is contained in:
Peter Steinberger
2026-01-02 22:33:26 +01:00
parent 47f4f59692
commit fd32fc8d8d
6 changed files with 28 additions and 1 deletions

View File

@@ -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.

View File

@@ -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:<id>` (DM) or `channel:<id>` (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)

View File

@@ -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.<id>.slug`: optional friendly slug used for display names.
- `guilds.<id>.users`: optional per-guild user allowlist (ids or names).
- `guilds.<id>.channels`: channel rules (keys are channel slugs or ids).

View File

@@ -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:

View File

@@ -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: {

View File

@@ -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;
}