github.com/diamondburned/arikawa@v1.3.14/api/message_reaction.go (about) 1 package api 2 3 import ( 4 "net/url" 5 6 "github.com/diamondburned/arikawa/discord" 7 "github.com/diamondburned/arikawa/utils/httputil" 8 ) 9 10 const maxMessageReactionFetchLimit = 100 11 12 // React creates a reaction for the message. 13 // 14 // This endpoint requires the READ_MESSAGE_HISTORY permission to be present on 15 // the current user. Additionally, if nobody else has reacted to the message 16 // using this emoji, this endpoint requires the 'ADD_REACTIONS' permission to 17 // be present on the current user. 18 func (c *Client) React(channelID discord.ChannelID, messageID discord.MessageID, emoji Emoji) error { 19 var msgURL = EndpointChannels + channelID.String() + 20 "/messages/" + messageID.String() + 21 "/reactions/" + url.PathEscape(emoji) + "/@me" 22 return c.FastRequest("PUT", msgURL) 23 } 24 25 // Unreact removes a reaction the current user has made for the message. 26 func (c *Client) Unreact(chID discord.ChannelID, msgID discord.MessageID, emoji Emoji) error { 27 return c.DeleteUserReaction(chID, msgID, 0, emoji) 28 } 29 30 // Reactions returns a list of users that reacted with the passed Emoji. This 31 // method automatically paginates until it reaches the passed limit, or, if the 32 // limit is set to 0, has fetched all users within the passed range. 33 // 34 // As the underlying endpoint has a maximum of 100 users per request, at 35 // maximum a total of limit/100 rounded up requests will be made, although they 36 // may be less, if no more guilds are available. 37 // 38 // When fetching the users, those with the smallest ID will be fetched first. 39 func (c *Client) Reactions( 40 channelID discord.ChannelID, messageID discord.MessageID, emoji Emoji, limit uint) ([]discord.User, error) { 41 42 return c.ReactionsAfter(channelID, messageID, 0, emoji, limit) 43 } 44 45 // ReactionsBefore returns a list of users that reacted with the passed Emoji. 46 // This method automatically paginates until it reaches the passed limit, or, 47 // if the limit is set to 0, has fetched all users with an id smaller than 48 // before. 49 // 50 // As the underlying endpoint has a maximum of 100 users per request, at 51 // maximum a total of limit/100 rounded up requests will be made, although they 52 // may be less, if no more guilds are available. 53 func (c *Client) ReactionsBefore( 54 channelID discord.ChannelID, messageID discord.MessageID, before discord.UserID, emoji Emoji, 55 limit uint) ([]discord.User, error) { 56 57 users := make([]discord.User, 0, limit) 58 59 fetch := uint(maxMessageReactionFetchLimit) 60 61 unlimited := limit == 0 62 63 for limit > 0 || unlimited { 64 // Only fetch as much as we need. Since limit gradually decreases, 65 // we only need to fetch min(fetch, limit). 66 if limit > 0 { 67 if fetch > limit { 68 fetch = limit 69 } 70 limit -= fetch 71 } 72 73 r, err := c.reactionsRange(channelID, messageID, before, 0, emoji, fetch) 74 if err != nil { 75 return users, err 76 } 77 users = append(r, users...) 78 79 if len(r) < maxMessageReactionFetchLimit { 80 break 81 } 82 83 before = r[0].ID 84 } 85 86 if len(users) == 0 { 87 return nil, nil 88 } 89 90 return users, nil 91 } 92 93 // ReactionsAfter returns a list of users that reacted with the passed Emoji. 94 // This method automatically paginates until it reaches the passed limit, or, 95 // if the limit is set to 0, has fetched all users with an id higher than 96 // after. 97 // 98 // As the underlying endpoint has a maximum of 100 users per request, at 99 // maximum a total of limit/100 rounded up requests will be made, although they 100 // may be less, if no more guilds are available. 101 func (c *Client) ReactionsAfter( 102 channelID discord.ChannelID, messageID discord.MessageID, after discord.UserID, emoji Emoji, 103 limit uint) ([]discord.User, error) { 104 105 users := make([]discord.User, 0, limit) 106 107 fetch := uint(maxMessageReactionFetchLimit) 108 109 unlimited := limit == 0 110 111 for limit > 0 || unlimited { 112 // Only fetch as much as we need. Since limit gradually decreases, 113 // we only need to fetch min(fetch, limit). 114 if limit > 0 { 115 if fetch > limit { 116 fetch = limit 117 } 118 limit -= fetch 119 } 120 121 r, err := c.reactionsRange(channelID, messageID, 0, after, emoji, fetch) 122 if err != nil { 123 return users, err 124 } 125 users = append(users, r...) 126 127 if len(r) < maxMessageReactionFetchLimit { 128 break 129 } 130 131 after = r[len(r)-1].ID 132 } 133 134 if len(users) == 0 { 135 return nil, nil 136 } 137 138 return users, nil 139 } 140 141 // reactionsRange get users before and after IDs. Before, after, and limit are 142 // optional. A maximum limit of only 100 reactions could be returned. 143 func (c *Client) reactionsRange( 144 channelID discord.ChannelID, messageID discord.MessageID, before, after discord.UserID, emoji Emoji, 145 limit uint) ([]discord.User, error) { 146 147 switch { 148 case limit == 0: 149 limit = 25 150 case limit > 100: 151 limit = 100 152 } 153 154 var param struct { 155 Before discord.UserID `schema:"before,omitempty"` 156 After discord.UserID `schema:"after,omitempty"` 157 158 Limit uint `schema:"limit"` 159 } 160 161 param.Before = before 162 param.After = after 163 param.Limit = limit 164 165 var users []discord.User 166 return users, c.RequestJSON( 167 &users, "GET", EndpointChannels+channelID.String()+ 168 "/messages/"+messageID.String()+ 169 "/reactions/"+url.PathEscape(emoji), 170 httputil.WithSchema(c, param), 171 ) 172 } 173 174 // DeleteReaction deletes another user's reaction. 175 // 176 // This endpoint requires the MANAGE_MESSAGES permission to be present on the 177 // current user. 178 func (c *Client) DeleteUserReaction( 179 channelID discord.ChannelID, messageID discord.MessageID, userID discord.UserID, emoji Emoji) error { 180 181 var user = "@me" 182 if userID > 0 { 183 user = userID.String() 184 } 185 186 return c.FastRequest( 187 "DELETE", 188 EndpointChannels+channelID.String()+"/messages/"+messageID.String()+ 189 "/reactions/"+url.PathEscape(emoji)+"/"+user, 190 ) 191 } 192 193 // DeleteReactions deletes all the reactions for a given emoji on a message. 194 // 195 // This endpoint requires the MANAGE_MESSAGES permission to be present on the 196 // current user. 197 // Fires a Message Reaction Remove Emoji Gateway event. 198 func (c *Client) DeleteReactions( 199 channelID discord.ChannelID, messageID discord.MessageID, emoji Emoji) error { 200 201 return c.FastRequest( 202 "DELETE", 203 EndpointChannels+channelID.String()+"/messages/"+messageID.String()+ 204 "/reactions/"+url.PathEscape(emoji), 205 ) 206 } 207 208 // DeleteAllReactions deletes all reactions on a message. 209 // 210 // This endpoint requires the MANAGE_MESSAGES permission to be present on the 211 // current user. 212 // Fires a Message Reaction Remove All Gateway event. 213 func (c *Client) DeleteAllReactions(channelID discord.ChannelID, messageID discord.MessageID) error { 214 return c.FastRequest( 215 "DELETE", 216 EndpointChannels+channelID.String()+"/messages/"+messageID.String()+"/reactions/", 217 ) 218 }