147 lines
5.4 KiB
TypeScript
147 lines
5.4 KiB
TypeScript
import { GuildMember, Message, User, SlashCommandBuilder, Interaction } from 'discord.js';
|
|
|
|
const DEFAULT_EMOJI = '🪙';
|
|
const STOP_EMOJI = '⏹️';
|
|
const DONE_EMOJI = '👍';
|
|
|
|
const END_TEMPLATES = [
|
|
'Alright! Here\'s the messages you all conjured:',
|
|
'Here are the abominations you all have made:',
|
|
'Time\'s up! Here\'s what you\'ve managed to achieve:',
|
|
'That does it! Here\'s what you\'ve all cooked up together:'
|
|
];
|
|
|
|
const RANDOM_WORDS = [
|
|
'tarsorado', 'aboba', 'robtop', 'viprin', 'milk', 'milking station', 'radiation', 'extreme', 'glogging', 'glogged',
|
|
'penis', 'deadlocked', 'cream', 'dragon cream', 'urine', 'communal', 'piss', 'matpat', 'big and round', 'easy',
|
|
'cum', 'glue', 'tampon', 'contaminated water', 'centrifuge', 'inflation', 'plutonium', 'uranium', 'thorium',
|
|
'imposter', 'sounding', '💥', '🥵', '🎊', '!!!', '...', '???', '?..', '?!', '!', '?', 'balls itch', 'robert',
|
|
'gas leak', 'among us', 'stick a finger', 'overclock', 'breed', 'gay sex', 'breedable', 'cock vore', 'appendix',
|
|
'mukbang', 'edging', 'onlyfans', 'productive', 'mandelbrot', 'novosibirsk', 'oops!', 'farting', 'memory leak',
|
|
'pepsi can'
|
|
];
|
|
|
|
function formatMessage(users: User[], time: number) {
|
|
return `Starting a Markov chain game (${users.length} player${users.length !== 1 ? 's' : ''})\n`
|
|
+ users.map(user => `- ${user.toString()}`).join('\n') + '\n'
|
|
+ (time <= 0 ?
|
|
'**Already started**' :
|
|
`Starting in **${Math.ceil(time / 1000)}s** - react ${STOP_EMOJI} to begin now`
|
|
);
|
|
}
|
|
|
|
function randomWord() {
|
|
return RANDOM_WORDS[Math.floor(Math.random() * RANDOM_WORDS.length)];
|
|
}
|
|
|
|
module.exports = {
|
|
data: new SlashCommandBuilder()
|
|
.setName('markov')
|
|
.setDescription('Play a Markov chain game')
|
|
.addIntegerOption((option) =>
|
|
option
|
|
.setName('context')
|
|
.setRequired(false)
|
|
.setDescription('Amount of words to show as context')
|
|
.setMinValue(1)
|
|
),
|
|
|
|
execute: async (interaction: Interaction, member: GuildMember) => {
|
|
if (!interaction.isChatInputCommand()) return;
|
|
|
|
let participants: User[] = [member.user];
|
|
const context = interaction.options.getInteger('context') || 3;
|
|
|
|
const duration = 25_000;
|
|
|
|
const m = await interaction.reply({
|
|
fetchReply: true,
|
|
content: formatMessage(participants, duration)
|
|
});
|
|
|
|
if (!(m instanceof Message)) return;
|
|
|
|
const emoji = m.guild?.emojis.cache.random();
|
|
await m.react(emoji || DEFAULT_EMOJI);
|
|
await m.react(STOP_EMOJI);
|
|
|
|
const started = Date.now();
|
|
const collector = m.createReactionCollector({
|
|
filter: (reaction, user) =>
|
|
!user.bot && (
|
|
(
|
|
(emoji ? reaction.emoji.id === emoji.id : reaction.emoji.name === DEFAULT_EMOJI) &&
|
|
!participants.find(u => user.id === u.id)
|
|
) || (reaction.emoji.name === STOP_EMOJI && user.id === member.id)
|
|
),
|
|
time: duration,
|
|
dispose: true
|
|
});
|
|
|
|
collector.on('collect', (reaction, user) => {
|
|
if (reaction.emoji.name === STOP_EMOJI) {
|
|
collector.stop();
|
|
} else {
|
|
participants.push(user);
|
|
m.edit(formatMessage(participants, duration - (Date.now() - started)));
|
|
}
|
|
});
|
|
|
|
collector.on('remove', (_, user) => {
|
|
participants = participants.filter(u => u.id !== user.id);
|
|
m.edit(formatMessage(participants, duration - (Date.now() - started)));
|
|
});
|
|
|
|
collector.on('end', async () => {
|
|
m.edit(formatMessage(participants, 0));
|
|
|
|
let sentences: string[][] = Array(participants.length).fill(0);
|
|
sentences = sentences.map(() => []);
|
|
let iterations = 0;
|
|
const maxIterations = 10;
|
|
|
|
// eslint-disable-next-line no-constant-condition
|
|
while (true) {
|
|
await Promise.all(
|
|
participants.map(async (p, i) => {
|
|
const sentence = sentences[(i + iterations) % sentences.length];
|
|
const msg = await p.send(`Continue the following sentence: [${iterations}/${maxIterations}]\n\n> _${context < sentence.length ? '…' : ''}${sentence.length > 0 ? sentence.slice(-context).join(' ') : `start a sentence... (try working with: “${randomWord()}”)`}_` + (iterations === 0 ? '\n\n**Send a message to continue**' : ''));
|
|
try {
|
|
const collected = await msg.channel.awaitMessages({
|
|
max: 1,
|
|
time: 30_000,
|
|
errors: ['time']
|
|
});
|
|
const message = collected.first() as Message;
|
|
|
|
if (sentence.join(' ').length + message.content.length >= 2000) {
|
|
message.reply('stop that');
|
|
sentence.push(...randomWord().split(' '));
|
|
} else {
|
|
sentence.push(...message.content.split(' '));
|
|
await message.react(DONE_EMOJI);
|
|
}
|
|
} catch (err) {
|
|
await p.send('Took too long... Surprise... Added...... :)');
|
|
sentence.push(...randomWord().split(' '));
|
|
}
|
|
})
|
|
);
|
|
|
|
iterations++;
|
|
|
|
if (iterations > maxIterations) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
const endTemplate = END_TEMPLATES[Math.floor(Math.random() * END_TEMPLATES.length)];
|
|
await m.reply({
|
|
content: endTemplate + '\n\n' + sentences.map(sentence => '- “' + sentence.join(' ') + '”').join('\n') + '\n\nThank you for participating :)',
|
|
allowedMentions: {
|
|
parse: ['users']
|
|
}
|
|
});
|
|
});
|
|
}
|
|
}; |