2020-01-02 05:39:52 +00:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
2020-05-11 19:03:33 +00:00
|
|
|
"net/url"
|
|
|
|
|
2020-10-28 22:39:59 +00:00
|
|
|
"github.com/diamondburned/arikawa/v2/discord"
|
|
|
|
"github.com/diamondburned/arikawa/v2/utils/httputil"
|
2020-01-02 05:39:52 +00:00
|
|
|
)
|
|
|
|
|
2020-10-19 14:47:43 +00:00
|
|
|
const maxMessageReactionFetchLimit = 100
|
|
|
|
|
2020-05-11 22:06:19 +00:00
|
|
|
// React creates a reaction for the message.
|
|
|
|
//
|
|
|
|
// This endpoint requires the READ_MESSAGE_HISTORY permission to be present on
|
|
|
|
// the current user. Additionally, if nobody else has reacted to the message
|
|
|
|
// using this emoji, this endpoint requires the 'ADD_REACTIONS' permission to
|
|
|
|
// be present on the current user.
|
2020-07-21 20:27:59 +00:00
|
|
|
func (c *Client) React(channelID discord.ChannelID, messageID discord.MessageID, emoji Emoji) error {
|
2020-01-06 05:32:25 +00:00
|
|
|
var msgURL = EndpointChannels + channelID.String() +
|
|
|
|
"/messages/" + messageID.String() +
|
2020-05-11 19:03:33 +00:00
|
|
|
"/reactions/" + url.PathEscape(emoji) + "/@me"
|
2020-01-02 05:39:52 +00:00
|
|
|
return c.FastRequest("PUT", msgURL)
|
|
|
|
}
|
|
|
|
|
2020-05-11 22:06:19 +00:00
|
|
|
// Unreact removes a reaction the current user has made for the message.
|
2020-07-21 20:27:59 +00:00
|
|
|
func (c *Client) Unreact(chID discord.ChannelID, msgID discord.MessageID, emoji Emoji) error {
|
2020-01-23 05:13:53 +00:00
|
|
|
return c.DeleteUserReaction(chID, msgID, 0, emoji)
|
|
|
|
}
|
|
|
|
|
2020-05-16 23:35:57 +00:00
|
|
|
// Reactions returns a list of users that reacted with the passed Emoji. This
|
|
|
|
// method automatically paginates until it reaches the passed limit, or, if the
|
|
|
|
// limit is set to 0, has fetched all users within the passed range.
|
2020-05-11 22:06:19 +00:00
|
|
|
//
|
2020-05-16 23:35:57 +00:00
|
|
|
// As the underlying endpoint has a maximum of 100 users per request, at
|
|
|
|
// maximum a total of limit/100 rounded up requests will be made, although they
|
|
|
|
// may be less, if no more guilds are available.
|
|
|
|
//
|
|
|
|
// When fetching the users, those with the smallest ID will be fetched first.
|
2020-01-06 05:32:25 +00:00
|
|
|
func (c *Client) Reactions(
|
2020-07-21 20:27:59 +00:00
|
|
|
channelID discord.ChannelID, messageID discord.MessageID, emoji Emoji, limit uint) ([]discord.User, error) {
|
2020-05-16 23:35:57 +00:00
|
|
|
|
2020-05-23 02:18:00 +00:00
|
|
|
return c.ReactionsAfter(channelID, messageID, 0, emoji, limit)
|
2020-05-16 23:35:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ReactionsBefore returns a list of users that reacted with the passed Emoji.
|
|
|
|
// This method automatically paginates until it reaches the passed limit, or,
|
2020-10-19 14:47:43 +00:00
|
|
|
// if the limit is set to 0, has fetched all users with an id smaller than
|
|
|
|
// before.
|
2020-05-16 23:35:57 +00:00
|
|
|
//
|
|
|
|
// As the underlying endpoint has a maximum of 100 users per request, at
|
|
|
|
// maximum a total of limit/100 rounded up requests will be made, although they
|
|
|
|
// may be less, if no more guilds are available.
|
|
|
|
func (c *Client) ReactionsBefore(
|
2020-07-21 20:27:59 +00:00
|
|
|
channelID discord.ChannelID, messageID discord.MessageID, before discord.UserID, emoji Emoji,
|
2020-05-23 02:18:00 +00:00
|
|
|
limit uint) ([]discord.User, error) {
|
2020-01-02 05:39:52 +00:00
|
|
|
|
2020-10-19 14:47:43 +00:00
|
|
|
users := make([]discord.User, 0, limit)
|
2020-01-06 05:22:26 +00:00
|
|
|
|
2020-10-19 14:47:43 +00:00
|
|
|
fetch := uint(maxMessageReactionFetchLimit)
|
2020-01-07 06:45:29 +00:00
|
|
|
|
2020-05-16 23:35:57 +00:00
|
|
|
unlimited := limit == 0
|
|
|
|
|
2020-10-19 14:47:43 +00:00
|
|
|
for limit > 0 || unlimited {
|
2020-05-16 23:35:57 +00:00
|
|
|
if limit > 0 {
|
2020-11-10 23:34:05 +00:00
|
|
|
// Only fetch as much as we need. Since limit gradually decreases,
|
|
|
|
// we only need to fetch min(fetch, limit).
|
2020-11-21 14:53:57 +00:00
|
|
|
fetch = uint(min(maxMessageReactionFetchLimit, int(limit)))
|
2020-05-16 23:35:57 +00:00
|
|
|
limit -= fetch
|
2020-01-07 06:45:29 +00:00
|
|
|
}
|
|
|
|
|
2020-05-23 02:18:00 +00:00
|
|
|
r, err := c.reactionsRange(channelID, messageID, before, 0, emoji, fetch)
|
2020-01-06 05:22:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return users, err
|
|
|
|
}
|
2020-05-23 00:08:36 +00:00
|
|
|
users = append(r, users...)
|
2020-01-06 05:22:26 +00:00
|
|
|
|
2020-10-19 14:47:43 +00:00
|
|
|
if len(r) < maxMessageReactionFetchLimit {
|
2020-01-06 05:22:26 +00:00
|
|
|
break
|
|
|
|
}
|
|
|
|
|
2020-05-16 23:35:57 +00:00
|
|
|
before = r[0].ID
|
2020-01-06 05:22:26 +00:00
|
|
|
}
|
|
|
|
|
2020-10-19 14:47:43 +00:00
|
|
|
if len(users) == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2020-01-06 05:22:26 +00:00
|
|
|
return users, nil
|
|
|
|
}
|
|
|
|
|
2020-05-16 23:35:57 +00:00
|
|
|
// ReactionsAfter returns a list of users that reacted with the passed Emoji.
|
|
|
|
// This method automatically paginates until it reaches the passed limit, or,
|
2020-10-19 14:47:43 +00:00
|
|
|
// if the limit is set to 0, has fetched all users with an id higher than
|
|
|
|
// after.
|
2020-05-16 23:35:57 +00:00
|
|
|
//
|
|
|
|
// As the underlying endpoint has a maximum of 100 users per request, at
|
|
|
|
// maximum a total of limit/100 rounded up requests will be made, although they
|
|
|
|
// may be less, if no more guilds are available.
|
|
|
|
func (c *Client) ReactionsAfter(
|
2020-07-21 20:27:59 +00:00
|
|
|
channelID discord.ChannelID, messageID discord.MessageID, after discord.UserID, emoji Emoji,
|
2020-05-23 02:18:00 +00:00
|
|
|
limit uint) ([]discord.User, error) {
|
2020-01-06 05:22:26 +00:00
|
|
|
|
2020-10-19 14:47:43 +00:00
|
|
|
users := make([]discord.User, 0, limit)
|
2020-01-06 05:22:26 +00:00
|
|
|
|
2020-10-19 14:47:43 +00:00
|
|
|
fetch := uint(maxMessageReactionFetchLimit)
|
2020-05-16 23:35:57 +00:00
|
|
|
|
|
|
|
unlimited := limit == 0
|
|
|
|
|
2020-10-19 14:47:43 +00:00
|
|
|
for limit > 0 || unlimited {
|
2020-05-16 23:35:57 +00:00
|
|
|
if limit > 0 {
|
2020-11-10 23:34:05 +00:00
|
|
|
// Only fetch as much as we need. Since limit gradually decreases,
|
|
|
|
// we only need to fetch min(fetch, limit).
|
2020-11-21 14:53:57 +00:00
|
|
|
fetch = uint(min(maxMessageReactionFetchLimit, int(limit)))
|
2020-05-16 23:35:57 +00:00
|
|
|
limit -= fetch
|
|
|
|
}
|
|
|
|
|
2020-05-23 02:18:00 +00:00
|
|
|
r, err := c.reactionsRange(channelID, messageID, 0, after, emoji, fetch)
|
2020-05-16 23:35:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return users, err
|
|
|
|
}
|
|
|
|
users = append(users, r...)
|
|
|
|
|
2020-10-19 14:47:43 +00:00
|
|
|
if len(r) < maxMessageReactionFetchLimit {
|
2020-05-16 23:35:57 +00:00
|
|
|
break
|
|
|
|
}
|
2020-01-06 05:22:26 +00:00
|
|
|
|
2020-05-22 22:59:27 +00:00
|
|
|
after = r[len(r)-1].ID
|
2020-05-16 23:35:57 +00:00
|
|
|
}
|
|
|
|
|
2020-10-19 14:47:43 +00:00
|
|
|
if len(users) == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2020-05-16 23:35:57 +00:00
|
|
|
return users, nil
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
2020-05-16 23:35:57 +00:00
|
|
|
// reactionsRange get users before and after IDs. Before, after, and limit are
|
2020-01-06 05:22:26 +00:00
|
|
|
// optional. A maximum limit of only 100 reactions could be returned.
|
2020-05-16 23:35:57 +00:00
|
|
|
func (c *Client) reactionsRange(
|
2020-07-21 20:27:59 +00:00
|
|
|
channelID discord.ChannelID, messageID discord.MessageID, before, after discord.UserID, emoji Emoji,
|
2020-05-23 02:18:00 +00:00
|
|
|
limit uint) ([]discord.User, error) {
|
2020-01-02 05:39:52 +00:00
|
|
|
|
2020-05-11 22:06:19 +00:00
|
|
|
switch {
|
|
|
|
case limit == 0:
|
2020-01-02 05:39:52 +00:00
|
|
|
limit = 25
|
2020-05-11 22:06:19 +00:00
|
|
|
case limit > 100:
|
2020-01-02 05:39:52 +00:00
|
|
|
limit = 100
|
|
|
|
}
|
|
|
|
|
2020-01-06 03:48:39 +00:00
|
|
|
var param struct {
|
2020-07-21 20:27:59 +00:00
|
|
|
Before discord.UserID `schema:"before,omitempty"`
|
|
|
|
After discord.UserID `schema:"after,omitempty"`
|
2020-01-02 05:39:52 +00:00
|
|
|
|
2020-01-06 03:48:39 +00:00
|
|
|
Limit uint `schema:"limit"`
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
2020-01-06 03:48:39 +00:00
|
|
|
param.Before = before
|
|
|
|
param.After = after
|
|
|
|
param.Limit = limit
|
|
|
|
|
2020-01-02 19:53:08 +00:00
|
|
|
var users []discord.User
|
2020-01-06 05:22:26 +00:00
|
|
|
return users, c.RequestJSON(
|
2020-01-06 05:26:20 +00:00
|
|
|
&users, "GET", EndpointChannels+channelID.String()+
|
|
|
|
"/messages/"+messageID.String()+
|
2020-05-11 19:03:33 +00:00
|
|
|
"/reactions/"+url.PathEscape(emoji),
|
2020-01-06 05:22:26 +00:00
|
|
|
httputil.WithSchema(c, param),
|
|
|
|
)
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 22:06:19 +00:00
|
|
|
// DeleteReaction deletes another user's reaction.
|
|
|
|
//
|
|
|
|
// This endpoint requires the MANAGE_MESSAGES permission to be present on the
|
|
|
|
// current user.
|
2020-01-23 05:13:53 +00:00
|
|
|
func (c *Client) DeleteUserReaction(
|
2020-07-21 20:27:59 +00:00
|
|
|
channelID discord.ChannelID, messageID discord.MessageID, userID discord.UserID, emoji Emoji) error {
|
2020-01-02 05:39:52 +00:00
|
|
|
|
|
|
|
var user = "@me"
|
|
|
|
if userID > 0 {
|
|
|
|
user = userID.String()
|
|
|
|
}
|
|
|
|
|
2020-05-12 02:05:08 +00:00
|
|
|
return c.FastRequest(
|
|
|
|
"DELETE",
|
|
|
|
EndpointChannels+channelID.String()+"/messages/"+messageID.String()+
|
|
|
|
"/reactions/"+url.PathEscape(emoji)+"/"+user,
|
|
|
|
)
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 22:06:19 +00:00
|
|
|
// DeleteReactions deletes all the reactions for a given emoji on a message.
|
|
|
|
//
|
|
|
|
// This endpoint requires the MANAGE_MESSAGES permission to be present on the
|
|
|
|
// current user.
|
|
|
|
// Fires a Message Reaction Remove Emoji Gateway event.
|
2020-01-23 05:13:53 +00:00
|
|
|
func (c *Client) DeleteReactions(
|
2020-07-21 20:27:59 +00:00
|
|
|
channelID discord.ChannelID, messageID discord.MessageID, emoji Emoji) error {
|
2020-01-02 05:39:52 +00:00
|
|
|
|
2020-05-12 01:57:35 +00:00
|
|
|
return c.FastRequest(
|
2020-05-12 02:05:08 +00:00
|
|
|
"DELETE",
|
2020-05-23 02:18:00 +00:00
|
|
|
EndpointChannels+channelID.String()+"/messages/"+messageID.String()+
|
2020-05-12 02:05:08 +00:00
|
|
|
"/reactions/"+url.PathEscape(emoji),
|
|
|
|
)
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|
|
|
|
|
2020-05-11 22:06:19 +00:00
|
|
|
// DeleteAllReactions deletes all reactions on a message.
|
|
|
|
//
|
|
|
|
// This endpoint requires the MANAGE_MESSAGES permission to be present on the
|
|
|
|
// current user.
|
|
|
|
// Fires a Message Reaction Remove All Gateway event.
|
2020-07-21 20:27:59 +00:00
|
|
|
func (c *Client) DeleteAllReactions(channelID discord.ChannelID, messageID discord.MessageID) error {
|
2020-05-12 02:05:08 +00:00
|
|
|
return c.FastRequest(
|
|
|
|
"DELETE",
|
2020-11-15 00:32:16 +00:00
|
|
|
EndpointChannels+channelID.String()+"/messages/"+messageID.String()+"/reactions",
|
2020-05-12 02:05:08 +00:00
|
|
|
)
|
2020-01-02 05:39:52 +00:00
|
|
|
}
|