From 6cf094c28214c24fd70045e848c48bfb33eaf47a Mon Sep 17 00:00:00 2001 From: Almeida Date: Thu, 2 May 2024 21:54:00 +0100 Subject: [PATCH] feat(MessageManager): poll methods (#10239) * feat(MessageManager): poll methods * docs: wording Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com> --------- Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com> --- .../discord.js/src/managers/MessageManager.js | 32 +++++++++++++++++++ packages/discord.js/src/structures/Poll.js | 13 +++----- .../discord.js/src/structures/PollAnswer.js | 24 +++++++------- packages/discord.js/typings/index.d.ts | 12 +++++-- packages/discord.js/typings/index.test-d.ts | 7 ++++ 5 files changed, 64 insertions(+), 24 deletions(-) diff --git a/packages/discord.js/src/managers/MessageManager.js b/packages/discord.js/src/managers/MessageManager.js index 840dc371c..b88cbc99f 100644 --- a/packages/discord.js/src/managers/MessageManager.js +++ b/packages/discord.js/src/managers/MessageManager.js @@ -266,6 +266,38 @@ class MessageManager extends CachedManager { await this.client.rest.delete(Routes.channelMessage(this.channel.id, message)); } + + /** + * Ends a poll. + * @param {Snowflake} channelId The id of the channel + * @param {Snowflake} messageId The id of the message + * @returns {Promise} + */ + async endPoll(channelId, messageId) { + const message = await this.client.rest.post(Routes.expirePoll(channelId, messageId)); + return this._add(message, false); + } + + /** + * Options used for fetching voters of an answer in a poll. + * @typedef {BaseFetchPollAnswerVotersOptions} FetchPollAnswerVotersOptions + * @param {Snowflake} channelId The id of the channel + * @param {Snowflake} messageId The id of the message + * @param {number} answerId The id of the answer + */ + + /** + * Fetches the users that voted for a poll answer. + * @param {FetchPollAnswerVotersOptions} options The options for fetching the poll answer voters + * @returns {Promise>} + */ + async fetchPollAnswerVoters({ channelId, messageId, answerId, after, limit }) { + const voters = await this.client.rest.get(Routes.pollAnswerVoters(channelId, messageId, answerId), { + query: makeURLSearchParams({ limit, after }), + }); + + return voters.users.reduce((acc, user) => acc.set(user.id, this.client.users._add(user, false)), new Collection()); + } } module.exports = MessageManager; diff --git a/packages/discord.js/src/structures/Poll.js b/packages/discord.js/src/structures/Poll.js index 5492ef3d8..710ac267c 100644 --- a/packages/discord.js/src/structures/Poll.js +++ b/packages/discord.js/src/structures/Poll.js @@ -1,7 +1,6 @@ 'use strict'; const { Collection } = require('@discordjs/collection'); -const { Routes } = require('discord-api-types/v10'); const Base = require('./Base'); const { PollAnswer } = require('./PollAnswer'); const { DiscordjsError } = require('../errors/DJSError'); @@ -95,19 +94,15 @@ class Poll extends Base { } /** - * End this poll + * Ends this poll. * @returns {Promise} */ - async end() { + end() { if (Date.now() > this.expiresTimestamp) { - throw new DiscordjsError(ErrorCodes.PollAlreadyExpired); + return Promise.reject(new DiscordjsError(ErrorCodes.PollAlreadyExpired)); } - const message = await this.client.rest.post(Routes.expirePoll(this.message.channel.id, this.message.id)); - - const clone = this.message._clone(); - clone._patch(message); - return clone; + return this.message.channel.messages.endPoll(this.message.channel.id, this.message.id); } } diff --git a/packages/discord.js/src/structures/PollAnswer.js b/packages/discord.js/src/structures/PollAnswer.js index 56f66c6bb..68ce7e56c 100644 --- a/packages/discord.js/src/structures/PollAnswer.js +++ b/packages/discord.js/src/structures/PollAnswer.js @@ -1,8 +1,5 @@ 'use strict'; -const { Collection } = require('@discordjs/collection'); -const { makeURLSearchParams } = require('@discordjs/rest'); -const { Routes } = require('discord-api-types/v10'); const Base = require('./Base'); const { Emoji } = require('./Emoji'); @@ -68,24 +65,25 @@ class PollAnswer extends Base { } /** - * @typedef {Object} FetchPollVotersOptions + * Options used for fetching voters of a poll answer. + * @typedef {Object} BaseFetchPollAnswerVotersOptions * @property {number} [limit] The maximum number of voters to fetch * @property {Snowflake} [after] The user id to fetch voters after */ /** - * Fetches the users that voted for this answer - * @param {FetchPollVotersOptions} [options={}] The options for fetching voters + * Fetches the users that voted for this answer. + * @param {BaseFetchPollAnswerVotersOptions} [options={}] The options for fetching voters * @returns {Promise>} */ - async fetchVoters({ after, limit } = {}) { - const { message } = this.poll; - - const voters = await this.client.rest.get(Routes.pollAnswerVoters(message.channel.id, message.id, this.id), { - query: makeURLSearchParams({ limit, after }), + fetchVoters({ after, limit } = {}) { + return this.poll.message.channel.fetchPollAnswerVoters({ + channelId: this.poll.message.channel.id, + messageId: this.poll.message.id, + answerId: this.id, + after, + limit, }); - - return voters.users.reduce((acc, user) => acc.set(user.id, this.client.users._add(user, false)), new Collection()); } } diff --git a/packages/discord.js/typings/index.d.ts b/packages/discord.js/typings/index.d.ts index 6723969f6..de0038b6a 100644 --- a/packages/discord.js/typings/index.d.ts +++ b/packages/discord.js/typings/index.d.ts @@ -2608,7 +2608,7 @@ export class Poll extends Base { public end(): Promise; } -export interface FetchPollVotersOptions { +export interface BaseFetchPollAnswerVotersOptions { after?: Snowflake; limit?: number; } @@ -2621,7 +2621,7 @@ export class PollAnswer extends Base { public text: string | null; public voteCount: number; public get emoji(): GuildEmoji | Emoji | null; - public fetchVoters(options?: FetchPollVotersOptions): Promise>; + public fetchVoters(options?: BaseFetchPollAnswerVotersOptions): Promise>; } export class ReactionCollector extends Collector { @@ -4397,6 +4397,12 @@ export class GuildMemberRoleManager extends DataManager; } +export interface FetchPollAnswerVotersOptions extends BaseFetchPollAnswerVotersOptions { + channelId: Snowflake; + messageId: Snowflake; + answerId: number; +} + export abstract class MessageManager extends CachedManager< Snowflake, Message, @@ -4415,6 +4421,8 @@ export abstract class MessageManager extends public react(message: MessageResolvable, emoji: EmojiIdentifierResolvable): Promise; public pin(message: MessageResolvable, reason?: string): Promise; public unpin(message: MessageResolvable, reason?: string): Promise; + public endPoll(channelId: Snowflake, messageId: Snowflake): Promise; + public fetchPollAnswerVoters(options: FetchPollAnswerVotersOptions): Promise>; } export class DMMessageManager extends MessageManager { diff --git a/packages/discord.js/typings/index.test-d.ts b/packages/discord.js/typings/index.test-d.ts index ef44dca76..6b867b39a 100644 --- a/packages/discord.js/typings/index.test-d.ts +++ b/packages/discord.js/typings/index.test-d.ts @@ -2548,4 +2548,11 @@ declare const poll: Poll; expectType(answer.voteCount); expectType>(await answer.fetchVoters({ after: snowflake, limit: 10 })); + + await messageManager.endPoll(snowflake, snowflake); + await messageManager.fetchPollAnswerVoters({ + channelId: snowflake, + messageId: snowflake, + answerId: 1, + }); }