code cleanup, split handler func
This commit is contained in:
181
bolt.go
181
bolt.go
@@ -32,11 +32,15 @@ type bolt struct {
|
||||
|
||||
type Bolt interface {
|
||||
Start() error
|
||||
AddCommands(cmd ...Command)
|
||||
//filtered methods
|
||||
stop() error
|
||||
AddCommands(cmd Command)
|
||||
messageHandler(s *dg.Session, msg *dg.MessageCreate)
|
||||
handleCommand(msg *dg.MessageCreate, s *dg.Session, server *dg.Guild, channel *dg.Channel, lg int) error
|
||||
createReply(content, message, channel, guild string) *dg.MessageSend
|
||||
getRemainingTimeout(timeout time.Time) string
|
||||
roleCheck(msg *dg.MessageCreate, s *dg.Session, run Command) (bool, error)
|
||||
timeoutCheck(msg *dg.MessageCreate, s *dg.Session, run Command) (bool, error)
|
||||
}
|
||||
|
||||
// setup
|
||||
@@ -49,7 +53,7 @@ func init() {
|
||||
}
|
||||
|
||||
// create a new bolt interface
|
||||
func New(opts ...Option) *bolt {
|
||||
func New(opts ...Option) Bolt {
|
||||
bot, err := dg.New(fmt.Sprintf("Bot %s", os.Getenv(TOKEN_ENV_VAR)))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
@@ -70,10 +74,8 @@ func New(opts ...Option) *bolt {
|
||||
return b
|
||||
}
|
||||
|
||||
// adds command handler and starts the bot, this is a BLOCKING CALL
|
||||
|
||||
// starts the bot, commands are added and the connection to Discord is opened, this is a BLOCKING
|
||||
// call and handles safe shutdown of the bot
|
||||
// call that handles safe shutdown of the bot
|
||||
func (b *bolt) Start() error {
|
||||
//register commands and open connection
|
||||
b.AddHandler(b.messageHandler)
|
||||
@@ -137,79 +139,70 @@ func (b *bolt) messageHandler(s *dg.Session, msg *dg.MessageCreate) {
|
||||
//does the message have the command indicator
|
||||
lg := len(b.indicator)
|
||||
if msg.Content[:lg] == b.indicator {
|
||||
words := strings.Split(msg.Content, " ")
|
||||
run, ok := b.Commands[words[0][lg:]]
|
||||
if !ok {
|
||||
return //command doesn't exist, maybe log or respond to author
|
||||
}
|
||||
|
||||
//has command met its timeout requirements
|
||||
wait := run.LastRun.Add(run.Timeout)
|
||||
if !time.Now().After(wait) {
|
||||
reply := b.createReply(fmt.Sprintf("that command cannot be run for another %s", b.getRemainingTimeout(wait)), msg.ID, msg.ChannelID, msg.GuildID)
|
||||
_, err := s.ChannelMessageSendComplex(msg.ChannelID, reply)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return //running too soon
|
||||
}
|
||||
|
||||
//does user have correct permissions
|
||||
if run.Roles != nil {
|
||||
var found bool
|
||||
for _, r := range msg.Member.Roles {
|
||||
n, err := s.State.Role(msg.GuildID, r)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
check := slices.Contains(run.Roles, n.Name)
|
||||
if check {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
|
||||
//can't find role, don't run command
|
||||
if !found {
|
||||
reply := b.createReply("you do not have permissions to run that command", msg.ID, msg.ChannelID, msg.GuildID)
|
||||
_, err := s.ChannelMessageSendComplex(msg.ChannelID, reply)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//run command payload
|
||||
res, err := run.Payload(Message{
|
||||
Author: msg.Author.Username,
|
||||
Words: words,
|
||||
Content: msg.Content,
|
||||
Channel: channel.Name,
|
||||
Server: server.Name,
|
||||
})
|
||||
|
||||
err := b.handleCommand(msg, s, server, channel, lg)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
//if a reply is returned send back to Discord
|
||||
if res != "" {
|
||||
reply := b.createReply(res, msg.ID, msg.ChannelID, msg.GuildID)
|
||||
_, err := s.ChannelMessageSendComplex(msg.ChannelID, reply)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//update run time
|
||||
run.LastRun = time.Now()
|
||||
b.Commands[run.Trigger] = run
|
||||
}
|
||||
}
|
||||
|
||||
// parses command from message and handles timeout checks, role checks, and command execution. All command responses are sent back to Discord
|
||||
func (b *bolt) handleCommand(msg *dg.MessageCreate, s *dg.Session, server *dg.Guild, channel *dg.Channel, lg int) error {
|
||||
words := strings.Split(msg.Content, " ")
|
||||
run, ok := b.Commands[words[0][lg:]]
|
||||
if !ok {
|
||||
return nil //command doesn't exist, maybe log or respond to author
|
||||
}
|
||||
|
||||
//has command met its timeout requirements
|
||||
tc, err := b.timeoutCheck(msg, s, run)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !tc {
|
||||
return nil
|
||||
}
|
||||
|
||||
//does user have correct permissions
|
||||
if run.Roles != nil {
|
||||
check, err := b.roleCheck(msg, s, run)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !check {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
//run command payload
|
||||
res, err := run.Payload(Message{
|
||||
Author: msg.Author.Username,
|
||||
Words: words,
|
||||
Content: msg.Content,
|
||||
Channel: channel.Name,
|
||||
Server: server.Name,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//if a reply is returned send back to Discord
|
||||
if res != "" {
|
||||
reply := b.createReply(res, msg.ID, msg.ChannelID, msg.GuildID)
|
||||
_, err := s.ChannelMessageSendComplex(msg.ChannelID, reply)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
//update run time
|
||||
run.lastRun = time.Now()
|
||||
b.Commands[run.Trigger] = run
|
||||
return nil
|
||||
}
|
||||
|
||||
// basic wrapper function to create easy Discord responses
|
||||
func (b *bolt) createReply(content, message, channel, guild string) *dg.MessageSend {
|
||||
details := &dg.MessageReference{
|
||||
@@ -244,3 +237,49 @@ func (b *bolt) getRemainingTimeout(timeout time.Time) string {
|
||||
|
||||
return fmt.Sprintf("%d%s", timeLeft, metric)
|
||||
}
|
||||
|
||||
// checks if the author of msg has the correct role to run the requested command
|
||||
func (b *bolt) roleCheck(msg *dg.MessageCreate, s *dg.Session, run Command) (bool, error) {
|
||||
var found bool
|
||||
//loop thru author roles
|
||||
for _, r := range msg.Member.Roles {
|
||||
//get role name from ID
|
||||
n, err := s.State.Role(msg.GuildID, r)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
//does this role exist in command roles
|
||||
check := slices.Contains(run.Roles, n.Name)
|
||||
if check {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
//can't find role, don't run command, alert user of missing permissions
|
||||
if !found {
|
||||
reply := b.createReply("you do not have permissions to run that command", msg.ID, msg.ChannelID, msg.GuildID)
|
||||
_, err := s.ChannelMessageSendComplex(msg.ChannelID, reply)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// check if the command timeout has been met, responding with remaining time if timeout has not been met yet.
|
||||
func (b *bolt) timeoutCheck(msg *dg.MessageCreate, s *dg.Session, run Command) (bool, error) {
|
||||
wait := run.lastRun.Add(run.Timeout)
|
||||
if !time.Now().After(wait) {
|
||||
reply := b.createReply(fmt.Sprintf("that command cannot be run for another %s", b.getRemainingTimeout(wait)), msg.ID, msg.ChannelID, msg.GuildID)
|
||||
_, err := s.ChannelMessageSendComplex(msg.ChannelID, reply)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user