Skip to content

Commit

Permalink
feat(model, cache, http): add support for polls (#2341)
Browse files Browse the repository at this point in the history
  • Loading branch information
suneettipirneni authored Jul 13, 2024
1 parent c9e8013 commit f660fd8
Show file tree
Hide file tree
Showing 33 changed files with 1,062 additions and 1 deletion.
1 change: 1 addition & 0 deletions twilight-cache-inmemory/src/event/interaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ mod tests {
mention_roles: Vec::new(),
mentions: Vec::new(),
pinned: false,
poll: None,
reactions: Vec::new(),
reference: None,
role_subscription_data: None,
Expand Down
1 change: 1 addition & 0 deletions twilight-cache-inmemory/src/event/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ mod tests {
mention_roles: Vec::new(),
mentions: Vec::new(),
pinned: false,
poll: None,
reactions: Vec::new(),
reference: None,
role_subscription_data: None,
Expand Down
2 changes: 2 additions & 0 deletions twilight-cache-inmemory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,8 @@ impl<CacheModels: CacheableModels> UpdateCache<CacheModels> for Event {
| Event::GuildScheduledEventUserRemove(_)
| Event::InviteCreate(_)
| Event::InviteDelete(_)
| Event::MessagePollVoteAdd(_)
| Event::MessagePollVoteRemove(_)
| Event::Resumed
| Event::ThreadMembersUpdate(_)
| Event::ThreadMemberUpdate(_)
Expand Down
4 changes: 4 additions & 0 deletions twilight-cache-inmemory/src/model/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use twilight_model::{
},
Id,
},
poll::Poll,
util::Timestamp,
};

Expand Down Expand Up @@ -114,6 +115,7 @@ pub struct CachedMessage {
pub(crate) mention_roles: Vec<Id<RoleMarker>>,
pub(crate) mentions: Vec<Id<UserMarker>>,
pub(crate) pinned: bool,
pub(crate) poll: Option<Poll>,
pub(crate) reactions: Vec<Reaction>,
reference: Option<MessageReference>,
role_subscription_data: Option<RoleSubscriptionData>,
Expand Down Expand Up @@ -320,6 +322,7 @@ impl From<Message> for CachedMessage {
mention_roles,
mentions,
pinned,
poll,
reactions,
reference,
referenced_message: _,
Expand Down Expand Up @@ -353,6 +356,7 @@ impl From<Message> for CachedMessage {
mention_roles,
mentions: mentions.into_iter().map(|mention| mention.id).collect(),
pinned,
poll,
reactions,
reference,
role_subscription_data,
Expand Down
1 change: 1 addition & 0 deletions twilight-cache-inmemory/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ pub fn cache_with_message_and_reactions() -> DefaultInMemoryCache {
mention_roles: Vec::new(),
mentions: Vec::new(),
pinned: false,
poll: None,
reactions: Vec::new(),
reference: None,
role_subscription_data: None,
Expand Down
12 changes: 12 additions & 0 deletions twilight-gateway/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ bitflags! {
const MESSAGE_DELETE = 1 << 20;
/// Multiple messages have been deleted in a channel.
const MESSAGE_DELETE_BULK = 1 << 21;
/// Message poll vote has been added.
const MESSAGE_POLL_VOTE_ADD = 1 << 28;
/// Message poll vote has been removed.
const MESSAGE_POLL_VOTE_REMOVE = 1 << 29;
/// Message in a channel has been updated.
const MESSAGE_UPDATE = 1 << 22;
/// User's presence details are updated.
Expand Down Expand Up @@ -282,6 +286,12 @@ bitflags! {
| Self::MESSAGE_DELETE_BULK.bits()
| Self::MESSAGE_UPDATE.bits();

/// All [`EventTypeFlags`] in [`Intents::DIRECT_MESSAGE_POLLS`] and [`Intents::GUILD_MESSAGE_POLLS`].
///
/// [`Intents::DIRECT_MESSAGE_POLLS`]: crate::Intents::DIRECT_MESSAGE_POLLS
/// [`Intents::GUILD_MESSAGE_POLLS`]: crate::Intents::GUILD_MESSAGE_POLLS
const MESSAGE_POLLS = Self::MESSAGE_POLL_VOTE_ADD.bits() | Self::MESSAGE_POLL_VOTE_REMOVE.bits();

/// All [`EventTypeFlags`] in [`Intents::GUILD_MESSAGE_REACTIONS`].
///
/// [`Intents::GUILD_MESSAGE_REACTIONS`]: crate::Intents::GUILD_MESSAGE_REACTIONS
Expand Down Expand Up @@ -370,6 +380,8 @@ impl From<EventType> for EventTypeFlags {
EventType::MessageCreate => Self::MESSAGE_CREATE,
EventType::MessageDelete => Self::MESSAGE_DELETE,
EventType::MessageDeleteBulk => Self::MESSAGE_DELETE_BULK,
EventType::MessagePollVoteAdd => Self::MESSAGE_POLL_VOTE_ADD,
EventType::MessagePollVoteRemove => Self::MESSAGE_POLL_VOTE_REMOVE,
EventType::MessageUpdate => Self::MESSAGE_UPDATE,
EventType::PresenceUpdate => Self::PRESENCE_UPDATE,
EventType::ReactionAdd => Self::REACTION_ADD,
Expand Down
2 changes: 2 additions & 0 deletions twilight-http-ratelimiting/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ pub enum Path {
ChannelsIdPins(u64),
/// Operating on a channel's individual pinned message.
ChannelsIdPinsMessageId(u64),
/// Operating on a channel's polls.
ChannelsIdPolls(u64),
/// Operating on a group DM's recipients.
ChannelsIdRecipients(u64),
/// Operating on a thread's members.
Expand Down
56 changes: 56 additions & 0 deletions twilight-http/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ use crate::{
UpdateCurrentMember, UpdateGuild, UpdateGuildChannelPositions, UpdateGuildMfa,
UpdateGuildWelcomeScreen, UpdateGuildWidgetSettings,
},
poll::{EndPoll, GetAnswerVoters},
scheduled_event::{
CreateGuildScheduledEvent, DeleteGuildScheduledEvent, GetGuildScheduledEvent,
GetGuildScheduledEventUsers, GetGuildScheduledEvents, UpdateGuildScheduledEvent,
Expand Down Expand Up @@ -2621,6 +2622,32 @@ impl Client {
CreateTestEntitlement::new(self, application_id, sku_id, owner)
}

/// Ends a poll in a channel.
///
/// # Examples
///
/// ```no_run
/// use twilight_http::Client;
/// use twilight_model::id::Id;
///
/// # #[tokio::main]
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let client = Client::new("my token".to_owned());
///
/// let channel_id = Id::new(1);
/// let message_id = Id::new(2);
///
/// client.end_poll(channel_id, message_id).await?;
/// # Ok(()) }
/// ```
pub const fn end_poll(
&self,
channel_id: Id<ChannelMarker>,
message_id: Id<MessageMarker>,
) -> EndPoll<'_> {
EndPoll::new(self, channel_id, message_id)
}

/// Deletes a currently-active test entitlement. Discord will act as though that user or
/// guild no longer has entitlement to your premium offering.
///
Expand Down Expand Up @@ -2651,6 +2678,35 @@ impl Client {
DeleteTestEntitlement::new(self, application_id, entitlement_id)
}

/// /// Get the voters for an answer in a poll.
///
/// # Examples
///
/// ```no_run
/// use twilight_http::Client;
/// use twilight_model::id::Id;
///
/// # #[tokio::main]
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let client = Client::new("my token".to_owned());
///
/// let channel_id = Id::new(1);
/// let message_id = Id::new(2);
/// let answer_id = 1;
///
/// let voters = client.get_answer_voters(channel_id, message_id, answer_id).await?;
///
/// println!("{:?}", voters);
/// # Ok(()) }
pub const fn get_answer_voters(
&self,
channel_id: Id<ChannelMarker>,
message_id: Id<MessageMarker>,
answer_id: u8,
) -> GetAnswerVoters<'_> {
GetAnswerVoters::new(self, channel_id, message_id, answer_id)
}

/// Returns all SKUs for a given application.
///
/// # Examples
Expand Down
13 changes: 13 additions & 0 deletions twilight-http/src/request/channel/message/create_message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use twilight_model::{
marker::{ChannelMarker, MessageMarker, StickerMarker},
Id,
},
poll::Poll,
};
use twilight_validate::message::{
attachment as validate_attachment, components as validate_components,
Expand Down Expand Up @@ -47,6 +48,8 @@ pub(crate) struct CreateMessageFields<'a> {
#[serde(skip_serializing_if = "Option::is_none")]
payload_json: Option<&'a [u8]>,
#[serde(skip_serializing_if = "Option::is_none")]
poll: Option<&'a Poll>,
#[serde(skip_serializing_if = "Option::is_none")]
sticker_ids: Option<&'a [Id<StickerMarker>]>,
#[serde(skip_serializing_if = "Option::is_none")]
tts: Option<bool>,
Expand Down Expand Up @@ -102,6 +105,7 @@ impl<'a> CreateMessage<'a> {
message_reference: None,
nonce: None,
payload_json: None,
poll: None,
allowed_mentions: None,
sticker_ids: None,
tts: None,
Expand Down Expand Up @@ -222,6 +226,15 @@ impl<'a> CreateMessage<'a> {
self
}

/// Specify if this message is a poll.
pub fn poll(mut self, poll: &'a Poll) -> Self {
if let Ok(fields) = self.fields.as_mut() {
fields.poll = Some(poll);
}

self
}

/// Whether to fail sending if the reply no longer exists.
///
/// Defaults to [`true`].
Expand Down
1 change: 1 addition & 0 deletions twilight-http/src/request/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub mod application;
pub mod attachment;
pub mod channel;
pub mod guild;
pub mod poll;
pub mod scheduled_event;
pub mod sticker;
pub mod template;
Expand Down
68 changes: 68 additions & 0 deletions twilight-http/src/request/poll/end_poll.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use crate::{
client::Client,
error::Error,
request::{Request, TryIntoRequest},
response::{Response, ResponseFuture},
routing::Route,
};
use serde::Serialize;
use std::future::IntoFuture;
use twilight_model::{
channel::Message,
id::{
marker::{ChannelMarker, MessageMarker},
Id,
},
};

#[derive(Serialize)]
struct EndPollFields {
channel_id: Id<ChannelMarker>,
message_id: Id<MessageMarker>,
}

// Ends a poll in a channel.
#[must_use = "requests must be configured and executed"]
pub struct EndPoll<'a> {
fields: EndPollFields,
http: &'a Client,
}

impl<'a> EndPoll<'a> {
pub(crate) const fn new(
http: &'a Client,
channel_id: Id<ChannelMarker>,
message_id: Id<MessageMarker>,
) -> Self {
Self {
fields: EndPollFields {
channel_id,
message_id,
},
http,
}
}
}

impl IntoFuture for EndPoll<'_> {
type Output = Result<Response<Message>, Error>;
type IntoFuture = ResponseFuture<Message>;

fn into_future(self) -> Self::IntoFuture {
let http = self.http;

match self.try_into_request() {
Ok(request) => http.request(request),
Err(source) => ResponseFuture::error(source),
}
}
}

impl TryIntoRequest for EndPoll<'_> {
fn try_into_request(self) -> Result<Request, Error> {
Ok(Request::from_route(&Route::EndPoll {
channel_id: self.fields.channel_id.get(),
message_id: self.fields.message_id.get(),
}))
}
}
Loading

0 comments on commit f660fd8

Please sign in to comment.