feat: unify group mention defaults

This commit is contained in:
Peter Steinberger
2026-01-02 22:50:51 +01:00
parent 281dc10b2f
commit a9ff03acaf
7 changed files with 49 additions and 14 deletions

View File

@@ -171,7 +171,7 @@ Minimal `~/.clawdis/clawdis.json`:
### Telegram ### Telegram
- Set `TELEGRAM_BOT_TOKEN` or `telegram.botToken` (env wins). - Set `TELEGRAM_BOT_TOKEN` or `telegram.botToken` (env wins).
- Optional: set `telegram.requireMention`, `telegram.allowFrom`, or `telegram.webhookUrl` as needed. - Optional: set `telegram.groups` (with `telegram.groups."*".requireMention`), `telegram.allowFrom`, or `telegram.webhookUrl` as needed.
```json5 ```json5
{ {

View File

@@ -995,8 +995,8 @@ export async function getReplyFromConfig(
const webAuthAgeMs = getWebAuthAgeMs(); const webAuthAgeMs = getWebAuthAgeMs();
const heartbeatSeconds = resolveHeartbeatSeconds(cfg, undefined); const heartbeatSeconds = resolveHeartbeatSeconds(cfg, undefined);
const groupActivation = isGroup const groupActivation = isGroup
? normalizeGroupActivation(sessionEntry?.groupActivation) ?? ? (normalizeGroupActivation(sessionEntry?.groupActivation) ??
defaultGroupActivation() defaultGroupActivation())
: undefined; : undefined;
const statusText = buildStatusMessage({ const statusText = buildStatusMessage({
agent: { agent: {

View File

@@ -1235,7 +1235,7 @@ const LEGACY_CONFIG_RULES: LegacyConfigRule[] = [
{ {
path: ["telegram", "requireMention"], path: ["telegram", "requireMention"],
message: message:
"telegram.requireMention was removed; use telegram.groups.\"*\".requireMention instead (run `clawdis doctor` to migrate).", 'telegram.requireMention was removed; use telegram.groups."*".requireMention instead (run `clawdis doctor` to migrate).',
}, },
]; ];
@@ -1280,8 +1280,10 @@ const LEGACY_CONFIG_MIGRATIONS: LegacyConfigMigration[] = [
const groupChat = const groupChat =
(routing as Record<string, unknown>).groupChat && (routing as Record<string, unknown>).groupChat &&
typeof (routing as Record<string, unknown>).groupChat === "object" typeof (routing as Record<string, unknown>).groupChat === "object"
? ((routing as Record<string, unknown>) ? ((routing as Record<string, unknown>).groupChat as Record<
.groupChat as Record<string, unknown>) string,
unknown
>)
: null; : null;
if (!groupChat) return; if (!groupChat) return;
const requireMention = groupChat.requireMention; const requireMention = groupChat.requireMention;
@@ -1331,18 +1333,22 @@ const LEGACY_CONFIG_MIGRATIONS: LegacyConfigMigration[] = [
}, },
{ {
id: "telegram.requireMention->telegram.groups.*.requireMention", id: "telegram.requireMention->telegram.groups.*.requireMention",
describe: "Move telegram.requireMention to telegram.groups.*.requireMention", describe:
"Move telegram.requireMention to telegram.groups.*.requireMention",
apply: (raw, changes) => { apply: (raw, changes) => {
const telegram = raw.telegram; const telegram = raw.telegram;
if (!telegram || typeof telegram !== "object") return; if (!telegram || typeof telegram !== "object") return;
const requireMention = (telegram as Record<string, unknown>).requireMention; const requireMention = (telegram as Record<string, unknown>)
.requireMention;
if (requireMention === undefined) return; if (requireMention === undefined) return;
const groups = const groups =
(telegram as Record<string, unknown>).groups && (telegram as Record<string, unknown>).groups &&
typeof (telegram as Record<string, unknown>).groups === "object" typeof (telegram as Record<string, unknown>).groups === "object"
? ((telegram as Record<string, unknown>) ? ((telegram as Record<string, unknown>).groups as Record<
.groups as Record<string, unknown>) string,
unknown
>)
: {}; : {};
const defaultKey = "*"; const defaultKey = "*";
const entry = const entry =

View File

@@ -2,7 +2,9 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
import * as replyModule from "../auto-reply/reply.js"; import * as replyModule from "../auto-reply/reply.js";
import { createTelegramBot } from "./bot.js"; import { createTelegramBot } from "./bot.js";
const loadConfig = vi.fn(() => ({})); const { loadConfig } = vi.hoisted(() => ({
loadConfig: vi.fn(() => ({})),
}));
vi.mock("../config/config.js", () => ({ vi.mock("../config/config.js", () => ({
loadConfig, loadConfig,
})); }));

View File

@@ -58,6 +58,14 @@ export function applyConfigSnapshot(state: ConfigState, snapshot: ConfigSnapshot
.filter((v) => v.length > 0) .filter((v) => v.length > 0)
.join(", ") .join(", ")
: ""; : "";
const telegramGroups =
telegram.groups && typeof telegram.groups === "object"
? (telegram.groups as Record<string, unknown>)
: {};
const telegramDefaultGroup =
telegramGroups["*"] && typeof telegramGroups["*"] === "object"
? (telegramGroups["*"] as Record<string, unknown>)
: {};
const allowFrom = Array.isArray(telegram.allowFrom) const allowFrom = Array.isArray(telegram.allowFrom)
? toList(telegram.allowFrom) ? toList(telegram.allowFrom)
: typeof telegram.allowFrom === "string" : typeof telegram.allowFrom === "string"
@@ -67,7 +75,9 @@ export function applyConfigSnapshot(state: ConfigState, snapshot: ConfigSnapshot
state.telegramForm = { state.telegramForm = {
token: typeof telegram.botToken === "string" ? telegram.botToken : "", token: typeof telegram.botToken === "string" ? telegram.botToken : "",
requireMention: requireMention:
typeof telegram.requireMention === "boolean" ? telegram.requireMention : true, typeof telegramDefaultGroup.requireMention === "boolean"
? telegramDefaultGroup.requireMention
: true,
allowFrom, allowFrom,
proxy: typeof telegram.proxy === "string" ? telegram.proxy : "", proxy: typeof telegram.proxy === "string" ? telegram.proxy : "",
webhookUrl: typeof telegram.webhookUrl === "string" ? telegram.webhookUrl : "", webhookUrl: typeof telegram.webhookUrl === "string" ? telegram.webhookUrl : "",

View File

@@ -147,7 +147,24 @@ export async function saveTelegramConfig(state: ConnectionsState) {
if (token) telegram.botToken = token; if (token) telegram.botToken = token;
else delete telegram.botToken; else delete telegram.botToken;
} }
telegram.requireMention = state.telegramForm.requireMention; const groups =
telegram.groups && typeof telegram.groups === "object"
? ({ ...(telegram.groups as Record<string, unknown>) } as Record<
string,
unknown
>)
: {};
const defaultGroup =
groups["*"] && typeof groups["*"] === "object"
? ({ ...(groups["*"] as Record<string, unknown>) } as Record<
string,
unknown
>)
: {};
defaultGroup.requireMention = state.telegramForm.requireMention;
groups["*"] = defaultGroup;
telegram.groups = groups;
delete telegram.requireMention;
const allowFrom = parseList(state.telegramForm.allowFrom); const allowFrom = parseList(state.telegramForm.allowFrom);
if (allowFrom.length > 0) telegram.allowFrom = allowFrom; if (allowFrom.length > 0) telegram.allowFrom = allowFrom;
else delete telegram.allowFrom; else delete telegram.allowFrom;

View File

@@ -298,7 +298,7 @@ function renderProvider(
/> />
</label> </label>
<label class="field"> <label class="field">
<span>Require mention</span> <span>Require mention in groups</span>
<select <select
.value=${props.telegramForm.requireMention ? "yes" : "no"} .value=${props.telegramForm.requireMention ? "yes" : "no"}
@change=${(e: Event) => @change=${(e: Event) =>