translate channel and user mentions

This commit is contained in:
JandereDev 2022-04-19 12:56:41 +02:00
parent b567de2277
commit f34d01745d
Signed by: Lea
GPG key ID: 5D5E18ACB990F57A
2 changed files with 98 additions and 7 deletions

View file

@ -6,9 +6,12 @@ import axios from 'axios';
import { ulid } from "ulid";
import GenericEmbed from "../types/GenericEmbed";
import FormData from 'form-data';
import { revoltFetchMessage } from "../util";
import { discordFetchUser, revoltFetchMessage } from "../util";
import { TextChannel } from "discord.js";
const MAX_BRIDGED_FILE_SIZE = 8_000_000; // 8 MB
const RE_MENTION_USER = /<@!*[0-9]+>/g;
const RE_MENTION_CHANNEL = /<#[0-9]+>/g;
client.on('messageDelete', async message => {
try {
@ -51,7 +54,7 @@ client.on('messageUpdate', async (oldMsg, newMsg) => {
const targetMsg = await revoltFetchMessage(bridgedMsg.revolt.messageId, revoltClient.channels.get(bridgeCfg.revolt));
if (!targetMsg) return logger.debug(`Discord: Could not fetch message from Revolt`);
await targetMsg.edit({ content: newMsg.content || undefined });
await targetMsg.edit({ content: newMsg.content ? await renderMessageBody(newMsg.content) : undefined });
} catch(e) {
console.error(e);
}
@ -146,7 +149,7 @@ client.on('messageCreate', async message => {
const sendBridgeMessage = async (reply?: string) => {
const payload = {
content: message.content,
content: message.content ? await renderMessageBody(message.content) : undefined,
//attachments: [],
//embeds: [],
nonce: nonce,
@ -192,3 +195,44 @@ client.on('messageCreate', async message => {
console.error(e);
}
});
// Replaces @mentions and #channel mentions
async function renderMessageBody(message: string): Promise<string> {
// We don't want users to generate large amounts of database and API queries
let failsafe = 0;
// @mentions
while (failsafe < 10) {
failsafe++;
const text = message.match(RE_MENTION_USER)?.[0];
if (!text) break;
const id = text.replace('<@!', '').replace('<@', '').replace('>', '');
const user = await discordFetchUser(id);
// replaceAll() when
while (message.includes(text)) message = message.replace(text, `@${user?.username || id}`);
}
// #channels
while (failsafe < 10) {
failsafe++;
const text = message.match(RE_MENTION_CHANNEL)?.[0];
if (!text) break;
const id = text.replace('<#', '').replace('>', '');
const channel = client.channels.cache.get(id);
const bridgeCfg = channel ? await BRIDGE_CONFIG.findOne({ discord: channel.id }) : undefined;
const revoltChannel = bridgeCfg?.revolt
? revoltClient.channels.get(bridgeCfg.revolt)
: undefined;
while (message.includes(text)) {
message = message.replace(text, revoltChannel ? `<#${revoltChannel._id}>` : `#${(channel as TextChannel)?.name || id}`);
}
}
return message;
}

View file

@ -1,9 +1,13 @@
import { BRIDGED_MESSAGES, BRIDGE_CONFIG, logger } from "..";
import { AUTUMN_URL, client } from "./client";
import { MessageEmbed, MessagePayload, WebhookClient, WebhookMessageOptions } from "discord.js";
import { client as discordClient } from "../discord/client";
import { MessageEmbed, MessagePayload, TextChannel, WebhookClient, WebhookMessageOptions } from "discord.js";
import GenericEmbed from "../types/GenericEmbed";
import { SendableEmbed } from "revolt-api";
import { clipText, discordFetchMessage } from "../util";
import { clipText, discordFetchMessage, revoltFetchUser } from "../util";
const RE_MENTION_USER = /<@[0-9A-HJ-KM-NP-TV-Z]{26}>/g;
const RE_MENTION_CHANNEL = /<#[0-9A-HJ-KM-NP-TV-Z]{26}>/g;
client.on('message/delete', async id => {
try {
@ -54,7 +58,7 @@ client.on('message/update', async message => {
if (!targetMsg) return logger.debug(`Revolt: Could not fetch message from Discord`);
const client = new WebhookClient({ id: bridgeCfg.discordWebhook.id, token: bridgeCfg.discordWebhook.token });
await client.editMessage(targetMsg, { content: message.content, allowedMentions: { parse: [ ] } });
await client.editMessage(targetMsg, { content: await renderMessageBody(message.content), allowedMentions: { parse: [ ] } });
client.destroy();
} catch(e) { console.error(e) }
});
@ -104,7 +108,7 @@ client.on('message', async message => {
});
const payload: MessagePayload|WebhookMessageOptions = {
content: message.content || undefined,
content: message.content ? await renderMessageBody(message.content) : undefined,
username: message.author?.username ?? 'Unknown user',
avatarURL: message.author?.generateAvatarURL({ max_side: 128 }),
embeds: message.embeds?.length
@ -178,3 +182,46 @@ client.on('message', async message => {
console.error(e);
}
});
// Replaces @mentions, #channel mentions and :emojis:
async function renderMessageBody(message: string): Promise<string> {
// We don't want users to generate large amounts of database and API queries
let failsafe = 0;
// @mentions
while (failsafe < 10) {
failsafe++;
const text = message.match(RE_MENTION_USER)?.[0];
if (!text) break;
const id = text.replace('<@', '').replace('>', '');
const user = await revoltFetchUser(id);
// replaceAll() when
while (message.includes(text)) message = message.replace(text, `@${user?.username || id}`);
}
// #channels
while (failsafe < 10) {
failsafe++;
const text = message.match(RE_MENTION_CHANNEL)?.[0];
if (!text) break;
const id = text.replace('<#', '').replace('>', '');
const channel = client.channels.get(id);
const bridgeCfg = channel ? await BRIDGE_CONFIG.findOne({ revolt: channel._id }) : undefined;
const discordChannel = bridgeCfg?.discord
? discordClient.channels.cache.get(bridgeCfg.discord)
: undefined;
while (message.includes(text)) {
message = message.replace(text, discordChannel ? `<#${discordChannel.id}>` : `#${channel?.name || id}`);
}
}
// :emojis: (todo lol)
return message;
}