UNPKG

discord-hangman

Version:

🎲 Complete framework to facilitate the creation of hangman games using discord.js V13

131 lines (115 loc) • 5.75 kB
const defaultOptions = require('./defaultOptions.js'); const Hangman = require('./hangman.js'); class HangmansManager { async create(interaction, gameType, options = {}) { await interaction.deferReply(); if (!['custom', 'random'].includes(gameType)) throw new Error('Gamemode must be either \'custom\' or \'random\''); let word = options.word || null; const lives = options.lives || 6; const messages = options.messages || defaultOptions; const displayWordOnGameOver = typeof options.displayWordOnGameOver === 'boolean' ? options.displayWordOnGameOver : true; const players = options.players || await this.#gatherPlayers(interaction, messages, options.filter ? options.filter : () => true); if (players.length === 0) return interaction.editReply({ content: messages.createNoPlayers }); if (gameType === 'custom' && players.length < 2) return interaction.editReply({ content: messages.customNotEnoughPlayers }); let selector; if (gameType === 'custom') { await interaction.editReply({ content: messages.customInitMessage.replace(/{players}/gi, players.length) }); // eslint-disable-next-line no-case-declarations const userSelection = await this.#getWordFromPlayers(players, interaction, messages); if (userSelection) { word = userSelection.word; selector = userSelection.selector; } else return interaction.editReply({ content: messages.customNoMoreWords }); }; await interaction.deleteReply(); const game = new Hangman(word, interaction, players, messages, displayWordOnGameOver, lives); await game.start(); return { game, selector }; }; #gatherPlayersFromMessage(interaction, filter) { return new Promise(resolve => { const players = []; const gatherFilter = msg => msg.content.toLowerCase().includes('join') && !msg.author.bot && filter(msg.author); const collector = interaction.channel.createMessageCollector({ gatherFilter, time: 10_000 }); collector.on('collect', msg => { players.push(msg.author); msg.delete(); }); collector.on('end', async () => resolve(players) ); }); }; async #gatherPlayersFromReaction(botReply, emoji, filter) { botReply.react(emoji); // eslint-disable-next-line no-async-promise-executor return new Promise(async resolve => { let players = []; const gatherFilter = (r, u) => r.emoji.name === emoji && !u.bot && filter(u); const collector = botReply.createReactionCollector({ gatherFilter, time: 10_000, dispose: true }); collector.on('collect', (r, u) => { if(!u.bot) players.push(u) }); collector.on('remove', (r, u) => { players = players.filter(p => p.id !== u.id ) }); collector.on('end', async () => { resolve(players); }); }); }; async #gatherPlayers(interaction, messages, filter) { await interaction.editReply({ content: messages.gatherPlayersMsg }); const botReply = await interaction.fetchReply(); const p1 = this.#gatherPlayersFromMessage(interaction, filter); const p2 = this.#gatherPlayersFromReaction(botReply, '📒', filter); const aPlayers = await Promise.all([p1, p2]); await botReply.reactions.removeAll(); const players = []; // join both arrays of players into one of unique players. aPlayers.forEach(ps => ps.forEach(p => { if (!players.find(pOther => pOther.id == p.id)) players.push(p); })); return players; }; async #getWordFromPlayers(players, interaction, messages) { let word; let chosenOne; while (!word && players.length > 1) { const index = Math.floor((Math.random() * 1000) % players.length); chosenOne = players[index]; players.splice(index, 1); const dm = await chosenOne.createDM(); await dm.send(messages.getWordFromPlayersDm); let finish = false; let tries = 0; let msgCollection; while (!finish && tries < 3) { try { const filter = (m) => !m.author.bot; msgCollection = await dm.awaitMessages({ filter, max: 1, time: 30_000, errors: ['time'] }) .catch((collected) => { throw collected; }); } catch (collected) { await dm.send(messages.timesUpDm); await interaction.editReply({ content: messages.timesUpMsg }); finish = true; continue; }; const msg = msgCollection.first().content; if (msg.match(/^[A-Za-zÀ-ú]{3,}$/)) { word = msg.toLowerCase(); finish = true; dm.send(messages.wordSuccess); } else { await dm.send(messages.invalidWord); ++tries; if (tries == 3) await dm.send(messages.tooManyInvalidsWords); }; }; }; if (!word && players.length <= 1) return; return { word: word, selector: chosenOne }; }; }; module.exports = new HangmansManager();