allow discord users to opt out of the bridge

This commit is contained in:
JandereDev 2022-05-26 19:08:19 +02:00
parent 800b9ed492
commit 8acd65159d
Signed by: Lea
GPG key ID: 5D5E18ACB990F57A
6 changed files with 100 additions and 7 deletions

View file

@ -3,7 +3,7 @@
import { client } from "./client";
import { REST } from '@discordjs/rest';
import { Routes } from 'discord-api-types/v9';
import { BRIDGED_MESSAGES, BRIDGE_CONFIG, BRIDGE_REQUESTS, logger } from "..";
import { BRIDGED_MESSAGES, BRIDGE_CONFIG, BRIDGE_REQUESTS, BRIDGE_USER_CONFIG, logger } from "..";
import { MessageEmbed, TextChannel } from "discord.js";
import { revoltFetchMessage, revoltFetchUser } from "../util";
import { client as revoltClient } from "../revolt/client";
@ -36,7 +36,20 @@ const COMMANDS: any[] = [
name: 'help',
description: 'Usage instructions',
type: 1,
}
},
{
name: 'opt_out',
description: 'Opt out of having your messages bridged',
type: 1,
options: [
{
name: 'opt_out',
description: 'Whether you wish to opt out of having your messages bridged',
optional: true,
type: 5 // Boolean
},
],
},
],
},
{
@ -168,6 +181,46 @@ client.on('interactionCreate', async interaction => {
await interaction.reply({ embeds: [ embed ], ephemeral: true });
break;
case 'opt_out':
const optOut = interaction.options.getBoolean('opt_out', false);
if (optOut == null) {
const userConfig = await BRIDGE_USER_CONFIG.findOne({ id: interaction.user.id });
if (userConfig?.optOut) {
return await interaction.reply({
ephemeral: true,
content: 'You are currently **opted out** of message bridging. ' +
'Users on Revolt **will not** see your username, avatar or message content.'
});
} else {
return await interaction.reply({
ephemeral: true,
content: 'You are currently **not** opted out of message bridging. ' +
'All your messages in a bridged channel will be sent to the associated Revolt channel.'
});
}
} else {
await BRIDGE_USER_CONFIG.update(
{ id: interaction.user.id },
{
$setOnInsert: { id: interaction.user.id },
$set: { optOut },
},
{ upsert: true }
);
return await interaction.reply({
ephemeral: true,
content: `You have **opted ${optOut ? 'out of' : 'into'}** message bridging. `
+ (
optOut
? 'Your username, avatar and message content will no longer be visible on Revolt.\n' +
'Please note that some servers may be configured to automatically delete your messages.'
: 'All your messages in a bridged channel will be sent to the associated Revolt channel.'
),
});
}
break;
default: await interaction.reply('Unknown subcommand');
}

View file

@ -1,4 +1,4 @@
import { BRIDGED_MESSAGES, BRIDGE_CONFIG, logger } from "..";
import { BRIDGED_MESSAGES, BRIDGE_CONFIG, BRIDGE_USER_CONFIG, logger } from "..";
import { client } from "./client";
import { AUTUMN_URL, client as revoltClient } from "../revolt/client";
import axios from 'axios';
@ -27,6 +27,7 @@ client.on('messageDelete', async message => {
]);
if (!bridgedMsg?.revolt) return logger.debug(`Discord: Message has not been bridged; ignoring deletion`);
if (!bridgedMsg.ignore) return logger.debug(`Discord: Message marked as ignore`);
if (!bridgeCfg?.revolt) return logger.debug(`Discord: No Revolt channel associated`);
const targetMsg = await revoltFetchMessage(bridgedMsg.revolt.messageId, revoltClient.channels.get(bridgeCfg.revolt));
@ -51,6 +52,7 @@ client.on('messageUpdate', async (oldMsg, newMsg) => {
]);
if (!bridgedMsg) return logger.debug(`Discord: Message has not been bridged; ignoring edit`);
if (!bridgedMsg.ignore) return logger.debug(`Discord: Message marked as ignore`);
if (!bridgeCfg?.revolt) return logger.debug(`Discord: No Revolt channel associated`);
if (newMsg.webhookId && newMsg.webhookId == bridgeCfg.discordWebhook?.id) {
return logger.debug(`Discord: Message was sent by bridge; ignoring edit`);
@ -69,12 +71,13 @@ client.on('messageUpdate', async (oldMsg, newMsg) => {
client.on('messageCreate', async message => {
try {
logger.debug(`[M] Discord: ${message.content}`);
const [ bridgeCfg, bridgedReply ] = await Promise.all([
const [ bridgeCfg, bridgedReply, userConfig ] = await Promise.all([
BRIDGE_CONFIG.findOne({ discord: message.channelId }),
(message.reference?.messageId
? BRIDGED_MESSAGES.findOne({ "discord.messageId": message.reference.messageId })
: undefined
),
BRIDGE_USER_CONFIG.findOne({ id: message.author.id }),
]);
if (message.webhookId && bridgeCfg?.discordWebhook?.id == message.webhookId) {
@ -98,6 +101,11 @@ client.on('messageCreate', async message => {
}
}
if (bridgeCfg.disallowIfOptedOut && userConfig?.optOut && message.deletable) {
await message.delete();
return;
}
// Setting a known nonce allows us to ignore bridged
// messages while still letting other AutoMod messages pass.
const nonce = ulid();
@ -105,7 +113,7 @@ client.on('messageCreate', async message => {
await BRIDGED_MESSAGES.update(
{ "discord.messageId": message.id },
{
$setOnInsert: {
$setOnInsert: userConfig?.optOut ? {} : {
origin: 'discord',
discord: {
messageId: message.id,
@ -116,12 +124,32 @@ client.on('messageCreate', async message => {
channels: {
discord: message.channelId,
revolt: bridgeCfg.revolt,
}
},
ignore: userConfig?.optOut,
}
},
{ upsert: true }
);
if (userConfig?.optOut) {
const msg = await channel.sendMessage({
content: `$\\color{#565656}\\small{\\textsf{Message content redacted}}$`,
masquerade: {
name: 'AutoMod Bridge',
},
nonce: nonce,
});
await BRIDGED_MESSAGES.update(
{ "discord.messageId": message.id },
{
$set: { "revolt.messageId": msg._id },
}
);
return;
}
const autumnUrls: string[] = [];
// todo: upload all attachments at once instead of sequentially

View file

@ -8,6 +8,7 @@ import BridgeConfig from './types/BridgeConfig';
import BridgedMessage from './types/BridgedMessage';
import BridgeRequest from './types/BridgeRequest';
import DiscordBridgedEmoji from './types/DiscordBridgedEmoji';
import BridgeUserConfig from './types/BridgeUserConfig';
config();
@ -17,6 +18,7 @@ const BRIDGED_MESSAGES: ICollection<BridgedMessage> = db.get('bridged_messages')
const BRIDGE_CONFIG: ICollection<BridgeConfig> = db.get('bridge_config');
const BRIDGE_REQUESTS: ICollection<BridgeRequest> = db.get('bridge_requests');
const BRIDGED_EMOJIS: ICollection<DiscordBridgedEmoji> = db.get('bridged_emojis');
const BRIDGE_USER_CONFIG: ICollection<BridgeUserConfig> = db.get('bridge_user_config');
for (const v of [ 'REVOLT_TOKEN', 'DISCORD_TOKEN', 'DB_STRING' ]) {
if (!process.env[v]) {
@ -33,4 +35,4 @@ for (const v of [ 'REVOLT_TOKEN', 'DISCORD_TOKEN', 'DB_STRING' ]) {
]);
})();
export { logger, db, BRIDGED_MESSAGES, BRIDGE_CONFIG, BRIDGE_REQUESTS, BRIDGED_EMOJIS }
export { logger, db, BRIDGED_MESSAGES, BRIDGE_CONFIG, BRIDGE_REQUESTS, BRIDGED_EMOJIS, BRIDGE_USER_CONFIG }

View file

@ -10,4 +10,7 @@ export default class {
id: string;
token: string;
}
// If true, messages by users who have opted out of bridging will be deleted.
disallowIfOptedOut?: boolean;
}

View file

@ -0,0 +1,5 @@
export default class {
platform: 'discord'; // Todo: Revolt users too?
id: string;
optOut?: boolean;
}

View file

@ -15,4 +15,6 @@ export default class {
discord: string;
revolt: string;
}
ignore?: boolean;
}