diff --git a/extensions/matrix/src/matrix/direct-management.ts b/extensions/matrix/src/matrix/direct-management.ts index 3f1c4cb5009..2d27a68bf0f 100644 --- a/extensions/matrix/src/matrix/direct-management.ts +++ b/extensions/matrix/src/matrix/direct-management.ts @@ -114,6 +114,28 @@ function buildNextDirectContent(params: { }; } +export async function persistMatrixDirectRoomMapping(params: { + client: MatrixClient; + remoteUserId: string; + roomId: string; +}): Promise { + const remoteUserId = normalizeRemoteUserId(params.remoteUserId); + const directContent = await readMatrixDirectAccountData(params.client); + const current = normalizeMappedRoomIds(directContent, remoteUserId); + if (current[0] === params.roomId) { + return false; + } + await params.client.setAccountData( + EventType.Direct, + buildNextDirectContent({ + directContent, + remoteUserId, + roomId: params.roomId, + }), + ); + return true; +} + export async function inspectMatrixDirectRooms(params: { client: MatrixClient; remoteUserId: string; @@ -198,7 +220,11 @@ export async function repairMatrixDirectRooms(params: { JSON.stringify(directContentAfter[remoteUserId] ?? []) !== JSON.stringify(directContentBefore[remoteUserId] ?? []); if (changed) { - await params.client.setAccountData(EventType.Direct, directContentAfter); + await persistMatrixDirectRoomMapping({ + client: params.client, + remoteUserId, + roomId: activeRoomId, + }); } return { ...inspected, diff --git a/extensions/matrix/src/matrix/send/targets.ts b/extensions/matrix/src/matrix/send/targets.ts index e27ff99a59e..de35b6aaccb 100644 --- a/extensions/matrix/src/matrix/send/targets.ts +++ b/extensions/matrix/src/matrix/send/targets.ts @@ -1,8 +1,7 @@ -import { inspectMatrixDirectRooms } from "../direct-management.js"; +import { inspectMatrixDirectRooms, persistMatrixDirectRoomMapping } from "../direct-management.js"; import { isStrictDirectRoom } from "../direct-room.js"; import type { MatrixClient } from "../sdk.js"; import { isMatrixQualifiedUserId, normalizeMatrixResolvableTarget } from "../target-ids.js"; -import { EventType, type MatrixDirectAccountData } from "./types.js"; function normalizeTarget(raw: string): string { const trimmed = raw.trim(); @@ -45,35 +44,6 @@ function setDirectRoomCached(client: MatrixClient, key: string, value: string): } } -async function persistDirectRoom( - client: MatrixClient, - userId: string, - roomId: string, -): Promise { - let directContent: MatrixDirectAccountData | undefined; - try { - directContent = (await client.getAccountData(EventType.Direct)) as - | MatrixDirectAccountData - | undefined; - } catch { - // Ignore fetch errors and fall back to an empty map. - } - const existing = directContent && !Array.isArray(directContent) ? directContent : {}; - const current = Array.isArray(existing[userId]) ? existing[userId] : []; - if (current[0] === roomId) { - return; - } - const next = [roomId, ...current.filter((id) => id !== roomId)]; - try { - await client.setAccountData(EventType.Direct, { - ...existing, - [userId]: next, - }); - } catch { - // Ignore persistence errors. - } -} - async function resolveDirectRoomId(client: MatrixClient, userId: string): Promise { const trimmed = userId.trim(); if (!isMatrixQualifiedUserId(trimmed)) { @@ -100,7 +70,13 @@ async function resolveDirectRoomId(client: MatrixClient, userId: string): Promis if (inspection.activeRoomId) { setDirectRoomCached(client, trimmed, inspection.activeRoomId); if (inspection.mappedRoomIds[0] !== inspection.activeRoomId) { - await persistDirectRoom(client, trimmed, inspection.activeRoomId); + await persistMatrixDirectRoomMapping({ + client, + remoteUserId: trimmed, + roomId: inspection.activeRoomId, + }).catch(() => { + // Ignore persistence errors when send resolution has already found a usable room. + }); } return inspection.activeRoomId; }