From caa9938147e0e944c7bc04bdfd2fa9df2c5f84b6 Mon Sep 17 00:00:00 2001 From: Catalan Lover <48515417+FSG-Cat@users.noreply.github.com> Date: Thu, 16 Apr 2026 19:59:29 +0200 Subject: [PATCH] Make Appservice register and setup basic profile information. (#1086) * Make Appservice register and setup basic profile information. Basic Profile information being setting a display name if none exists. * Add changeset information * Relocate Profile logic to after initialisation. * Clean up Appservice Bot Reg and Profile Set code Co-authored-by: Gnuxie * Workaround bug with ensureRegistered in matrix-appservice-bridge. https://github.com/matrix-org/matrix-appservice-bridge/issues/525 * Clarify that this is mostly dead code --------- Co-authored-by: Gnuxie --- .changeset/wise-carpets-push.md | 5 ++ apps/draupnir/src/appservice/AppService.ts | 66 +++++++++++++++++++++- 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 .changeset/wise-carpets-push.md diff --git a/.changeset/wise-carpets-push.md b/.changeset/wise-carpets-push.md new file mode 100644 index 00000000..46cde22d --- /dev/null +++ b/.changeset/wise-carpets-push.md @@ -0,0 +1,5 @@ +--- +"draupnir": patch +--- + +Make appservice configure profile information for main bot and register it. diff --git a/apps/draupnir/src/appservice/AppService.ts b/apps/draupnir/src/appservice/AppService.ts index c955e1f6..91bf0809 100644 --- a/apps/draupnir/src/appservice/AppService.ts +++ b/apps/draupnir/src/appservice/AppService.ts @@ -1,5 +1,5 @@ -// Copyright 2022 Gnuxie // Copyright 2022 The Matrix.org Foundation C.I.C. +// SPDX-FileCopyrightText: 2023 - 2026 Gnuxie // SPDX-FileCopyrightText: 2026 Catalan Lover // // SPDX-License-Identifier: AFL-3.0 AND Apache-2.0 @@ -30,11 +30,14 @@ import { ClientCapabilityFactory, RoomStateManagerFactory, joinedRoomsSafe, + resultifyBotSDKRequestError, + resultifyBotSDKRequestErrorWith404AsUndefined, } from "matrix-protection-suite-for-matrix-bot-sdk"; import { ClientsInRoomMap, DefaultEventDecoder, EventDecoder, + Ok, StandardClientsInRoomMap, Task, isError, @@ -46,10 +49,12 @@ import { MatrixRoomReference, StringRoomID, StringUserID, + userLocalpart, } from "@the-draupnir-project/matrix-basic-types"; import { SqliteRoomStateBackingStore } from "../backingstore/better-sqlite3/SqliteRoomStateBackingStore"; import { TopLevelStores } from "../backingstore/DraupnirStores"; import { patchMatrixClient } from "../utils"; +import { Result } from "@gnuxie/typescript-result"; const log = new Logger("AppService"); /** @@ -87,6 +92,59 @@ export class MjolnirAppService { ); } + private static async ensureAppserviceBotProfile( + bridge: Bridge, + botUserID: StringUserID + ): Promise> { + const botIntent = bridge.getIntent(botUserID); + const registrationResult = await botIntent + // There seems to be a bug in the matrix-appservice-bridge does not create the profile. + // https://github.com/matrix-org/matrix-appservice-bridge/issues/525 + .ensureRegistered(true) + .then((_) => Ok(undefined), resultifyBotSDKRequestError); + if (isError(registrationResult)) { + return registrationResult.elaborate( + "Failed to register the main appservice bot user" + ); + } + const botProfileResult = await botIntent.matrixClient + .getUserProfile(botUserID) + .then( + (value) => Ok(value), + resultifyBotSDKRequestErrorWith404AsUndefined + ); + if (isError(botProfileResult)) { + return botProfileResult.elaborate( + "Unable to fetch appservice bot profile information" + ); + } + // The code beyond this point is redundant in Synapse but we don't know + // if other implementations set the profile up when an appservice user is + // registered. + const extractDisplayName = (profile: unknown) => { + if (typeof profile !== "object" || profile === null) { + return undefined; + } + if ("displayname" in profile && typeof profile.displayname === "string") { + return profile.displayname; + } + return undefined; + }; + const botDisplayName = extractDisplayName(botProfileResult.ok); + if (botDisplayName !== undefined && botDisplayName !== "") { + return Ok(undefined); // displayname is already set, nothing to do. + } + const setDisplaynameResult = await botIntent + .setDisplayName(userLocalpart(botUserID)) + .then((_) => Ok(undefined), resultifyBotSDKRequestError); + if (isError(setDisplaynameResult)) { + return setDisplaynameResult.elaborate( + `Unable to set appservice bot displayname during startup` + ); + } + return Ok(undefined); + } + /** * Make and initialize the app service from the config, ready to be started. * @param config The appservice's config, not draupnirs's, see `src/appservice/config`. @@ -252,6 +310,12 @@ export class MjolnirAppService { ); // The call to `start` MUST happen last. As it needs the datastore, and the mjolnir manager to be initialized before it can process events from the homeserver. await service.start(port); + ( + await MjolnirAppService.ensureAppserviceBotProfile( + service.bridge, + service.botUserID + ) + ).expect("Failed to ensure the appservice bot's profile exists"); return service; }