1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2024-09-30 06:01:17 +00:00
arikawa/api/message.go

302 lines
7.5 KiB
Go
Raw Normal View History

2020-01-02 05:39:52 +00:00
package api
import (
"io"
"git.sr.ht/~diamondburned/arikawa/discord"
"git.sr.ht/~diamondburned/arikawa/httputil"
"github.com/pkg/errors"
)
type Message struct {
ID discord.Snowflake `json:"id"`
Type MessageType `json:"type"`
ChannelID discord.Snowflake `json:"channel_id"`
GuildID discord.Snowflake `json:"guild_id,omitempty"`
// The author object follows the structure of the user object, but is only
// a valid user in the case where the message is generated by a user or bot
// user. If the message is generated by a webhook, the author object
// corresponds to the webhook's id, username, and avatar. You can tell if a
// message is generated by a webhook by checking for the webhook_id on the
// message object.
Author User `json:"author"`
// The member object exists in MESSAGE_CREATE and MESSAGE_UPDATE
// events from text-based guild channels.
Member *GuildMember `json:"member,omitempty"`
Content string `json:"content"`
Timestamp discord.Timestamp `json:"timestamp,omitempty"`
EditedTimestamp *discord.Timestamp `json:"edited_timestamp,omitempty"`
TTS bool `json:"tts"`
Pinned bool `json:"pinned"`
// The user objects in the mentions array will only have the partial
// member field present in MESSAGE_CREATE and MESSAGE_UPDATE events from
// text-based guild channels.
Mentions []GuildUser `json:"mentions"`
MentionRoleIDs []discord.Snowflake `json:"mention_roles"`
MentionEveryone bool `json:"mention_everyone"`
// Not all channel mentions in a message will appear in mention_channels.
MentionChannels []ChannelMention `json:"mention_channels,omitempty"`
Attachments []Attachment `json:"attachments"`
Embeds []Embed `json:"embeds"`
Reactions []Reaction `json:"reaction,omitempty"`
// Used for validating a message was sent
Nonce string `json:"nonce,omitempty"`
WebhookID discord.Snowflake `json:"webhook_id,omitempty"`
Activity *MessageActivity `json:"activity,omitempty"`
Application *MessageApplication `json:"application,omitempty"`
Reference *MessageReference `json:"message_reference,omitempty"`
Flags MessageFlags `json:"flags"`
}
type MessageType uint8
const (
DefaultMessage MessageType = iota
RecipientAddMessage
RecipientRemoveMessage
CallMessage
ChannelNameChangeMessage
ChannelIconChangeMessage
ChannelPinnedMessage
GuildMemberJoinMessage
NitroBoostMessage
NitroTier1Message
NitroTier2Message
NitroTier3Message
ChannelFollowAddMessage
)
type MessageFlags uint8
const (
CrosspostedMessage MessageFlags = 1 << iota
MessageIsCrosspost
SuppressEmbeds
SourceMessageDeleted
UrgentMessage
)
type ChannelMention struct {
ChannelID discord.Snowflake `json:"id"`
GuildID discord.Snowflake `json:"guild_id"`
ChannelType ChannelType `json:"type"`
ChannelName string `json:"name"`
}
type GuildUser struct {
User
Member *GuildMember `json:"member,omitempty"`
}
//
type MessageActivity struct {
Type MessageActivityType `json:"type"`
// From a Rich Presence event
PartyID string `json:"party_id,omitempty"`
}
type MessageActivityType uint8
const (
JoinMessage MessageActivityType = iota + 1
SpectateMessage
ListenMessage
JoinRequestMessage
)
//
type MessageApplication struct {
ID discord.Snowflake `json:"id"`
CoverID string `json:"cover_image,omitempty"`
Description string `json:"description"`
Icon string `json:"icon"`
Name string `json:"name"`
}
//
type MessageReference struct {
ChannelID discord.Snowflake `json:"channel_id"`
// Field might not be provided
MessageID discord.Snowflake `json:"message_id,omitempty"`
GuildID discord.Snowflake `json:"guild_id,omitempty"`
}
//
type Attachment struct {
ID discord.Snowflake `json:"id"`
Filename string `json:"filename"`
Size uint64 `json:"size"`
URL discord.URL `json:"url"`
Proxy discord.URL `json:"proxy_url"`
// Only if Image
Height uint `json:"height,omitempty"`
Width uint `json:"width,omitempty"`
}
//
func (c *Client) Messages(
channelID discord.Snowflake, limit uint) ([]Message, error) {
return c.messages(channelID, limit, nil)
}
func (c *Client) MessagesAround(
channelID, around discord.Snowflake, limit uint) ([]Message, error) {
return c.messages(channelID, limit, map[string]interface{}{
"around": around,
})
}
func (c *Client) MessagesBefore(
channelID, before discord.Snowflake, limit uint) ([]Message, error) {
return c.messages(channelID, limit, map[string]interface{}{
"before": before,
})
}
func (c *Client) MessagesAfter(
channelID, after discord.Snowflake, limit uint) ([]Message, error) {
return c.messages(channelID, limit, map[string]interface{}{
"after": after,
})
}
func (c *Client) messages(channelID discord.Snowflake,
limit uint, body map[string]interface{}) ([]Message, error) {
if body == nil {
body = map[string]interface{}{}
}
switch {
case limit == 0:
limit = 50
case limit > 100:
limit = 100
}
body["limit"] = limit
var msgs []Message
return msgs, c.RequestJSON(&msgs, "GET",
EndpointChannels+channelID.String(), httputil.WithJSONBody(c, body))
}
func (c *Client) Message(
channelID, messageID discord.Snowflake) (*Message, error) {
var msg *Message
return msg, c.RequestJSON(&msg, "GET",
EndpointChannels+channelID.String()+"/messages/"+messageID.String())
}
func (c *Client) SendMessage(channelID discord.Snowflake,
content string, embed *Embed) (*Message, error) {
return c.SendMessageComplex(channelID, SendMessageData{
Content: content,
Embed: embed,
})
}
func (c *Client) SendMessageComplex(channelID discord.Snowflake,
data SendMessageData) (*Message, error) {
if data.Embed != nil {
if err := data.Embed.Validate(); err != nil {
return nil, errors.Wrap(err, "Embed error")
}
}
var URL = EndpointChannels + channelID.String()
var msg *Message
if len(data.Files) == 0 {
// No files, no need for streaming
return msg, c.RequestJSON(&msg, "POST", URL,
httputil.WithJSONBody(c, data))
}
writer := func(w io.Writer) error {
return data.WriteMultipart(c, w)
}
resp, err := c.MeanwhileBody(writer, "POST", URL)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return msg, c.DecodeStream(resp.Body, &msg)
}
func (c *Client) EditMessage(channelID, messageID discord.Snowflake,
content string, embed *Embed, suppressEmbeds bool) (*Message, error) {
var param struct {
Content string `json:"content,omitempty"`
Embed *Embed `json:"embed,omitempty"`
Flags MessageFlags `json:"flags,omitempty"`
}
param.Content = content
param.Embed = embed
if suppressEmbeds {
param.Flags = SuppressEmbeds
}
var msg *Message
return msg, c.RequestJSON(
&msg, "PATCH",
EndpointChannels+channelID.String()+"/messages/"+messageID.String(),
httputil.WithJSONBody(c, param),
)
}
// DeleteMessage deletes a message. Requires MANAGE_MESSAGES if the message is
// not made by yourself.
func (c *Client) DeleteMessage(channelID, messageID discord.Snowflake) error {
return c.FastRequest("DELETE", EndpointChannels+channelID.String()+
"/messages/"+messageID.String())
}
// DeleteMessages only works for bots. It can't delete messages older than 2
// weeks, and will fail if tried. This endpoint requires MANAGE_MESSAGES.
func (c *Client) DeleteMessages(channelID discord.Snowflake,
messageIDs []discord.Snowflake) error {
var param struct {
Messages []discord.Snowflake `json:"messages"`
}
param.Messages = messageIDs
return c.FastRequest("POST", EndpointChannels+channelID.String()+
"/messages/bulk-delete", httputil.WithJSONBody(c, param))
}