refactor(matrix): dedupe directory/target match helpers
This commit is contained in:
@@ -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<ReturnType<typeof resolveMatrixAuth>>;
|
||||
|
||||
async function fetchMatrixJson<T>(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<ChannelDirectoryEntry[]> {
|
||||
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<ChannelDirectoryEntry[]> {
|
||||
const context = await resolveMatrixDirectoryContext(params);
|
||||
if (!context) {
|
||||
return [];
|
||||
}
|
||||
const { query, auth } = context;
|
||||
const res = await fetchMatrixJson<MatrixUserDirectoryResponse>({
|
||||
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<ChannelDirectoryEntry[]> {
|
||||
const query = normalizeQuery(params.query);
|
||||
if (!query) {
|
||||
export async function listMatrixDirectoryGroupsLive(
|
||||
params: MatrixDirectoryLiveParams,
|
||||
): Promise<ChannelDirectoryEntry[]> {
|
||||
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<MatrixJoinedRoomsResponse>({
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user