refactor: unify channel config matching and gating

Co-authored-by: thewilloftheshadow <thewilloftheshadow@users.noreply.github.com>
This commit is contained in:
Peter Steinberger
2026-01-18 01:21:27 +00:00
parent 05f49d2846
commit f73dbdbaea
24 changed files with 430 additions and 120 deletions

View File

@@ -1,5 +1,5 @@
import type { ChannelAccountSnapshot, ChannelStatusIssue } from "../types.js";
import { asString, isRecord } from "./shared.js";
import { appendMatchMetadata, asString, isRecord } from "./shared.js";
type DiscordIntentSummary = {
messageContent?: "enabled" | "limited" | "disabled";
@@ -128,15 +128,15 @@ export function collectDiscordStatusIssues(
if (channel.ok === true) continue;
const missing = channel.missing?.length ? ` missing ${channel.missing.join(", ")}` : "";
const error = channel.error ? `: ${channel.error}` : "";
const matchMeta =
channel.matchKey || channel.matchSource
? ` (matchKey=${channel.matchKey ?? "none"} matchSource=${channel.matchSource ?? "none"})`
: "";
const baseMessage = `Channel ${channel.channelId} permission check failed.${missing}${error}`;
issues.push({
channel: "discord",
accountId,
kind: "permissions",
message: `Channel ${channel.channelId} permission check failed.${missing}${error}${matchMeta}`,
message: appendMatchMetadata(baseMessage, {
matchKey: channel.matchKey,
matchSource: channel.matchSource,
}),
fix: "Ensure the bot role can view + send in this channel (and that channel overrides don't deny it).",
});
}

View File

@@ -5,3 +5,27 @@ export function asString(value: unknown): string | undefined {
export function isRecord(value: unknown): value is Record<string, unknown> {
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
}
export function formatMatchMetadata(params: {
matchKey?: unknown;
matchSource?: unknown;
}): string | undefined {
const matchKey =
typeof params.matchKey === "string"
? params.matchKey
: typeof params.matchKey === "number"
? String(params.matchKey)
: undefined;
const matchSource = asString(params.matchSource);
const parts = [matchKey ? `matchKey=${matchKey}` : null, matchSource ? `matchSource=${matchSource}` : null]
.filter((entry): entry is string => Boolean(entry));
return parts.length > 0 ? parts.join(" ") : undefined;
}
export function appendMatchMetadata(
message: string,
params: { matchKey?: unknown; matchSource?: unknown },
): string {
const meta = formatMatchMetadata(params);
return meta ? `${message} (${meta})` : message;
}

View File

@@ -1,5 +1,5 @@
import type { ChannelAccountSnapshot, ChannelStatusIssue } from "../types.js";
import { asString, isRecord } from "./shared.js";
import { appendMatchMetadata, asString, isRecord } from "./shared.js";
type TelegramAccountStatus = {
accountId?: unknown;
@@ -111,15 +111,15 @@ export function collectTelegramStatusIssues(
if (group.ok === true) continue;
const status = group.status ? ` status=${group.status}` : "";
const err = group.error ? `: ${group.error}` : "";
const matchMeta =
group.matchKey || group.matchSource
? ` (matchKey=${group.matchKey ?? "none"} matchSource=${group.matchSource ?? "none"})`
: "";
const baseMessage = `Group ${group.chatId} not reachable by bot.${status}${err}`;
issues.push({
channel: "telegram",
accountId,
kind: "runtime",
message: `Group ${group.chatId} not reachable by bot.${status}${err}${matchMeta}`,
message: appendMatchMetadata(baseMessage, {
matchKey: group.matchKey,
matchSource: group.matchSource,
}),
fix: "Invite the bot to the group, then DM the bot once (/start) and restart the gateway.",
});
}