rewrite(matrix): use matrix-bot-sdk as base to enable e2ee encryption, strictly follow location + typing + group concepts, fix room bugs

This commit is contained in:
Sebastian Schubotz
2026-01-20 09:37:27 +01:00
committed by Peter Steinberger
parent dd82d32d85
commit 9b71382efb
32 changed files with 1727 additions and 616 deletions

View File

@@ -46,10 +46,12 @@ const meta = {
function normalizeMatrixMessagingTarget(raw: string): string | undefined {
let normalized = raw.trim();
if (!normalized) return undefined;
if (normalized.toLowerCase().startsWith("matrix:")) {
const lowered = normalized.toLowerCase();
if (lowered.startsWith("matrix:")) {
normalized = normalized.slice("matrix:".length).trim();
}
return normalized ? normalized.toLowerCase() : undefined;
const stripped = normalized.replace(/^(room|channel|user):/i, "").trim();
return stripped || undefined;
}
function buildMatrixConfigUpdate(
@@ -155,10 +157,11 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
}),
collectWarnings: ({ account, cfg }) => {
const defaultGroupPolicy = (cfg as CoreConfig).channels?.defaults?.groupPolicy;
const groupPolicy = account.config.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
const groupPolicy =
account.config.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
if (groupPolicy !== "open") return [];
return [
"- Matrix rooms: groupPolicy=\"open\" allows any room to trigger (mention-gated). Set channels.matrix.groupPolicy=\"allowlist\" + channels.matrix.rooms to restrict rooms.",
"- Matrix rooms: groupPolicy=\"open\" allows any room to trigger (mention-gated). Set channels.matrix.groupPolicy=\"allowlist\" + channels.matrix.groups (and optionally channels.matrix.groupAllowFrom) to restrict rooms.",
];
},
},
@@ -168,6 +171,17 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
threading: {
resolveReplyToMode: ({ cfg }) =>
(cfg as CoreConfig).channels?.matrix?.replyToMode ?? "off",
buildToolContext: ({ context, hasRepliedRef }) => {
const currentTarget = context.To;
return {
currentChannelId: currentTarget?.trim() || undefined,
currentThreadTs:
context.MessageThreadId != null
? String(context.MessageThreadId)
: context.ReplyToId,
hasRepliedRef,
};
},
},
messaging: {
normalizeTarget: normalizeMatrixMessagingTarget,
@@ -194,7 +208,14 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
ids.add(raw.replace(/^matrix:/i, ""));
}
for (const room of Object.values(account.config.rooms ?? {})) {
for (const entry of account.config.groupAllowFrom ?? []) {
const raw = String(entry).trim();
if (!raw || raw === "*") continue;
ids.add(raw.replace(/^matrix:/i, ""));
}
const groups = account.config.groups ?? account.config.rooms ?? {};
for (const room of Object.values(groups)) {
for (const entry of room.users ?? []) {
const raw = String(entry).trim();
if (!raw || raw === "*") continue;
@@ -226,7 +247,8 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
listGroups: async ({ cfg, accountId, query, limit }) => {
const account = resolveMatrixAccount({ cfg: cfg as CoreConfig, accountId });
const q = query?.trim().toLowerCase() || "";
const ids = Object.keys(account.config.rooms ?? {})
const groups = account.config.groups ?? account.config.rooms ?? {};
const ids = Object.keys(groups)
.map((raw) => raw.trim())
.filter((raw) => Boolean(raw) && raw !== "*")
.map((raw) => raw.replace(/^matrix:/i, ""))
@@ -263,10 +285,16 @@ export const matrixPlugin: ChannelPlugin<ResolvedMatrixAccount> = {
validateInput: ({ input }) => {
if (input.useEnv) return null;
if (!input.homeserver?.trim()) return "Matrix requires --homeserver";
if (!input.userId?.trim()) return "Matrix requires --user-id";
if (!input.accessToken?.trim() && !input.password?.trim()) {
const accessToken = input.accessToken?.trim();
const password = input.password?.trim();
const userId = input.userId?.trim();
if (!accessToken && !password) {
return "Matrix requires --access-token or --password";
}
if (!accessToken) {
if (!userId) return "Matrix requires --user-id when using --password";
if (!password) return "Matrix requires --password when using --user-id";
}
return null;
},
applyAccountConfig: ({ cfg, input }) => {