translate channel and user mentions
This commit is contained in:
parent
b567de2277
commit
f34d01745d
2 changed files with 98 additions and 7 deletions
|
@ -6,9 +6,12 @@ import axios from 'axios';
|
||||||
import { ulid } from "ulid";
|
import { ulid } from "ulid";
|
||||||
import GenericEmbed from "../types/GenericEmbed";
|
import GenericEmbed from "../types/GenericEmbed";
|
||||||
import FormData from 'form-data';
|
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 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 => {
|
client.on('messageDelete', async message => {
|
||||||
try {
|
try {
|
||||||
|
@ -51,7 +54,7 @@ client.on('messageUpdate', async (oldMsg, newMsg) => {
|
||||||
const targetMsg = await revoltFetchMessage(bridgedMsg.revolt.messageId, revoltClient.channels.get(bridgeCfg.revolt));
|
const targetMsg = await revoltFetchMessage(bridgedMsg.revolt.messageId, revoltClient.channels.get(bridgeCfg.revolt));
|
||||||
if (!targetMsg) return logger.debug(`Discord: Could not fetch message from 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) {
|
} catch(e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
@ -146,7 +149,7 @@ client.on('messageCreate', async message => {
|
||||||
|
|
||||||
const sendBridgeMessage = async (reply?: string) => {
|
const sendBridgeMessage = async (reply?: string) => {
|
||||||
const payload = {
|
const payload = {
|
||||||
content: message.content,
|
content: message.content ? await renderMessageBody(message.content) : undefined,
|
||||||
//attachments: [],
|
//attachments: [],
|
||||||
//embeds: [],
|
//embeds: [],
|
||||||
nonce: nonce,
|
nonce: nonce,
|
||||||
|
@ -192,3 +195,44 @@ client.on('messageCreate', async message => {
|
||||||
console.error(e);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
import { BRIDGED_MESSAGES, BRIDGE_CONFIG, logger } from "..";
|
import { BRIDGED_MESSAGES, BRIDGE_CONFIG, logger } from "..";
|
||||||
import { AUTUMN_URL, client } from "./client";
|
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 GenericEmbed from "../types/GenericEmbed";
|
||||||
import { SendableEmbed } from "revolt-api";
|
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 => {
|
client.on('message/delete', async id => {
|
||||||
try {
|
try {
|
||||||
|
@ -54,7 +58,7 @@ client.on('message/update', async message => {
|
||||||
if (!targetMsg) return logger.debug(`Revolt: Could not fetch message from Discord`);
|
if (!targetMsg) return logger.debug(`Revolt: Could not fetch message from Discord`);
|
||||||
|
|
||||||
const client = new WebhookClient({ id: bridgeCfg.discordWebhook.id, token: bridgeCfg.discordWebhook.token });
|
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();
|
client.destroy();
|
||||||
} catch(e) { console.error(e) }
|
} catch(e) { console.error(e) }
|
||||||
});
|
});
|
||||||
|
@ -104,7 +108,7 @@ client.on('message', async message => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const payload: MessagePayload|WebhookMessageOptions = {
|
const payload: MessagePayload|WebhookMessageOptions = {
|
||||||
content: message.content || undefined,
|
content: message.content ? await renderMessageBody(message.content) : undefined,
|
||||||
username: message.author?.username ?? 'Unknown user',
|
username: message.author?.username ?? 'Unknown user',
|
||||||
avatarURL: message.author?.generateAvatarURL({ max_side: 128 }),
|
avatarURL: message.author?.generateAvatarURL({ max_side: 128 }),
|
||||||
embeds: message.embeds?.length
|
embeds: message.embeds?.length
|
||||||
|
@ -178,3 +182,46 @@ client.on('message', async message => {
|
||||||
console.error(e);
|
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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue