From eb4f1e765c09d5999724ff3e0aec273d7579f5eb Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 18 Feb 2026 16:20:12 +0000 Subject: [PATCH] refactor(matrix): dedupe directory/target match helpers --- extensions/matrix/src/directory-live.ts | 84 ++++++++++++++---------- extensions/matrix/src/resolve-targets.ts | 49 ++++++-------- 2 files changed, 71 insertions(+), 62 deletions(-) diff --git a/extensions/matrix/src/directory-live.ts b/extensions/matrix/src/directory-live.ts index f06eb0be2..e7c8fd459 100644 --- a/extensions/matrix/src/directory-live.ts +++ b/extensions/matrix/src/directory-live.ts @@ -22,6 +22,15 @@ type MatrixAliasLookup = { room_id?: string; }; +type MatrixDirectoryLiveParams = { + cfg: unknown; + accountId?: string | null; + query?: string | null; + limit?: number | null; +}; + +type MatrixResolvedAuth = Awaited>; + async function fetchMatrixJson(params: { homeserver: string; path: string; @@ -48,17 +57,42 @@ function normalizeQuery(value?: string | null): string { return value?.trim().toLowerCase() ?? ""; } -export async function listMatrixDirectoryPeersLive(params: { - cfg: unknown; - accountId?: string | null; - query?: string | null; - limit?: number | null; -}): Promise { +function resolveMatrixDirectoryLimit(limit?: number | null): number { + return typeof limit === "number" && limit > 0 ? limit : 20; +} + +async function resolveMatrixDirectoryContext( + params: MatrixDirectoryLiveParams, +): Promise<{ query: string; auth: MatrixResolvedAuth } | null> { const query = normalizeQuery(params.query); if (!query) { - return []; + return null; } const auth = await resolveMatrixAuth({ cfg: params.cfg as never, accountId: params.accountId }); + return { query, auth }; +} + +function createGroupDirectoryEntry(params: { + id: string; + name: string; + handle?: string; +}): ChannelDirectoryEntry { + return { + kind: "group", + id: params.id, + name: params.name, + handle: params.handle, + } satisfies ChannelDirectoryEntry; +} + +export async function listMatrixDirectoryPeersLive( + params: MatrixDirectoryLiveParams, +): Promise { + const context = await resolveMatrixDirectoryContext(params); + if (!context) { + return []; + } + const { query, auth } = context; const res = await fetchMatrixJson({ homeserver: auth.homeserver, accessToken: auth.accessToken, @@ -66,7 +100,7 @@ export async function listMatrixDirectoryPeersLive(params: { method: "POST", body: { search_term: query, - limit: typeof params.limit === "number" && params.limit > 0 ? params.limit : 20, + limit: resolveMatrixDirectoryLimit(params.limit), }, }); const results = res.results ?? []; @@ -121,42 +155,26 @@ async function fetchMatrixRoomName( } } -export async function listMatrixDirectoryGroupsLive(params: { - cfg: unknown; - accountId?: string | null; - query?: string | null; - limit?: number | null; -}): Promise { - const query = normalizeQuery(params.query); - if (!query) { +export async function listMatrixDirectoryGroupsLive( + params: MatrixDirectoryLiveParams, +): Promise { + const context = await resolveMatrixDirectoryContext(params); + if (!context) { return []; } - const auth = await resolveMatrixAuth({ cfg: params.cfg as never, accountId: params.accountId }); - const limit = typeof params.limit === "number" && params.limit > 0 ? params.limit : 20; + const { query, auth } = context; + const limit = resolveMatrixDirectoryLimit(params.limit); if (query.startsWith("#")) { const roomId = await resolveMatrixRoomAlias(auth.homeserver, auth.accessToken, query); if (!roomId) { return []; } - return [ - { - kind: "group", - id: roomId, - name: query, - handle: query, - } satisfies ChannelDirectoryEntry, - ]; + return [createGroupDirectoryEntry({ id: roomId, name: query, handle: query })]; } if (query.startsWith("!")) { - return [ - { - kind: "group", - id: query, - name: query, - } satisfies ChannelDirectoryEntry, - ]; + return [createGroupDirectoryEntry({ id: query, name: query })]; } const joined = await fetchMatrixJson({ diff --git a/extensions/matrix/src/resolve-targets.ts b/extensions/matrix/src/resolve-targets.ts index 3cb9c6e69..fb111da0c 100644 --- a/extensions/matrix/src/resolve-targets.ts +++ b/extensions/matrix/src/resolve-targets.ts @@ -6,6 +6,22 @@ import type { } from "openclaw/plugin-sdk"; import { listMatrixDirectoryGroupsLive, listMatrixDirectoryPeersLive } from "./directory-live.js"; +function findExactDirectoryMatches( + matches: ChannelDirectoryEntry[], + query: string, +): ChannelDirectoryEntry[] { + const normalized = query.trim().toLowerCase(); + if (!normalized) { + return []; + } + return matches.filter((match) => { + const id = match.id.trim().toLowerCase(); + const name = match.name?.trim().toLowerCase(); + const handle = match.handle?.trim().toLowerCase(); + return normalized === id || normalized === name || normalized === handle; + }); +} + function pickBestGroupMatch( matches: ChannelDirectoryEntry[], query: string, @@ -13,19 +29,8 @@ function pickBestGroupMatch( if (matches.length === 0) { return undefined; } - const normalized = query.trim().toLowerCase(); - if (normalized) { - const exact = matches.find((match) => { - const name = match.name?.trim().toLowerCase(); - const handle = match.handle?.trim().toLowerCase(); - const id = match.id.trim().toLowerCase(); - return name === normalized || handle === normalized || id === normalized; - }); - if (exact) { - return exact; - } - } - return matches[0]; + const [exact] = findExactDirectoryMatches(matches, query); + return exact ?? matches[0]; } function pickBestUserMatch( @@ -35,16 +40,7 @@ function pickBestUserMatch( if (matches.length === 0) { return undefined; } - const normalized = query.trim().toLowerCase(); - if (!normalized) { - return undefined; - } - const exact = matches.filter((match) => { - const id = match.id.trim().toLowerCase(); - const name = match.name?.trim().toLowerCase(); - const handle = match.handle?.trim().toLowerCase(); - return normalized === id || normalized === name || normalized === handle; - }); + const exact = findExactDirectoryMatches(matches, query); if (exact.length === 1) { return exact[0]; } @@ -59,12 +55,7 @@ function describeUserMatchFailure(matches: ChannelDirectoryEntry[], query: strin if (!normalized) { return "empty input"; } - const exact = matches.filter((match) => { - const id = match.id.trim().toLowerCase(); - const name = match.name?.trim().toLowerCase(); - const handle = match.handle?.trim().toLowerCase(); - return normalized === id || normalized === name || normalized === handle; - }); + const exact = findExactDirectoryMatches(matches, normalized); if (exact.length === 0) { return "no exact match; use full Matrix ID"; }