diff --git a/changelog.d/766.bugfix b/changelog.d/766.bugfix new file mode 100644 index 00000000..333a9625 --- /dev/null +++ b/changelog.d/766.bugfix @@ -0,0 +1 @@ +User correct Matrix accounts when redacting events. diff --git a/src/BaseSlackHandler.ts b/src/BaseSlackHandler.ts index c9f29c0c..ee7bf875 100644 --- a/src/BaseSlackHandler.ts +++ b/src/BaseSlackHandler.ts @@ -50,6 +50,7 @@ export interface ISlackEventMessageAttachment { } export interface ISlackMessageEvent extends ISlackEvent { + team?: string; team_domain?: string; team_id?: string; user?: string; diff --git a/src/SlackEventHandler.ts b/src/SlackEventHandler.ts index eeaa527f..dee007a0 100644 --- a/src/SlackEventHandler.ts +++ b/src/SlackEventHandler.ts @@ -18,6 +18,7 @@ import { BaseSlackHandler, ISlackEvent, ISlackMessageEvent, ISlackUser } from ". import { BridgedRoom } from "./BridgedRoom"; import { Main, METRIC_RECEIVED_MESSAGE } from "./Main"; import { Logger } from "matrix-appservice-bridge"; +import { TeamEntry } from "./datastore/Models"; const log = new Logger("SlackEventHandler"); /** @@ -289,11 +290,10 @@ export class SlackEventHandler extends BaseSlackHandler { } } } else if (msg.subtype === "message_deleted" && msg.deleted_ts) { - const originalEvent = await this.main.datastore.getEventBySlackId(msg.channel, msg.deleted_ts); - if (originalEvent) { - const botClient = this.main.botIntent.matrixClient; - await botClient.redactEvent(originalEvent.roomId, originalEvent.eventId); - return; + try { + await this.deleteMessage(msg, team); + } catch (err) { + log.error(err); } // If we don't have the event throw Error("unknown_message"); @@ -315,6 +315,42 @@ export class SlackEventHandler extends BaseSlackHandler { return room.onSlackMessage(msg); } + private async deleteMessage(msg: ISlackMessageEvent, team: TeamEntry): Promise { + const originalEvent = await this.main.datastore.getEventBySlackId(msg.channel, msg.deleted_ts!); + if (originalEvent) { + const previousMessage = msg.previous_message; + if (!previousMessage) { + throw new Error(`Cannot delete message with no previous_message: ${JSON.stringify(msg)}`); + } + + // Try to determine the Matrix user responsible for deleting the message, fallback to our main bot if all else fails + if (!previousMessage.user) { + log.warn("We don't know the original sender of", previousMessage, "will try to remove with our bot"); + } + + const isOurMessage = previousMessage.subtype === 'bot_message' && (previousMessage.bot_id === team.bot_id); + + if (previousMessage.user && !isOurMessage) { + try { + const ghost = await this.main.ghostStore.get(previousMessage.user, previousMessage.team_domain, previousMessage.team); + await ghost.redactEvent(originalEvent.roomId, originalEvent.eventId); + return; + } catch (err) { + log.warn(`Failed to remove message on behalf of ${previousMessage.user}, falling back to our bot`); + } + } + + try { + const botClient = this.main.botIntent.matrixClient; + await botClient.redactEvent(originalEvent.roomId, originalEvent.eventId, "Deleted on Slack"); + } catch (err) { + throw new Error( + `Failed to remove message ${JSON.stringify(previousMessage)} with our Matrix bot. insufficient power level? Error: ${err}` + ); + } + } + } + private async handleReaction(event: ISlackEventReaction, teamId: string) { // Reactions store the channel in the item const channel = event.item.channel; diff --git a/src/SlackGhost.ts b/src/SlackGhost.ts index 9fd574e2..b43a5edc 100644 --- a/src/SlackGhost.ts +++ b/src/SlackGhost.ts @@ -321,6 +321,13 @@ export class SlackGhost { return Slackdown.parse(body); } + public async redactEvent(roomId: string, eventId: string) { + if (!this._intent) { + throw Error('No intent associated with ghost'); + } + await this._intent.matrixClient.redactEvent(roomId, eventId); + } + public async sendInThread(roomId: string, text: string, slackRoomId: string, slackEventTs: string, replyEvent: IMatrixReplyEvent): Promise { const content = {