aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
Diffstat (limited to 'src/client')
-rw-r--r--src/client/context.rs86
-rw-r--r--src/client/dispatch.rs24
-rw-r--r--src/client/event_store.rs2
-rw-r--r--src/client/http.rs56
-rw-r--r--src/client/mod.rs20
-rw-r--r--src/client/ratelimiting.rs1
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,