From 01dd3633ef0c52c36f026cea7733df88b42563c6 Mon Sep 17 00:00:00 2001 From: jake Date: Tue, 24 Feb 2026 18:45:00 -0500 Subject: [PATCH] adding Context - converting messages and methods into one context per event --- README.md | 2 +- bolt.go | 29 +++++---- command.go | 55 ++++++++--------- message.go | 170 +++++++++++++++++++++++++++-------------------------- option.go | 6 +- 5 files changed, 134 insertions(+), 128 deletions(-) diff --git a/README.md b/README.md index 7849b16..9af7bb3 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ import ( func main() { b, err := bolt.New(bolt.WithLogLevel(bolt.LogLevelAll), - bolt.WithMaxGoroutines(50), + bolt.WithMaxGoroutines(150), bolt.WithPermissions(bolt.MessagePermissions, bolt.AdminPermissions)) if err != nil { diff --git a/bolt.go b/bolt.go index 939ccf6..97bd94a 100644 --- a/bolt.go +++ b/bolt.go @@ -33,8 +33,7 @@ type bolt struct { pool chan struct{} maxRoutines int msgHandlerf Payload - admin bool - tools AdminToolBox + // admin bool } type Bolt interface { @@ -64,12 +63,12 @@ func New(opts ...Option) (Bolt, error) { } b := &bolt{ - Session: bot, - commands: make(map[string]Command, 0), - logLvl: LogLevelAll, - indicator: DEFAULT_INDICATOR, - wg: sync.WaitGroup{}, - admin: false, + Session: bot, + commands: make(map[string]Command, 0), + logLvl: LogLevelAll, + indicator: DEFAULT_INDICATOR, + wg: sync.WaitGroup{}, + // admin: false, maxRoutines: DEFAULT_MAX_GOROUTINES, } @@ -80,7 +79,7 @@ func New(opts ...Option) (Bolt, error) { //options can change these fields so we must create post-opts b.pool = make(chan struct{}, b.maxRoutines) - b.tools = NewToolbox(b) + // b.tools = NewToolbox(b) return b, nil } @@ -173,7 +172,7 @@ func (b *bolt) msgEventHandler(s *dg.Session, msg *dg.MessageCreate) { ChannelID: channel.ID, Server: server.Name, ServerID: server.ID, - sesh: b, + // sesh: b, } w := strings.Fields(msg.Content) @@ -240,7 +239,10 @@ func (b *bolt) msgEventHandler(s *dg.Session, msg *dg.MessageCreate) { func (b *bolt) handleMessage(event *Message) error { if b.msgHandlerf != nil { - return b.msgHandlerf(event, b.tools) + return b.msgHandlerf(&Context{ + Message: event, + bolt: b, + }) } return nil @@ -277,7 +279,10 @@ func (b *bolt) handleCommand(msg *Message, lg int) error { } } - err = run.Payload(msg, b.tools) + err = run.Payload(&Context{ + Message: msg, + bolt: b, + }) if err != nil { return fmt.Errorf("encountered an error while handling command (%s): %e", msg.Words[0], err) } diff --git a/command.go b/command.go index 5deee6b..14655bb 100644 --- a/command.go +++ b/command.go @@ -13,37 +13,34 @@ type Command struct { Roles []string //roles that can use command, if none are set anyone can run the command } -// command payload functions, any strings returned are sent as a response to the command -type Payload func(msg *Message, admin AdminToolBox) error +// type adminToolbox struct { +// *bolt +// } +// type AdminToolBox interface { +// Timeout(userId, serverId string, duration time.Time) error +// ClearTimeout(userId, serverId string) error +// Mute(userId, serverId string) error +// Unmute(userId, serverId string) error +// } -type adminToolbox struct { - *bolt -} -type AdminToolBox interface { - Timeout(userId, serverId string, duration time.Time) error - ClearTimeout(userId, serverId string) error - Mute(userId, serverId string) error - Unmute(userId, serverId string) error -} +// func NewToolbox(b *bolt) AdminToolBox { +// return &adminToolbox{ +// bolt: b, +// } +// } -func NewToolbox(b *bolt) AdminToolBox { - return &adminToolbox{ - bolt: b, - } -} +// func (a *adminToolbox) Timeout(userId, serverId string, duration time.Time) error { +// return a.GuildMemberTimeout(serverId, userId, &duration) +// } -func (a *adminToolbox) Timeout(userId, serverId string, duration time.Time) error { - return a.GuildMemberTimeout(serverId, userId, &duration) -} +// func (a *adminToolbox) ClearTimeout(userId, serverId string) error { +// return a.GuildMemberTimeout(serverId, userId, nil) +// } -func (a *adminToolbox) ClearTimeout(userId, serverId string) error { - return a.GuildMemberTimeout(serverId, userId, nil) -} +// func (a *adminToolbox) Mute(userId, serverId string) error { +// return a.GuildMemberMute(serverId, userId, true) +// } -func (a *adminToolbox) Mute(userId, serverId string) error { - return a.GuildMemberMute(serverId, userId, true) -} - -func (a *adminToolbox) Unmute(userId, serverId string) error { - return a.GuildMemberMute(serverId, userId, false) -} +// func (a *adminToolbox) Unmute(userId, serverId string) error { +// return a.GuildMemberMute(serverId, userId, false) +// } diff --git a/message.go b/message.go index cc054a6..e4a8902 100644 --- a/message.go +++ b/message.go @@ -2,6 +2,7 @@ package bolt import ( "fmt" + "time" dg "github.com/bwmarrin/discordgo" ) @@ -11,89 +12,8 @@ const ( MSG_MAX_LENGTH = 2000 ) -// Message contains basic information about the messages received and provides a few methods -// for handling replies, bans, timeouts, reaction, and deletion. All Discord utilities will use -// a timeout to prevent hanging for too long, this timeout can be customized with the WithTimeout -// option. -type Message struct { - Author Author - ID string //message ID - Words []string //message data split on whitespaces - Content string //entire message data string - Channel string //name of channel message was sent in - ChannelID string //ID of channel message was sent in - Server string //name of guild message was sent in - ServerID string //ID of guild message was sent in - Attachments []MessageAttachment //any attachments bound to the message - Mentions []*dg.User - sesh *bolt -} - -type Author struct { - Name string - ID string - Roles []string -} - -// React applies reaction to the message -func (m *Message) React(emoji Reaction) error { - return m.sesh.MessageReactionAdd(m.ChannelID, m.ID, fmt.Sprint(emoji)) -} - -// Respond sends a response to the message, handling chunking if the message exceeds max length -func (m *Message) Respond(res string) error { - if len(res) > MSG_MAX_LENGTH { - for len(res) > 0 { - //send full chunk size allowed by discord - sc := res[:MSG_MAX_LENGTH] - rep := m.sesh.createReply(sc, m.ID, m.ChannelID, m.ServerID) - _, err := m.sesh.ChannelMessageSendComplex(m.ChannelID, rep) - 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 := m.sesh.createReply(res, m.ID, m.ChannelID, m.ServerID) - _, err := m.sesh.ChannelMessageSendComplex(m.ChannelID, final) - if err != nil { - return err - } - - break - } - } - - return nil - } - - //short enough message to send in one go - rep := m.sesh.createReply(res, m.ID, m.ChannelID, m.ServerID) - _, err := m.sesh.ChannelMessageSendComplex(m.ChannelID, rep) - return err -} - -// Delete removes the message from the current channel -func (m *Message) Delete() error { - return m.sesh.ChannelMessageDelete(m.ChannelID, m.ID, nil) -} - -// func (m *Message) Timeout(userID string, duration time.Time) error { -// return m.sesh.GuildMemberTimeout(m.serverID, userID, &duration) -// } - -// func (m *Message) ClearTimeout(userID string) error { -// return m.sesh.GuildMemberTimeout(m.serverID, userID, nil) -// } - -// func (m *Message) Mute(userID string) error { -// return m.sesh.GuildMemberMute(m.serverID, userID, true) -// } - -// func (m *Author) Unmute(userID string) error { -// return m.sesh.GuildMemberMute(m.serverID, userID, false) -// } +// command payload functions, any strings returned are sent as a response to the command +type Payload func(c *Context) error // message attachment details type MessageAttachment struct { @@ -107,3 +27,87 @@ type MessageAttachment struct { Size int DurationSecs float64 } + +type Author struct { + Name string + ID string + Roles []string +} + +type Message struct { + Author Author + ID string //message ID + Words []string //message data split on whitespaces + Content string //entire message data string + Channel string //name of channel message was sent in + ChannelID string //ID of channel message was sent in + Server string //name of guild message was sent in + ServerID string //ID of guild message was sent in + Attachments []MessageAttachment //any attachments bound to the message + Mentions []*dg.User +} + +type Context struct { + Message *Message + bolt *bolt +} + +// React applies 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 { + 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) + 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) + if err != nil { + return err + } + + break + } + } + + return nil + } + + //short enough message to send in one go + 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) +} + +func (c *Context) Timeout(userId string, duration time.Time) error { + return c.bolt.GuildMemberTimeout(c.Message.ServerID, userId, &duration) +} + +func (c *Context) ClearTimeout(userId string) error { + return c.bolt.GuildMemberTimeout(c.Message.ServerID, userId, nil) +} + +func (c *Context) Mute(userId string) error { + return c.bolt.GuildMemberMute(c.Message.ServerID, userId, true) +} + +func (c *Context) Unmute(userId string) error { + return c.bolt.GuildMemberMute(c.Message.ServerID, userId, false) +} diff --git a/option.go b/option.go index d5a1cb2..e07b553 100644 --- a/option.go +++ b/option.go @@ -34,9 +34,9 @@ func WithPermissions(perms ...Permission) Option { return func(b *bolt) { var fullPerms dg.Intent for _, p := range perms { - if p == AdminPermissions { - b.admin = true - } + // if p == AdminPermissions { + // b.admin = true + // } fullPerms |= dg.Intent(p) }