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