feature/improvements #8

Merged
jake merged 5 commits from feature/improvements into main 2026-02-25 19:22:27 +00:00
5 changed files with 134 additions and 128 deletions
Showing only changes of commit 01dd3633ef - Show all commits

View File

@@ -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 {

29
bolt.go
View File

@@ -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)
}

View File

@@ -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)
// }

View File

@@ -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)
}

View File

@@ -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)
}