From fd52f6be22bb4549f455d38c87a5e95ff241508c Mon Sep 17 00:00:00 2001 From: BenSegal855 Date: Tue, 9 Feb 2021 22:55:12 -0500 Subject: [PATCH 1/2] feat: poll command --- src/commands/Fun/poll.ts | 57 ++++++++++++++++++++++++++++++++++++ src/languages/en-US.ts | 13 ++++++++ src/lib/types/Languages.d.ts | 6 ++++ 3 files changed, 76 insertions(+) create mode 100644 src/commands/Fun/poll.ts diff --git a/src/commands/Fun/poll.ts b/src/commands/Fun/poll.ts new file mode 100644 index 00000000..77dbb790 --- /dev/null +++ b/src/commands/Fun/poll.ts @@ -0,0 +1,57 @@ +import { SteveCommand } from '@lib/structures/commands/SteveCommand'; +import { CommandOptions, KlasaMessage } from 'klasa'; +import { Message, MessageReaction } from 'discord.js'; +import { ApplyOptions } from '@skyra/decorators'; +import { floatPromise } from '@utils/util'; + +@ApplyOptions({ + aliases: ['vote'], + description: lang => lang.tget('commandPollDescription'), + extendedHelp: lang => lang.tget('commandPollExtended'), + usage: ' [...]' +}) + +export default class extends SteveCommand { + + public async run(msg: KlasaMessage, [duration, name, ...choices]: [number, string, string]): Promise { + if (choices.length < 2) return msg.channel.send(msg.language.tget('commandPollTooFew')); + if (choices.length > 10) return msg.channel.send(msg.language.tget('commandPollTooMany')); + + // return msg.channel.send(`duration: ${duration}\nname: ${name}\nchoices: ${choices.join(', ')}`); + + const emotes = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟'].slice(0, choices.length); + + let out = `**${name}**\n`; + choices.forEach((choice, option) => { + out += `${emotes[option]} ${choice}\n`; + }); + + const pollMsg = await msg.channel.send(out); + + emotes.forEach(emote => { + floatPromise(this, pollMsg.react(emote)); + }); + + return pollMsg.awaitReactions( + (reaction: MessageReaction) => emotes.includes(reaction.emoji.name), + { time: duration } + ).then(reactions => { + let maxVotes = 0; + reactions.forEach(reaction => { + if (reaction.users.cache.size > maxVotes) { + maxVotes = reaction.users.cache.size; + } + }); + + if (maxVotes <= 1) return pollMsg.reply(msg.language.tget('commandPollFail')); + + const winners = reactions + .filter(reaction => reaction.users.cache.size >= maxVotes) + .map(reaction => choices[emotes.indexOf(reaction.emoji.name)]); + + // Replies here are for when djs 13 switches this function to using inline replies + return pollMsg.reply(msg.language.tget('commandPollEnd', winners, maxVotes - 1)); + }); + } + +} diff --git a/src/languages/en-US.ts b/src/languages/en-US.ts index 8c8ea1a9..88d05ab8 100644 --- a/src/languages/en-US.ts +++ b/src/languages/en-US.ts @@ -458,6 +458,19 @@ export default class extends Language { extendedHelp: 'The ability to search for a relevant XKCD is coming soon!' }), commandXkcdInvalid: 'I was unable to find that XKCD.', + commandPollDescription: `Have ${botName} create a poll for you`, + commandPollExtended: builder.display('poll', { + examples: [ + 'Is butt legs?|Butt is legs|Butt is butt' + ], + extendedHelp: 'This command requires you to have at least two options and no more than ten.' + }), + commandPollTooFew: 'I need more than one choice to create a poll.', + commandPollTooMany: 'I can\'t create a poll with more than ten choices.', + commandPollEnd: (options, votes) => options.length === 1 + ? `${options} won the poll with ${votes} vote${votes === 1 ? '' : 's'}.` + : `${options.join(' & ')} tied the poll with ${votes} vote${votes === 1 ? '' : 's'} each.`, + commandPollFail: 'It looks like no one voted in the poll.', /** * ################################ * # MODERATION SYSTEM # diff --git a/src/lib/types/Languages.d.ts b/src/lib/types/Languages.d.ts index e8443587..8cbfcb46 100644 --- a/src/lib/types/Languages.d.ts +++ b/src/lib/types/Languages.d.ts @@ -194,6 +194,12 @@ declare module 'klasa' { commandXkcdDescription: string; commandXkcdExtended: string; commandXkcdInvalid: string; + commandPollDescription: string; + commandPollExtended: string; + commandPollTooFew: string; + commandPollTooMany: string; + commandPollEnd: (options: string[], votes: number) => string; + commandPollFail: string; moderationNoDuration: string; moderationNoReason: string; moderationNoSteve: string; From a49844ca2dd78729df02d83f3c9b0718381d99bc Mon Sep 17 00:00:00 2001 From: BenSegal855 Date: Wed, 10 Feb 2021 16:16:21 -0500 Subject: [PATCH 2/2] tweak: edit poll to show winner --- src/commands/Fun/poll.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/commands/Fun/poll.ts b/src/commands/Fun/poll.ts index 77dbb790..ab22fc92 100644 --- a/src/commands/Fun/poll.ts +++ b/src/commands/Fun/poll.ts @@ -21,12 +21,12 @@ export default class extends SteveCommand { const emotes = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟'].slice(0, choices.length); - let out = `**${name}**\n`; + let pollText = `**${name}**\n`; choices.forEach((choice, option) => { - out += `${emotes[option]} ${choice}\n`; + pollText += `${emotes[option]} ${choice}\n`; }); - const pollMsg = await msg.channel.send(out); + const pollMsg = await msg.channel.send(pollText); emotes.forEach(emote => { floatPromise(this, pollMsg.react(emote)); @@ -50,6 +50,7 @@ export default class extends SteveCommand { .map(reaction => choices[emotes.indexOf(reaction.emoji.name)]); // Replies here are for when djs 13 switches this function to using inline replies + floatPromise(this, pollMsg.edit(`${pollText}${msg.language.tget('commandPollEnd', winners, maxVotes - 1)}`)); return pollMsg.reply(msg.language.tget('commandPollEnd', winners, maxVotes - 1)); }); }