1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2024-10-31 20:14:21 +00:00
arikawa/api/message.go

313 lines
9.6 KiB
Go
Raw Normal View History

2020-01-02 05:39:52 +00:00
package api
import (
"github.com/pkg/errors"
"github.com/diamondburned/arikawa/discord"
"github.com/diamondburned/arikawa/utils/httputil"
2020-05-11 22:06:19 +00:00
"github.com/diamondburned/arikawa/utils/json/option"
2020-01-02 05:39:52 +00:00
)
2020-05-16 23:35:57 +00:00
// Messages returns a list of messages sent in the channel with the passed ID.
// This method automatically paginates until it reaches the passed limit, or,
// if the limit is set to 0, has fetched all guilds within the passed ange.
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 messages per request, at
// maximum a total of limit/100 rounded up requests will be made, although they
// may be less, if no more messages are available.
//
// When fetching the messages, those with the smallest ID will be fetched
// first.
func (c *Client) Messages(channelID discord.Snowflake, limit uint) ([]discord.Message, error) {
return c.MessagesAfter(channelID, 0, limit)
}
// MessagesAround returns messages around the ID, with a limit of 100.
func (c *Client) MessagesAround(
channelID, around discord.Snowflake, limit uint) ([]discord.Message, error) {
return c.messagesRange(channelID, 0, 0, around, limit)
}
// MessagesBefore returns a list messages sent in the channel with the passed
// ID. This method automatically paginates until it reaches the passed limit,
// or, if the limit is set to 0, has fetched all guilds within the passed
// range.
//
// As the underlying endpoint has a maximum of 100 messages per request, at
// maximum a total of limit/100 rounded up requests will be made, although they
// may be less, if no more messages are available.
func (c *Client) MessagesBefore(
channelID, before discord.Snowflake, limit uint) ([]discord.Message, error) {
2020-01-06 05:22:26 +00:00
var msgs []discord.Message
2020-05-16 23:35:57 +00:00
// this is the limit of max messages per request, as imposed by Discord
const hardLimit int = 100
2020-05-16 23:35:57 +00:00
unlimited := limit == 0
2020-05-11 22:06:19 +00:00
2020-05-16 23:35:57 +00:00
for fetch := uint(hardLimit); limit > 0 || unlimited; fetch = uint(hardLimit) {
if limit > 0 {
if fetch > limit {
fetch = limit
2020-01-18 19:34:08 +00:00
}
2020-05-16 23:35:57 +00:00
limit -= fetch
}
2020-05-16 23:35:57 +00:00
m, err := c.messagesRange(channelID, before, 0, 0, fetch)
2020-01-06 05:22:26 +00:00
if err != nil {
return msgs, err
}
2020-05-16 23:35:57 +00:00
msgs = append(m, msgs...)
2020-01-06 05:22:26 +00:00
if len(m) < hardLimit {
2020-01-06 05:22:26 +00:00
break
}
before = m[0].ID
2020-01-06 05:22:26 +00:00
}
2020-01-02 05:39:52 +00:00
2020-01-06 05:22:26 +00:00
return msgs, nil
2020-01-02 05:39:52 +00:00
}
2020-05-16 23:35:57 +00:00
// MessagesAfter returns a list messages sent in the channel with the passed
// ID. This method automatically paginates until it reaches the passed limit,
// or, if the limit is set to 0, has fetched all guilds within the passed
// range.
//
// As the underlying endpoint has a maximum of 100 messages per request, at
// maximum a total of limit/100 rounded up requests will be made, although they
// may be less, if no more messages are available.
func (c *Client) MessagesAfter(
channelID, after discord.Snowflake, limit uint) ([]discord.Message, error) {
2020-01-02 05:39:52 +00:00
2020-05-16 23:35:57 +00:00
var msgs []discord.Message
2020-01-02 05:39:52 +00:00
2020-05-16 23:35:57 +00:00
// this is the limit of max messages per request, as imposed by Discord
const hardLimit int = 100
2020-01-02 05:39:52 +00:00
2020-05-16 23:35:57 +00:00
unlimited := limit == 0
2020-01-02 05:39:52 +00:00
2020-05-16 23:35:57 +00:00
for fetch := uint(hardLimit); limit > 0 || unlimited; fetch = uint(hardLimit) {
if limit > 0 {
if fetch > limit {
fetch = limit
}
limit -= fetch
}
2020-01-02 05:39:52 +00:00
2020-05-16 23:35:57 +00:00
m, err := c.messagesRange(channelID, 0, after, 0, fetch)
if err != nil {
return msgs, err
}
msgs = append(msgs, m...)
if len(m) < hardLimit {
break
}
after = m[len(m)-1].ID
2020-05-16 23:35:57 +00:00
}
return msgs, nil
2020-01-02 05:39:52 +00:00
}
func (c *Client) messagesRange(
2020-05-16 23:35:57 +00:00
channelID, before, after, around discord.Snowflake, limit uint) ([]discord.Message, error) {
2020-01-02 05:39:52 +00:00
switch {
case limit == 0:
limit = 50
case limit > 100:
limit = 100
}
2020-01-06 05:22:26 +00:00
var param struct {
Before discord.Snowflake `schema:"before,omitempty"`
After discord.Snowflake `schema:"after,omitempty"`
Around discord.Snowflake `schema:"around,omitempty"`
Limit uint `schema:"limit"`
}
2020-01-02 05:39:52 +00:00
2020-01-16 04:27:57 +00:00
param.Before = before
param.After = after
param.Around = around
param.Limit = limit
var msgs []discord.Message
return msgs, c.RequestJSON(
&msgs, "GET",
EndpointChannels+channelID.String()+"/messages",
httputil.WithSchema(c, param),
)
2020-01-02 05:39:52 +00:00
}
2020-05-11 22:06:19 +00:00
// Message returns a specific message in the channel.
//
// If operating on a guild channel, this endpoint requires the
// READ_MESSAGE_HISTORY permission to be present on the current user.
func (c *Client) Message(channelID, messageID discord.Snowflake) (*discord.Message, error) {
var msg *discord.Message
2020-01-02 05:39:52 +00:00
return msg, c.RequestJSON(&msg, "GET",
EndpointChannels+channelID.String()+"/messages/"+messageID.String())
}
2020-05-12 03:21:48 +00:00
// SendText posts a only-text message to a guild text or DM channel.
//
// If operating on a guild channel, this endpoint requires the SEND_MESSAGES
// permission to be present on the current user.
//
// Fires a Message Create Gateway event.
func (c *Client) SendText(channelID discord.Snowflake, content string) (*discord.Message, error) {
return c.SendMessageComplex(channelID, SendMessageData{
Content: content,
})
}
// SendEmbed posts an Embed to a guild text or DM channel.
//
// If operating on a guild channel, this endpoint requires the SEND_MESSAGES
// permission to be present on the current user.
//
// Fires a Message Create Gateway event.
func (c *Client) SendEmbed(
channelID discord.Snowflake, e discord.Embed) (*discord.Message, error) {
return c.SendMessageComplex(channelID, SendMessageData{
Embed: &e,
})
}
2020-05-11 22:06:19 +00:00
// SendMessage posts a message to a guild text or DM channel.
//
// If operating on a guild channel, this endpoint requires the SEND_MESSAGES
// permission to be present on the current user.
//
// Fires a Message Create Gateway event.
func (c *Client) SendMessage(
2020-05-11 22:06:19 +00:00
channelID discord.Snowflake, content string, embed *discord.Embed) (*discord.Message, error) {
2020-01-02 05:39:52 +00:00
return c.SendMessageComplex(channelID, SendMessageData{
Content: content,
Embed: embed,
})
}
2020-05-11 22:06:19 +00:00
// https://discord.com/developers/docs/resources/channel#edit-message-json-params
type EditMessageData struct {
// Content is the new message contents (up to 2000 characters).
Content option.NullableString `json:"content,omitempty"`
// Embed contains embedded rich content.
2020-05-15 17:14:37 +00:00
Embed *discord.Embed `json:"embed,omitempty"`
// AllowedMentions are the allowed mentions for a message.
2020-05-11 22:06:19 +00:00
AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"`
// Flags edits the flags of a message (only SUPPRESS_EMBEDS can currently
// be set/unset)
//
// This field is nullable.
Flags *discord.MessageFlags `json:"flags,omitempty"`
}
2020-01-02 05:39:52 +00:00
2020-05-15 17:17:52 +00:00
// EditText edits the contents of a previously sent message. For more
// documentation, refer to EditMessageComplex.
func (c *Client) EditText(
channelID, messageID discord.Snowflake, content string) (*discord.Message, error) {
return c.EditMessageComplex(channelID, messageID, EditMessageData{
Content: option.NewNullableString(content),
})
}
// EditEmbed edits the embed of a previously sent message. For more
// documentation, refer to EditMessageComplex.
func (c *Client) EditEmbed(
channelID, messageID discord.Snowflake, embed discord.Embed) (*discord.Message, error) {
return c.EditMessageComplex(channelID, messageID, EditMessageData{
Embed: &embed,
})
}
2020-05-15 17:14:37 +00:00
// EditMessage edits a previously sent message. For more documentation, refer to
// EditMessageComplex.
func (c *Client) EditMessage(
channelID, messageID discord.Snowflake, content string,
embed *discord.Embed, suppressEmbeds bool) (*discord.Message, error) {
var data = EditMessageData{
Content: option.NewNullableString(content),
Embed: embed,
}
if suppressEmbeds {
data.Flags = &discord.SuppressEmbeds
}
return c.EditMessageComplex(channelID, messageID, data)
}
// EditMessageComplex edits a previously sent message. The fields Content,
// Embed, AllowedMentions and Flags can be edited by the original message
// author. Other users can only edit flags and only if they have the
// MANAGE_MESSAGES permission in the corresponding channel. When specifying
// flags, ensure to include all previously set flags/bits in addition to ones
// that you are modifying. Only flags documented in EditMessageData may be
// modified by users (unsupported flag changes are currently ignored without
// error).
2020-05-11 22:06:19 +00:00
//
// Fires a Message Update Gateway event.
func (c *Client) EditMessageComplex(
2020-05-11 22:06:19 +00:00
channelID, messageID discord.Snowflake, data EditMessageData) (*discord.Message, error) {
2020-01-02 05:39:52 +00:00
if data.AllowedMentions != nil {
if err := data.AllowedMentions.Verify(); err != nil {
return nil, errors.Wrap(err, "allowedMentions error")
}
}
if data.Embed != nil {
if err := data.Embed.Validate(); err != nil {
return nil, errors.Wrap(err, "embed error")
}
}
var msg *discord.Message
2020-01-02 05:39:52 +00:00
return msg, c.RequestJSON(
&msg, "PATCH",
EndpointChannels+channelID.String()+"/messages/"+messageID.String(),
2020-05-11 22:06:19 +00:00
httputil.WithJSONBody(data),
2020-01-02 05:39:52 +00:00
)
}
2020-05-11 22:06:19 +00:00
// DeleteMessage delete a message. If operating on a guild channel and trying
// to delete a message that was not sent by the current user, this endpoint
// requires the MANAGE_MESSAGES permission.
2020-01-02 05:39:52 +00:00
func (c *Client) DeleteMessage(channelID, messageID discord.Snowflake) error {
return c.FastRequest("DELETE", EndpointChannels+channelID.String()+
"/messages/"+messageID.String())
}
2020-05-11 22:06:19 +00:00
// DeleteMessages deletes multiple messages in a single request. This endpoint
// can only be used on guild channels and requires the MANAGE_MESSAGES
// permission. This endpoint only works for bots.
//
// This endpoint will not delete messages older than 2 weeks, and will fail if
// any message provided is older than that or if any duplicate message IDs are
// provided.
//
// Fires a Message Delete Bulk Gateway event.
func (c *Client) DeleteMessages(channelID discord.Snowflake, messageIDs []discord.Snowflake) error {
2020-01-02 05:39:52 +00:00
var param struct {
Messages []discord.Snowflake `json:"messages"`
}
param.Messages = messageIDs
2020-05-12 02:05:08 +00:00
return c.FastRequest(
"POST",
EndpointChannels+channelID.String()+"/messages/bulk-delete",
httputil.WithJSONBody(param),
)
2020-01-02 05:39:52 +00:00
}