diff options
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/context.rs | 86 | ||||
| -rw-r--r-- | src/client/dispatch.rs | 24 | ||||
| -rw-r--r-- | src/client/event_store.rs | 2 | ||||
| -rw-r--r-- | src/client/http.rs | 56 | ||||
| -rw-r--r-- | src/client/mod.rs | 20 | ||||
| -rw-r--r-- | src/client/ratelimiting.rs | 1 |
6 files changed, 187 insertions, 2 deletions
diff --git a/src/client/context.rs b/src/client/context.rs index 6402e9b..2d3d3e4 100644 --- a/src/client/context.rs +++ b/src/client/context.rs @@ -232,6 +232,26 @@ impl Context { http::create_private_channel(map) } + /// React to a [`Message`] with a custom [`Emoji`] or unicode character. + /// + /// **Note**: Requires the [Add Reactions] permission. + /// + /// [`Emoji`]: ../models/struct.Emoji.html + /// [`Message`]: ../models/struct.Message.html + /// [Add Reactions]: ../models/permissions/constant.ADD_REACTIONS.html + pub fn create_reaction<C, M, R>(&self, + channel_id: C, + message_id: M, + reaction_type: R) + -> Result<()> + where C: Into<ChannelId>, + M: Into<MessageId>, + R: Into<ReactionType> { + http::create_reaction(channel_id.into().0, + message_id.into().0, + reaction_type.into()) + } + pub fn create_role<F, G>(&self, guild_id: G, f: F) -> Result<Role> where F: FnOnce(EditRole) -> EditRole, G: Into<GuildId> { let id = guild_id.into().0; @@ -331,6 +351,30 @@ impl Context { http::delete_permission(channel_id.into().0, id) } + + /// Deletes the given [`Reaction`], but only if the current user is the user + /// who made the reaction or has permission to. + /// + /// **Note**: Requires the [`Manage Messages`] permission, _if_ the current + /// user did not perform the reaction. + /// + /// [`Reaction`]: ../models/struct.Reaction.html + /// [Manage Messages]: ../models/permissions/constant.MANAGE_MESSAGES.html + pub fn delete_reaction<C, M, R>(&self, + channel_id: C, + message_id: M, + user_id: Option<UserId>, + reaction_type: R) + -> Result<()> + where C: Into<ChannelId>, + M: Into<MessageId>, + R: Into<ReactionType> { + http::delete_reaction(channel_id.into().0, + message_id.into().0, + user_id.map(|uid| uid.0), + reaction_type.into()) + } + pub fn delete_role<G, R>(&self, guild_id: G, role_id: R) -> Result<()> where G: Into<GuildId>, R: Into<RoleId> { http::delete_role(guild_id.into().0, role_id.into().0) @@ -650,6 +694,48 @@ impl Context { http::get_messages(channel_id.into().0, &query) } + /// Retrieves the list of [`User`]s who have reacted to a [`Message`] with a + /// certain [`Emoji`]. + /// + /// The default `limit` is `50` - specify otherwise to receive a different + /// maximum number of users. The maximum that may be retrieve at a time is + /// `100`, if a greater number is provided then it is automatically reduced. + /// + /// The optional `after` attribute is to retrieve the users after a certain + /// user. This is useful for pagination. + /// + /// **Note**: Requires the [Read Message History] permission. + /// + /// # Errors + /// + /// Returns a [`ClientError::InvalidPermissions`] if the current user does + /// not have the required [permissions]. + /// + /// [`ClientError::InvalidPermissions`]: ../client/enum.ClientError.html#variant.InvalidPermissions + /// [`Emoji`]: struct.Emoji.html + /// [`Message`]: struct.Message.html + /// [`User`]: struct.User.html + /// [Read Message History]: permissions/constant.READ_MESSAGE_HISTORY.html + pub fn get_reaction_users<C, M, R, U>(&self, + channel_id: C, + message_id: M, + reaction_type: R, + limit: Option<u8>, + after: Option<U>) + -> Result<Vec<User>> + where C: Into<ChannelId>, + M: Into<MessageId>, + R: Into<ReactionType>, + U: Into<UserId> { + let limit = limit.map(|x| if x > 100 { 100 } else { x }).unwrap_or(50); + + http::get_reaction_users(channel_id.into().0, + message_id.into().0, + reaction_type.into(), + limit, + after.map(|u| u.into().0)) + } + pub fn get_voice_regions(&self) -> Result<Vec<VoiceRegion>> { http::get_voice_regions() } diff --git a/src/client/dispatch.rs b/src/client/dispatch.rs index 5e206ee..567bc6e 100644 --- a/src/client/dispatch.rs +++ b/src/client/dispatch.rs @@ -488,6 +488,30 @@ pub fn dispatch(event: Result<Event>, }); } }, + Ok(Event::ReactionAdd(event)) => { + if let Some(ref handler) = handler!(on_reaction_add, event_store) { + let context = context(Some(event.reaction.channel_id), + conn, + login_type); + let handler = handler.clone(); + + thread::spawn(move || { + (handler)(context, event.reaction); + }); + } + }, + Ok(Event::ReactionRemove(event)) => { + if let Some(ref handler) = handler!(on_reaction_remove, event_store) { + let context = context(Some(event.reaction.channel_id), + conn, + login_type); + let handler = handler.clone(); + + thread::spawn(move || { + (handler)(context, event.reaction); + }); + } + }, Ok(Event::Ready(event)) => { if let Some(ref handler) = handler!(on_ready, event_store) { update!(update_with_ready, event); diff --git a/src/client/event_store.rs b/src/client/event_store.rs index 4bd8459..0ba5301 100644 --- a/src/client/event_store.rs +++ b/src/client/event_store.rs @@ -55,6 +55,8 @@ pub struct EventStore { pub on_message_ack: Option<Arc<Fn(Context, ChannelId, Option<MessageId>) + Send + Sync + 'static>>, pub on_message_delete: Option<Arc<Fn(Context, ChannelId, MessageId) + Send + Sync + 'static>>, pub on_message_delete_bulk: Option<Arc<Fn(Context, ChannelId, Vec<MessageId>) + Send + Sync + 'static>>, + pub on_reaction_add: Option<Arc<Fn(Context, Reaction) + Send + Sync + 'static>>, + pub on_reaction_remove: Option<Arc<Fn(Context, Reaction) + Send + Sync + 'static>>, pub on_message_update: Option<Arc<Fn(Context, MessageUpdateEvent) + Send + Sync + 'static>>, pub on_note_update: Option<Arc<Fn(Context, UserId, String) + Send + Sync + 'static>>, pub on_presence_replace: Option<Arc<Fn(Context, Vec<Presence>) + Send + Sync + 'static>>, diff --git a/src/client/http.rs b/src/client/http.rs index 3421359..9d29ae6 100644 --- a/src/client/http.rs +++ b/src/client/http.rs @@ -116,8 +116,7 @@ pub fn create_guild(map: Value) -> Result<Guild> { Guild::decode(try!(serde_json::from_reader(response))) } -pub fn create_guild_integration( - guild_id: u64, +pub fn create_guild_integration(guild_id: u64, integration_id: u64, map: Value) -> Result<()> { let body = try!(serde_json::to_string(&map)); @@ -161,6 +160,18 @@ pub fn create_private_channel(map: Value) PrivateChannel::decode(try!(serde_json::from_reader(response))) } +pub fn create_reaction(channel_id: u64, + message_id: u64, + reaction_type: ReactionType) + -> Result<()> { + verify(204, request!(Route::ChannelsIdMessagesIdReactionsUserIdType, + put, + "/channels/{}/messages/{}/reactions/{}/@me", + channel_id, + message_id, + reaction_type.as_data())) +} + pub fn create_role(guild_id: u64) -> Result<Role> { let body = String::from("{}"); let response = request!(Route::GuildsIdRoles, @@ -236,6 +247,22 @@ pub fn delete_permission(channel_id: u64, target_id: u64) target_id)) } +pub fn delete_reaction(channel_id: u64, + message_id: u64, + user_id: Option<u64>, + reaction_type: ReactionType) + -> Result<()> { + let user = user_id.map(|uid| uid.to_string()).unwrap_or("@me".to_string()); + + verify(204, request!(Route::ChannelsIdMessagesIdReactionsUserIdType, + delete, + "/channels/{}/messages/{}/reactions/{}/{}", + channel_id, + message_id, + reaction_type.as_data(), + user)) +} + pub fn delete_role(guild_id: u64, role_id: u64) -> Result<()> { verify(204, request!(Route::GuildsIdRolesId, delete, @@ -508,6 +535,31 @@ pub fn get_pins(channel_id: u64) -> Result<Vec<Message>> { decode_array(try!(serde_json::from_reader(response)), Message::decode) } +pub fn get_reaction_users(channel_id: u64, + message_id: u64, + reaction_type: ReactionType, + limit: u8, + after: Option<u64>) + -> Result<Vec<User>> { + let mut uri = format!("/channels/{}/messages/{}/reactions/{}?limit={}", + channel_id, + message_id, + reaction_type.as_data(), + limit); + + if let Some(user_id) = after { + uri.push_str("&after="); + uri.push_str(&user_id.to_string()); + } + + let response = request!(Route::ChannelsIdMessagesIdReactionsUserIdType, + get, + "{}", + uri); + + decode_array(try!(serde_json::from_reader(response)), User::decode) +} + pub fn get_user(user_id: u64) -> Result<CurrentUser> { let response = request!(Route::UsersId, get, "/users/{}", user_id); diff --git a/src/client/mod.rs b/src/client/mod.rs index 8e291fb..50461c8 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -685,6 +685,26 @@ impl Client { .on_presence_update = Some(Arc::new(handler)); } + /// Attached a handler for when a [`ReactionAdd`] is received. + /// + /// [`ReactionAdd`]: ../model/enum.Event.html#ReactionAdd.v + pub fn on_reaction_add<F>(&mut self, handler: F) + where F: Fn(Context, Reaction) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_reaction_add = Some(Arc::new(handler)) + } + + /// Attached a handler for when a [`ReactionRemove`] is received. + /// + /// [`ReactionRemove`]: ../model/enum.Event.html#ReactionRemove.v + pub fn on_reaction_remove<F>(&mut self, handler: F) + where F: Fn(Context, Reaction) + Send + Sync + 'static { + self.event_store.lock() + .unwrap() + .on_reaction_remove = Some(Arc::new(handler)) + } + /// Register an event to be called whenever a Ready event is received. /// /// Registering a handler for the ready event is good for noting when your diff --git a/src/client/ratelimiting.rs b/src/client/ratelimiting.rs index f5f7cdb..ae886a9 100644 --- a/src/client/ratelimiting.rs +++ b/src/client/ratelimiting.rs @@ -22,6 +22,7 @@ pub enum Route { ChannelsIdMessages, ChannelsIdMessagesBulkDelete, ChannelsIdMessagesId, + ChannelsIdMessagesIdReactionsUserIdType, ChannelsIdPermissionsOverwriteId, ChannelsIdPins, ChannelsIdPinsMessageId, |