diff --git a/src/bot.ts b/src/bot.ts index cfbd700403c461ab1ac0339d6ce68b5b78fdaf27..240ab20a72cd7ca8be5937de194bdb230f507617 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -60,7 +60,7 @@ export class DiscordBot { public setBridge(bridge: Bridge) { this.bridge = bridge; this.mxEventProcessor = new MatrixEventProcessor( - new MatrixEventProcessorOpts(this.config, bridge), + new MatrixEventProcessorOpts(this.config, bridge, this), ); } @@ -331,6 +331,20 @@ export class DiscordBot { return false; } + public GetDiscordUserOrMember(userId: Discord.Snowflake, guildId?: Discord.Snowflake) + : Promise<Discord.User|Discord.GuildMember> { + try { + if (guildId && this.bot.guilds.has(guildId)) { + return this.bot.guilds.get(guildId).fetchMember(userId); + } + return this.bot.fetchUser(userId); + } + catch (ex) { + log.warn(`Could not fetch user data for ${userId} (guild: ${guildId})`); + return undefined; + } + } + public GetChannelFromRoomId(roomId: string): Promise<Discord.Channel> { return this.bridge.getRoomStore().getEntriesByMatrixId( roomId, diff --git a/src/matrixeventprocessor.ts b/src/matrixeventprocessor.ts index ea734eeb7ff556fd2adb7525f84fa3c4397b88e0..90765e7fa10475a6cde5e2d0552fcae43ac75aee 100644 --- a/src/matrixeventprocessor.ts +++ b/src/matrixeventprocessor.ts @@ -6,6 +6,7 @@ import * as escapeStringRegexp from "escape-string-regexp"; import {Util} from "./util"; import * as path from "path"; import * as mime from "mime"; +import {MatrixUser} from "matrix-appservice-bridge"; import { Log } from "./log"; const log = new Log("MatrixEventProcessor"); @@ -19,6 +20,7 @@ export class MatrixEventProcessorOpts { constructor( readonly config: DiscordBridgeConfig, readonly bridge: any, + readonly discord: DiscordBot, ) { } @@ -32,10 +34,12 @@ export interface IMatrixEventProcessorResult { export class MatrixEventProcessor { private config: DiscordBridgeConfig; private bridge: any; + private discord: DiscordBot; constructor (opts: MatrixEventProcessorOpts) { this.config = opts.config; this.bridge = opts.bridge; + this.discord = opts.discord; } public StateEventToMessage(event: any, channel: Discord.TextChannel): string { @@ -126,7 +130,7 @@ export class MatrixEventProcessor { const messageEmbed = new Discord.RichEmbed(); const replyEmbedAndBody = await this.GetEmbedForReply(event); messageEmbed.setDescription(replyEmbedAndBody ? replyEmbedAndBody[1] : body); - this.SetEmbedAuthor(messageEmbed, event.sender, profile); + await this.SetEmbedAuthor(messageEmbed, event.sender, profile); return { messageEmbed, replyEmbed: replyEmbedAndBody ? replyEmbedAndBody[0] : undefined, @@ -230,10 +234,9 @@ export class MatrixEventProcessor { replyText = Util.GetReplyFromReplyBody(sourceEvent.content.body); } embed.setDescription(replyText); - this.SetEmbedAuthor( + await this.SetEmbedAuthor( embed, sourceEvent.sender, - await intent.getProfileInfo(sourceEvent.sender), ); } catch (ex) { // For some reason we failed to get the event, so using fallback. @@ -243,11 +246,38 @@ export class MatrixEventProcessor { return [embed, reponseText]; } - private SetEmbedAuthor(embed: Discord.RichEmbed, sender: string, profile: any) { + private async SetEmbedAuthor(embed: Discord.RichEmbed, sender: string, profile?: any) { const intent = this.bridge.getIntent(); let displayName = sender; let avatarUrl = undefined; + // Are they a discord user. + if (this.bridge.getBot().isRemoteUser(sender)) { + const localpart = new MatrixUser(sender.replace("@", "")).localpart; + const userOrMember = await this.discord.GetDiscordUserOrMember(localpart.substring("_discord_".length)); + if (userOrMember instanceof Discord.User) { + embed.setAuthor( + userOrMember.username, + userOrMember.avatarURL + ); + return; + } else if (userOrMember instanceof Discord.GuildMember) { + embed.setAuthor( + userOrMember.displayName, + userOrMember.user.avatarURL + ); + return; + } + // Let it fall through. + } + if (profile === undefined) { + try { + profile = await intent.getProfileInfo(sender); + } catch (ex) { + log.warn(`Failed to fetch profile for ${sender}`, ex); + } + } + if (profile) { if (profile.displayname && profile.displayname.length >= MIN_NAME_LENGTH && diff --git a/src/matrixroomhandler.ts b/src/matrixroomhandler.ts index e627fc9cc463581996b9045b800496a33554b1e5..4fc96a4d476e63bc4cf6cae8e47c497a378fc88d 100644 --- a/src/matrixroomhandler.ts +++ b/src/matrixroomhandler.ts @@ -109,7 +109,7 @@ export class MatrixRoomHandler { if (event.type === "m.room.member" && event.content.membership === "invite") { return this.HandleInvite(event); } else if (event.type === "m.room.member" && event.content.membership === "join") { - if (this.bridge.getBot()._isRemoteUser(event.state_key)) { + if (this.bridge.getBot().isRemoteUser(event.state_key)) { return this.discord.UserSyncroniser.OnMemberState(event, USERSYNC_STATE_DELAY_MS); } else { return this.discord.ProcessMatrixStateEvent(event); diff --git a/test/test_matrixeventprocessor.ts b/test/test_matrixeventprocessor.ts index e54d2accbb38dc8304cdef735191720171463757..f08e8c959f26adfdbe25e5a05d6963a2ce14989e 100644 --- a/test/test_matrixeventprocessor.ts +++ b/test/test_matrixeventprocessor.ts @@ -45,6 +45,11 @@ function createMatrixEventProcessor }, }; }, + getBot: () => { + return { + isRemoteUser: () => false, + } + }, getIntent: () => { return { getClient: () => { @@ -118,6 +123,7 @@ This is the first reply`, new MatrixEventProcessorOpts( config, bridge, + null )); } const mockChannel = new MockChannel(); diff --git a/test/test_matrixroomhandler.ts b/test/test_matrixroomhandler.ts index 0bfefe5e45be2aab7401b65d23c24f451da4f639..aa2b5f641b5c483040e7600d8a9fdd9537dae00c 100644 --- a/test/test_matrixroomhandler.ts +++ b/test/test_matrixroomhandler.ts @@ -66,7 +66,7 @@ function createRH(opts: any = {}) { }, getBot: () => { return { - _isRemoteUser: (id) => { + isRemoteUser: (id) => { return id !== undefined && id.startsWith("@_discord_"); }, };