Prevent all mentions from message responses. Some other light refactoring.

This commit is contained in:
Charlie Laabs
2022-01-05 16:40:44 -06:00
parent 947100282e
commit 564c4f9c7c
2 changed files with 54 additions and 43 deletions

View File

@@ -23,6 +23,7 @@ All notable changes to this project will be documented in this file.
* Discord slash command support * Discord slash command support
* Many more config options available at <https://claabs.github.io/markov-discord/classes/AppConfig.html> * Many more config options available at <https://claabs.github.io/markov-discord/classes/AppConfig.html>
* Config file supports [JSON5](https://json5.org/) (comments, trailing commas, etc) * Config file supports [JSON5](https://json5.org/) (comments, trailing commas, etc)
* Generated responses will now never ping a user or role, only just highlight their name
### 0.7.3 ### 0.7.3

View File

@@ -1,18 +1,14 @@
/* eslint-disable no-console */
import 'source-map-support/register'; import 'source-map-support/register';
import 'reflect-metadata'; import 'reflect-metadata';
import * as Discord from 'discord.js'; import * as Discord from 'discord.js';
import Markov, { import Markov, {
MarkovGenerateOptions, MarkovGenerateOptions,
MarkovConstructorOptions, MarkovConstructorOptions,
AddDataProps, AddDataProps,
} from 'markov-strings-db'; } from 'markov-strings-db';
import { createConnection } from 'typeorm'; import { createConnection } from 'typeorm';
import { MarkovInputData } from 'markov-strings-db/dist/src/entity/MarkovInputData'; import { MarkovInputData } from 'markov-strings-db/dist/src/entity/MarkovInputData';
import type { PackageJsonPerson } from 'types-package-json'; import type { PackageJsonPerson } from 'types-package-json';
import makeEta from 'simple-eta'; import makeEta from 'simple-eta';
import formatDistanceToNow from 'date-fns/formatDistanceToNow'; import formatDistanceToNow from 'date-fns/formatDistanceToNow';
import addSeconds from 'date-fns/addSeconds'; import addSeconds from 'date-fns/addSeconds';
@@ -376,7 +372,10 @@ async function generateResponse(
const response = await markov.generate<MarkovDataCustom>(markovGenerateOptions); const response = await markov.generate<MarkovDataCustom>(markovGenerateOptions);
L.info({ string: response.string }, 'Generated response text'); L.info({ string: response.string }, 'Generated response text');
L.debug({ response }, 'Generated response object'); L.debug({ response }, 'Generated response object');
const messageOpts: Discord.MessageOptions = { tts }; const messageOpts: Discord.MessageOptions = {
tts,
allowedMentions: { repliedUser: false, parse: [] },
};
const attachmentUrls = response.refs const attachmentUrls = response.refs
.filter((ref) => ref.custom && 'attachments' in ref.custom) .filter((ref) => ref.custom && 'attachments' in ref.custom)
.flatMap((ref) => (ref.custom as MarkovDataCustom).attachments); .flatMap((ref) => (ref.custom as MarkovDataCustom).attachments);
@@ -397,20 +396,26 @@ async function generateResponse(
messageOpts.files = [{ attachment: getRandomElement(randomMessageAttachmentUrls) }]; messageOpts.files = [{ attachment: getRandomElement(randomMessageAttachmentUrls) }];
} }
} }
response.string = response.string.replace(/@everyone/g, '@everyοne'); // Replace @everyone with a homoglyph 'o'
messageOpts.content = response.string; messageOpts.content = response.string;
const responseMessages: GenerateResponse = { const responseMessages: GenerateResponse = {
message: messageOpts, message: messageOpts,
}; };
if (debug) { if (debug) {
responseMessages.debug = { content: `\`\`\`\n${JSON.stringify(response, null, 2)}\n\`\`\`` }; responseMessages.debug = {
content: `\`\`\`\n${JSON.stringify(response, null, 2)}\n\`\`\``,
allowedMentions: { repliedUser: false, parse: [] },
};
} }
return responseMessages; return responseMessages;
} catch (err) { } catch (err) {
L.error(err); L.error(err);
return { error: { content: `\n\`\`\`\nERROR: ${err}\n\`\`\`` } }; return {
error: {
content: `\n\`\`\`\nERROR: ${err}\n\`\`\``,
allowedMentions: { repliedUser: false, parse: [] },
},
};
} }
} }
@@ -498,6 +503,31 @@ function inviteMessage(): Discord.MessageOptions {
return { embeds: [embed] }; return { embeds: [embed] };
} }
async function handleResponseMessage(
generatedResponse: GenerateResponse,
message: Discord.Message
): Promise<void> {
if (generatedResponse.message) await message.reply(generatedResponse.message);
if (generatedResponse.debug) await message.reply(generatedResponse.debug);
if (generatedResponse.error) await message.reply(generatedResponse.error);
}
async function handleUnprivileged(
interaction: Discord.CommandInteraction | Discord.SelectMenuInteraction,
deleteReply = true
): Promise<void> {
if (deleteReply) await interaction.deleteReply();
await interaction.followUp({ content: INVALID_PERMISSIONS_MESSAGE, ephemeral: true });
}
async function handleNoGuild(
interaction: Discord.CommandInteraction | Discord.SelectMenuInteraction,
deleteReply = true
): Promise<void> {
if (deleteReply) await interaction.deleteReply();
await interaction.followUp({ content: INVALID_GUILD_MESSAGE, ephemeral: true });
}
client.on('ready', async (readyClient) => { client.on('ready', async (readyClient) => {
L.info({ inviteUrl: generateInviteUrl() }, 'Bot logged in'); L.info({ inviteUrl: generateInviteUrl() }, 'Bot logged in');
@@ -538,23 +568,17 @@ client.on('messageCreate', async (message) => {
if (command === 'respond') { if (command === 'respond') {
L.debug('Responding to legacy command'); L.debug('Responding to legacy command');
const generatedResponse = await generateResponse(message); const generatedResponse = await generateResponse(message);
if (generatedResponse.message) await message.reply(generatedResponse.message); await handleResponseMessage(generatedResponse, message);
if (generatedResponse.debug) await message.reply(generatedResponse.debug);
if (generatedResponse.error) await message.reply(generatedResponse.error);
} }
if (command === 'tts') { if (command === 'tts') {
L.debug('Responding to legacy command tts'); L.debug('Responding to legacy command tts');
const generatedResponse = await generateResponse(message, { tts: true }); const generatedResponse = await generateResponse(message, { tts: true });
if (generatedResponse.message) await message.reply(generatedResponse.message); await handleResponseMessage(generatedResponse, message);
if (generatedResponse.debug) await message.reply(generatedResponse.debug);
if (generatedResponse.error) await message.reply(generatedResponse.error);
} }
if (command === 'debug') { if (command === 'debug') {
L.debug('Responding to legacy command debug'); L.debug('Responding to legacy command debug');
const generatedResponse = await generateResponse(message, { debug: true }); const generatedResponse = await generateResponse(message, { debug: true });
if (generatedResponse.message) await message.reply(generatedResponse.message); await handleResponseMessage(generatedResponse, message);
if (generatedResponse.debug) await message.reply(generatedResponse.debug);
if (generatedResponse.error) await message.reply(generatedResponse.error);
} }
if (command === null) { if (command === null) {
if (!message.author.bot) { if (!message.author.bot) {
@@ -563,9 +587,7 @@ client.on('messageCreate', async (message) => {
// <@!278354154563567636> how are you doing? // <@!278354154563567636> how are you doing?
const startSeed = message.content.replace(/<@!\d+>/g, '').trim(); const startSeed = message.content.replace(/<@!\d+>/g, '').trim();
const generatedResponse = await generateResponse(message, { startSeed }); const generatedResponse = await generateResponse(message, { startSeed });
if (generatedResponse.message) await message.reply(generatedResponse.message); await handleResponseMessage(generatedResponse, message);
if (generatedResponse.debug) await message.reply(generatedResponse.debug);
if (generatedResponse.error) await message.reply(generatedResponse.error);
} }
if (await isValidChannel(message.channelId)) { if (await isValidChannel(message.channelId)) {
@@ -598,6 +620,7 @@ client.on('messageUpdate', async (oldMessage, newMessage) => {
await markov.addData([newMessage.content]); await markov.addData([newMessage.content]);
}); });
// eslint-disable-next-line consistent-return
client.on('interactionCreate', async (interaction) => { client.on('interactionCreate', async (interaction) => {
if (interaction.isCommand()) { if (interaction.isCommand()) {
L.info({ command: interaction.commandName }, 'Recieved slash command'); L.info({ command: interaction.commandName }, 'Recieved slash command');
@@ -626,14 +649,10 @@ client.on('interactionCreate', async (interaction) => {
await interaction.editReply(reply); await interaction.editReply(reply);
} else if (subCommand === 'add') { } else if (subCommand === 'add') {
if (!isModerator(interaction.member)) { if (!isModerator(interaction.member)) {
await interaction.deleteReply(); return handleUnprivileged(interaction);
await interaction.followUp({ content: INVALID_PERMISSIONS_MESSAGE, ephemeral: true });
return;
} }
if (!interaction.guildId) { if (!interaction.guildId) {
await interaction.deleteReply(); return handleNoGuild(interaction);
await interaction.followUp({ content: INVALID_GUILD_MESSAGE, ephemeral: true });
return;
} }
const channels = getChannelsFromInteraction(interaction); const channels = getChannelsFromInteraction(interaction);
await addValidChannels(channels, interaction.guildId); await addValidChannels(channels, interaction.guildId);
@@ -642,14 +661,10 @@ client.on('interactionCreate', async (interaction) => {
); );
} else if (subCommand === 'remove') { } else if (subCommand === 'remove') {
if (!isModerator(interaction.member)) { if (!isModerator(interaction.member)) {
await interaction.deleteReply(); return handleUnprivileged(interaction);
await interaction.followUp({ content: INVALID_PERMISSIONS_MESSAGE, ephemeral: true });
return;
} }
if (!interaction.guildId) { if (!interaction.guildId) {
await interaction.deleteReply(); return handleNoGuild(interaction);
await interaction.followUp({ content: INVALID_GUILD_MESSAGE, ephemeral: true });
return;
} }
const channels = getChannelsFromInteraction(interaction); const channels = getChannelsFromInteraction(interaction);
await removeValidChannels(channels, interaction.guildId); await removeValidChannels(channels, interaction.guildId);
@@ -657,15 +672,13 @@ client.on('interactionCreate', async (interaction) => {
`Removed ${channels.length} text channels from the list. Use \`/train\` to remove these channels from the past known messages.` `Removed ${channels.length} text channels from the list. Use \`/train\` to remove these channels from the past known messages.`
); );
} else if (subCommand === 'modify') { } else if (subCommand === 'modify') {
await interaction.deleteReply();
if (!interaction.guild) { if (!interaction.guild) {
await interaction.followUp({ content: INVALID_GUILD_MESSAGE, ephemeral: true }); return handleNoGuild(interaction);
return;
} }
if (!isModerator(interaction.member)) { if (!isModerator(interaction.member)) {
await interaction.followUp({ content: INVALID_PERMISSIONS_MESSAGE, ephemeral: true }); await handleUnprivileged(interaction);
return;
} }
await interaction.deleteReply();
const dbTextChannels = await getTextChannels(interaction.guild); const dbTextChannels = await getTextChannels(interaction.guild);
const row = new Discord.MessageActionRow().addComponents( const row = new Discord.MessageActionRow().addComponents(
new Discord.MessageSelectMenu() new Discord.MessageSelectMenu()
@@ -698,13 +711,10 @@ client.on('interactionCreate', async (interaction) => {
await interaction.deferUpdate(); await interaction.deferUpdate();
const { guild } = interaction; const { guild } = interaction;
if (!isModerator(interaction.member)) { if (!isModerator(interaction.member)) {
await interaction.followUp({ content: INVALID_PERMISSIONS_MESSAGE, ephemeral: true }); return handleUnprivileged(interaction, false);
return;
} }
if (!guild) { if (!guild) {
await interaction.deleteReply(); return handleNoGuild(interaction, false);
await interaction.followUp({ content: INVALID_GUILD_MESSAGE, ephemeral: true });
return;
} }
const allChannels = const allChannels =