diff --git a/src/client/components/commands/utility/Poll.ts b/src/client/components/commands/utility/Poll.ts index 37d8553..b45fb3e 100644 --- a/src/client/components/commands/utility/Poll.ts +++ b/src/client/components/commands/utility/Poll.ts @@ -56,91 +56,76 @@ class PollCommand extends SlashCommand async execute (invoker: InvokerWrapper, { choices, channel, duration, multichoice, message }: CommandParams) { - const { subcommand, author } = invoker; - const guild = invoker.guild!; - const member = invoker.member!; + const { subcommand } = invoker; if (subcommand!.name === 'create') - { - const targetChannel = (channel?.asChannel || invoker.channel) as GuildTextBasedChannel; - if (!targetChannel?.isTextBased()) - throw new CommandError(invoker, { index: 'ERR_INVALID_CHANNEL_TYPE' }); - const botMissing = targetChannel.permissionsFor(this.client.user!)?.missing([ 'SendMessages', 'EmbedLinks' ]); - const userMissing = targetChannel.permissionsFor(member).missing([ 'SendMessages' ]); - if (!botMissing || botMissing.length) - return invoker.editReply({ index: 'COMMAND_POLL_BOT_PERMS', params: { missing: botMissing?.join(', ') ?? 'ALL', channel: targetChannel.id } }); - if (userMissing.length) - return invoker.editReply({ index: 'COMMAND_POLL_USER_PERMS', params: { missing: userMissing.join(', '), channel: targetChannel.id } }); - - const questions = await this.#queryQuestions(invoker, choices?.asNumber ?? 1, targetChannel); - if (!questions) - return; - - await invoker.editReply({ index: 'COMMAND_POLL_STARTING' }); - - const embed = { - title: guild.format('COMMAND_POLL_TITLE', { user: author.tag }), - description: guild.format('COMMAND_POLL_DESCRIPTION', { - multi: guild.format('COMMAND_POLL_MULTI', { multichoice: multichoice?.asBool && questions.length > 1 || false }, { code: true }), - duration: duration ? guild.format('COMMAND_POLL_DURATION', { time: Util.humanise(duration.asNumber), duration: Math.floor(Date.now() / 1000) + duration.asNumber }) : guild.format('COMMAND_POLL_INFINITE') - }), - fields: questions, - color: EmbedDefaultColor, - timestamp: new Date().toISOString() - }; - - let pollMsg = null; - if (questions.length === 1) - { - questions[0].name = guild.format('COMMAND_POLL_FIELD_QUESTION'); - pollMsg = await targetChannel.send({ embeds: [ embed ] }); - await pollMsg.react('👍'); - await pollMsg.react('👎'); - } - else - { - pollMsg = await targetChannel.send({ embeds: [ embed ] }); - for (const question of questions) - await pollMsg.react(PollReactions.Multi[question.index + 1]); - } - - const poll: PollData = { - questions: questions.map(q => q.value), - duration: (duration?.asNumber ?? 0), - multiChoice: multichoice?.asBool && questions.length > 1 || false, - user: author.id, - channel: targetChannel.id, - startedIn: invoker.channel!.id, - message: pollMsg.id - }; - - if (duration) - await this.client.polls.create(poll, guild.id); - await invoker.editReply({ emoji: 'success', index: 'COMMAND_POLL_START', params: { channel: targetChannel.id } }); - } + return this.#createPoll(invoker, { choices, channel, duration, multichoice }); else if (subcommand!.name === 'delete') - { - const poll = await this.client.polls.delete(message!.asString); - if (!poll) - return { index: 'COMMAND_POLL_404', emoji: 'failure' }; - const pollChannel = await guild.resolveChannel(poll.payload.channel); - if (!pollChannel) - return { index: 'COMMAND_POLL_MISSING_CHANNEL', emoji: 'failure' }; - const msg = await pollChannel.messages.fetch(poll.payload.message).catch(() => null); - if (msg) - await msg.delete(); - return { index: 'COMMAND_POLL_DELETED', emoji: 'success' }; - } + return this.#deletePoll(invoker, { message }); else if (subcommand!.name === 'end') - { - const poll = await this.client.polls.find(message!.asString); - if (!poll) - return { index: 'COMMAND_POLL_404', emoji: 'failure' }; - await this.client.polls.end(poll.payload); - // await guild._poll(poll.data as PollData & CallbackData); - return { index: 'COMMAND_POLL_ENDED', emoji: 'success' }; - } + return this.#endPoll(invoker, { message }); } + + async #createPoll (invoker: InvokerWrapper, { choices, channel, duration, multichoice }: CommandParams) + { + const { guild, member, author } = invoker; + const targetChannel = (channel?.asChannel || invoker.channel) as GuildTextBasedChannel; + if (!targetChannel?.isTextBased()) + throw new CommandError(invoker, { index: 'ERR_INVALID_CHANNEL_TYPE' }); + const botMissing = targetChannel.permissionsFor(this.client.user!)?.missing([ 'SendMessages', 'EmbedLinks' ]); + const userMissing = targetChannel.permissionsFor(member).missing([ 'SendMessages' ]); + if (!botMissing || botMissing.length) + return invoker.editReply({ index: 'COMMAND_POLL_BOT_PERMS', params: { missing: botMissing?.join(', ') ?? 'ALL', channel: targetChannel.id } }); + if (userMissing.length) + return invoker.editReply({ index: 'COMMAND_POLL_USER_PERMS', params: { missing: userMissing.join(', '), channel: targetChannel.id } }); + + const questions = await this.#queryQuestions(invoker, choices?.asNumber ?? 1, targetChannel); + if (!questions) + return; + + await invoker.editReply({ index: 'COMMAND_POLL_STARTING' }); + + const embed = { + title: guild.format('COMMAND_POLL_TITLE', { user: author.tag }), + description: guild.format('COMMAND_POLL_DESCRIPTION', { + multi: guild.format('COMMAND_POLL_MULTI', { multichoice: multichoice?.asBool && questions.length > 1 || false }, { code: true }), + duration: duration ? guild.format('COMMAND_POLL_DURATION', { time: Util.humanise(duration.asNumber), duration: Math.floor(Date.now() / 1000) + duration.asNumber }) : guild.format('COMMAND_POLL_INFINITE') + }), + fields: questions, + color: EmbedDefaultColor, + timestamp: new Date().toISOString() + }; + + let pollMsg = null; + if (questions.length === 1) + { + questions[0].name = guild.format('COMMAND_POLL_FIELD_QUESTION'); + pollMsg = await targetChannel.send({ embeds: [ embed ] }); + await pollMsg.react('👍'); + await pollMsg.react('👎'); + } + else + { + pollMsg = await targetChannel.send({ embeds: [ embed ] }); + for (const question of questions) + await pollMsg.react(PollReactions.Multi[question.index + 1]); + } + + const poll: PollData = { + questions: questions.map(q => q.value), + duration: (duration?.asNumber ?? 0), + multiChoice: multichoice?.asBool && questions.length > 1 || false, + user: author.id, + channel: targetChannel.id, + startedIn: invoker.channel!.id, + message: pollMsg.id + }; + + if (duration) + await this.client.polls.create(poll, guild.id); + await invoker.editReply({ emoji: 'success', index: 'COMMAND_POLL_START', params: { channel: targetChannel.id } }); + } + async #queryQuestions (invoker: InvokerWrapper, choices: number, targetchannel: GuildTextBasedChannel) { const { guild, member } = invoker; @@ -166,6 +151,31 @@ class PollCommand extends SlashCommand } return questions; } + + async #deletePoll (invoker: InvokerWrapper, { message }: CommandParams) + { + const { guild } = invoker; + const poll = await this.client.polls.delete(message!.asString); + if (!poll) + return { index: 'COMMAND_POLL_404', emoji: 'failure' }; + const pollChannel = await guild.resolveChannel(poll.payload.channel); + if (!pollChannel) + return { index: 'COMMAND_POLL_MISSING_CHANNEL', emoji: 'failure' }; + const msg = await pollChannel.messages.fetch(poll.payload.message).catch(() => null); + if (msg) + await msg.delete(); + return { index: 'COMMAND_POLL_DELETED', emoji: 'success' }; + } + + async #endPoll (_invoker: InvokerWrapper, { message }: CommandParams) + { + const poll = await this.client.polls.find(message!.asString); + if (!poll) + return { index: 'COMMAND_POLL_404', emoji: 'failure' }; + await this.client.polls.end(poll._id, poll.payload); + // await guild._poll(poll.data as PollData & CallbackData); + return { index: 'COMMAND_POLL_ENDED', emoji: 'success' }; + } } export default PollCommand; \ No newline at end of file diff --git a/src/client/components/managers/PollManager.ts b/src/client/components/managers/PollManager.ts index ccc22d4..306153a 100644 --- a/src/client/components/managers/PollManager.ts +++ b/src/client/components/managers/PollManager.ts @@ -47,12 +47,12 @@ class PollManager implements CallbackClient return poll; } - async handleCallback (_id: string, payload: PollData): Promise + async handleCallback (id: string, payload: PollData): Promise { - await this.end(payload); + await this.end(id, payload); } - async end ({ user, channel, startedIn, message, multiChoice }: PollData) + async end (id: string, { user, channel, startedIn, message, multiChoice }: PollData) { const startChannel = await this.#client.resolveChannel(startedIn); const pollChannel = await this.#client.resolveChannel(channel); @@ -89,6 +89,7 @@ class PollManager implements CallbackClient if (startChannel && startChannel.isTextBased()) await startChannel.send(guild.format('COMMAND_POLL_NOTIFY_STARTER', { user, channel })); } + await this.callbacks.removeCallback(id); } }