Skip to content

Commit

Permalink
Bridge edits to discord webhooks
Browse files Browse the repository at this point in the history
Support M->D edit bridging via the native discord webhook endpoint

Fixes issue #644
  • Loading branch information
Vyquos committed Oct 12, 2022
1 parent 129a5cf commit 9baccd8
Showing 1 changed file with 68 additions and 46 deletions.
114 changes: 68 additions & 46 deletions src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -527,41 +527,78 @@ export class DiscordBot {
} catch (err) {
log.warning("Failed to edit discord message, falling back to delete and resend...", err);
}
} else {
let hook = await this.getWebhook(chan);
try {
if (hook) {
// do we need to delete the event off of the store?
// the edit may bridge over back to matrix otherwise
const embeds = this.prepareEmbedSetWebhook(embedSet);
hook.editMessage(oldMsg, embed.description, {
avatarURL: embed!.author!.iconURL,
embeds,
files: opts.files,
username: embed!.author!.name,
})
this.channelLock.release(chan.id);
} else {
// fallback: use the old method for editing messages of
// simply (re)sending them.
if (editedEventId === this.lastEventIds[chan.id]) {
log.info("Immediate edit, deleting and re-sending");
this.channelLock.set(chan.id);
// we need to delete the event off of the store
// else the delete bridges over back to matrix
const dbEvent = await this.store.Get(DbEvent, { discord_id: editedEventId });
log.verbose("Event to delete", dbEvent);
if (dbEvent && dbEvent.Next()) {
await this.store.Delete(dbEvent);
}
await oldMsg.delete();
this.channelLock.release(chan.id);
const msg = await this.send(embedSet, opts, roomLookup, event, true);
// we re-insert the old matrix event with the new discord id
// to allow consecutive edits, as matrix edits are typically
// done on the original event
const dummyEvent = {
event_id: event.content!["m.relates_to"].event_id,
room_id: event.room_id,
} as IMatrixEvent;
this.StoreMessagesSent(msg, chan, dummyEvent).catch(() => {
log.warn("Failed to store edit sent message for ", event.event_id);
});
return;
}
const link = `https://discord.com/channels/${chan.guild.id}/${chan.id}/${editedEventId}`;
embedSet.messageEmbed.description = `[Edit](${link}): ${embedSet.messageEmbed.description}`;
await this.send(embedSet, opts, roomLookup, event);
}
} catch (err) {
// throw wrapError(err, Unstable.ForeignNetworkError, "Couldn't edit message");
log.warn(`Failed to edit message ${event.event_id}`);
log.verbose(err);
}
}
}

public async getWebhook(channel: Discord.TextChannel): Promise<Discord.Webhook | undefined> {
const webhooks = await channel.fetchWebhooks();
let hook: Discord.Webhook | undefined = webhooks.filter((h) => h.name === "_matrix").first();
// Create a new webhook if none already exists
try {
if (editedEventId === this.lastEventIds[chan.id]) {
log.info("Immediate edit, deleting and re-sending");
this.channelLock.set(chan.id);
// we need to delete the event off of the store
// else the delete bridges over back to matrix
const dbEvent = await this.store.Get(DbEvent, { discord_id: editedEventId });
log.verbose("Event to delete", dbEvent);
if (dbEvent && dbEvent.Next()) {
await this.store.Delete(dbEvent);
}
await oldMsg.delete();
this.channelLock.release(chan.id);
const msg = await this.send(embedSet, opts, roomLookup, event, true);
// we re-insert the old matrix event with the new discord id
// to allow consecutive edits, as matrix edits are typically
// done on the original event
const dummyEvent = {
event_id: event.content!["m.relates_to"].event_id,
room_id: event.room_id,
} as IMatrixEvent;
this.StoreMessagesSent(msg, chan, dummyEvent).catch(() => {
log.warn("Failed to store edit sent message for ", event.event_id);
});
return;
if (!hook) {
hook = await channel.createWebhook(
"_matrix",
{
avatar: MATRIX_ICON_URL,
reason: "Matrix Bridge: Allow rich user messages",
});
}
const link = `https://discord.com/channels/${chan.guild.id}/${chan.id}/${editedEventId}`;
embedSet.messageEmbed.description = `[Edit](${link}): ${embedSet.messageEmbed.description}`;
await this.send(embedSet, opts, roomLookup, event);
} catch (err) {
// throw wrapError(err, Unstable.ForeignNetworkError, "Couldn't edit message");
log.warn(`Failed to edit message ${event.event_id}`);
log.verbose(err);
// throw wrapError(err, Unstable.ForeignNetworkError, "Unable to create \"_matrix\" webhook");
log.warn("Unable to create _matrix webook:", err);
}
return hook
}

/**
Expand All @@ -582,22 +619,7 @@ export class DiscordBot {
let msg: Discord.Message | null | (Discord.Message | null)[] = null;
let hook: Discord.Webhook | undefined;
if (botUser) {
const webhooks = await chan.fetchWebhooks();
hook = webhooks.filter((h) => h.name === "_matrix").first();
// Create a new webhook if none already exists
try {
if (!hook) {
hook = await chan.createWebhook(
"_matrix",
{
avatar: MATRIX_ICON_URL,
reason: "Matrix Bridge: Allow rich user messages",
});
}
} catch (err) {
// throw wrapError(err, Unstable.ForeignNetworkError, "Unable to create \"_matrix\" webhook");
log.warn("Unable to create _matrix webook:", err);
}
hook = await this.getWebhook(chan);
}
try {
this.channelLock.set(chan.id);
Expand Down

0 comments on commit 9baccd8

Please sign in to comment.