Files
bolt/message.go

129 lines
3.7 KiB
Go
Raw Normal View History

package bolt
2025-08-17 20:37:22 -04:00
import (
"fmt"
"time"
2025-08-17 20:37:22 -04:00
dg "github.com/bwmarrin/discordgo"
)
2026-01-26 22:59:13 -05:00
const (
// the max length allowed for basic messages, if the message content exceeds this amount
// then messages are split unto chunks of max size
2026-01-26 22:59:13 -05:00
MSG_MAX_LENGTH = 2000
)
// command and message payload function type
type Payload func(c *Context) error
type MessageAttachment struct {
ID string
URL string
ProxyURL string
Filename string
ContentType string
Width int
Height int
Size int
DurationSecs float64
}
// Author contains basic information about message authors
type Author struct {
Name string
ID string
Roles []string
}
// Message contains all needed data to handle message events
type Message struct {
Author Author
//current message ID
ID string
//message content split on whitespace to allow for easy argument parsing with commands
Words []string
//entire message content unchanged
Content string
//channel message was sent in, name and ID
Channel string
ChannelID string
//guild message was sent in, name and ID
Server string
ServerID string
//message extras
Attachments []MessageAttachment //any attachments bound to the message
Mentions []*dg.User //users mention in the message with @
}
// Context is the struct passed to message and command handlers, it contains all needed message data as well as
// some methods to make interaction with the message as easy as possible
type Context struct {
Message *Message
bolt *bolt
2026-02-24 18:19:41 -05:00
}
// React applies the reaction to the message
func (c *Context) React(emoji Reaction) error {
return c.bolt.MessageReactionAdd(c.Message.ChannelID, c.Message.ID, fmt.Sprint(emoji))
}
// Respond sends a response to the message, handling chunking if the message exceeds max length
func (c *Context) Respond(res string) error {
2026-01-26 22:59:13 -05:00
if len(res) > MSG_MAX_LENGTH {
for len(res) > 0 {
//send full chunk size allowed by discord
sc := res[:MSG_MAX_LENGTH]
rep := c.bolt.createReply(sc, c.Message.ID, c.Message.ChannelID, c.Message.ServerID)
_, err := c.bolt.ChannelMessageSendComplex(c.Message.ChannelID, rep)
2026-01-26 22:59:13 -05:00
if err != nil {
return err
}
res = res[MSG_MAX_LENGTH:]
//if we have left than a full chunk send the rest and break the loop
if len(res) < MSG_MAX_LENGTH {
final := c.bolt.createReply(res, c.Message.ID, c.Message.ChannelID, c.Message.ServerID)
_, err := c.bolt.ChannelMessageSendComplex(c.Message.ChannelID, final)
2026-01-26 22:59:13 -05:00
if err != nil {
return err
}
break
}
}
return nil
}
//short enough message to send in one go, so ship it
rep := c.bolt.createReply(res, c.Message.ID, c.Message.ChannelID, c.Message.ServerID)
_, err := c.bolt.ChannelMessageSendComplex(c.Message.ChannelID, rep)
return err
}
// Delete removes the message from the current channel
func (c *Context) Delete() error {
return c.bolt.ChannelMessageDelete(c.Message.ChannelID, c.Message.ID, nil)
}
// Timeout creates a user timeout for the supplied userID that lasts until duration is exceeded or the
// timeout is cleared
func (c *Context) Timeout(userId string, duration time.Time) error {
return c.bolt.GuildMemberTimeout(c.Message.ServerID, userId, &duration)
}
// ClearTimeout clears existing user timeouts, allowing them access again
func (c *Context) ClearTimeout(userId string) error {
return c.bolt.GuildMemberTimeout(c.Message.ServerID, userId, nil)
}
// Mute handles muting a user from Voice Chat, this mute stays until it is Unmute()'d
func (c *Context) Mute(userId string) error {
return c.bolt.GuildMemberMute(c.Message.ServerID, userId, true)
}
2025-08-17 20:37:22 -04:00
// Unmute removes a mute on the user, allowing them vc access again
func (c *Context) Unmute(userId string) error {
return c.bolt.GuildMemberMute(c.Message.ServerID, userId, false)
}