1
0
Fork 0
mirror of https://github.com/diamondburned/arikawa.git synced 2025-01-05 19:57:02 +00:00

Bot: Added EditableCommands

This commit is contained in:
diamondburned 2020-05-14 18:52:15 -07:00
parent 6b8628804f
commit 795a69ca7d
5 changed files with 47 additions and 18 deletions

View file

@ -63,16 +63,6 @@ custom remote or local state storage.
things in the state, which is useful for keeping it updated.
- No code generation: just so the library is a lot easier to maintain.
## You-should-knows
- ~~The bot will fatally exit if it fails to reconnect to the Gateway after a
certain amount of times. This is changeable in `gateway.WSFatal`, or
`(*Gateway).FatalLog`.~~
- ~~The bot will error out if the initial connection fails. However,
reconnections will be retried forever until it succeeds.~~ This is no longer
true. The bot will retry until `WSRetries` is reached, then the error will go
to `(*Gateway).FatalError` or `(*Gateway).Wait()`.
## Testing
The package includes integration tests that require `$BOT_TOKEN`. To run these

View file

@ -19,6 +19,7 @@ func main() {
wait, err := bot.Start(token, commands, func(ctx *bot.Context) error {
ctx.HasPrefix = bot.NewPrefix("!", "~")
ctx.EditableCommands = true
// Subcommand demo, but this can be in another package.
ctx.MustRegisterSubcommand(&Debug{})

View file

@ -124,6 +124,11 @@ type Context struct {
// MessageCreate events.
ReplyError bool
// EditableCommands when true will also listen for MessageUpdateEvent and
// treat them as newly created messages. This is convenient if you want
// to quickly edit a message and re-execute the command.
EditableCommands bool
// Subcommands contains all the registered subcommands. This is not
// exported, as it shouldn't be used directly.
subcommands []*Subcommand

View file

@ -58,19 +58,51 @@ func (ctx *Context) callCmd(ev interface{}) (bottomError error) {
}
}
var msc *gateway.MessageCreateEvent
// We call the messages later, since we want MessageCreate middlewares to
// run as well.
if evT == typeMessageCreate {
// safe assertion always
err := ctx.callMessageCreate(ev.(*gateway.MessageCreateEvent), evV)
// There's no need for an errNoBreak here, as the method already checked
// for that.
if err != nil {
bottomError = err
switch {
case evT == typeMessageCreate:
msc = ev.(*gateway.MessageCreateEvent)
case evT == typeMessageUpdate && ctx.EditableCommands:
up := ev.(*gateway.MessageUpdateEvent)
// Message updates could have empty contents when only their embeds are
// filled. We don't need that here.
if up.Content == "" {
return nil
}
// Query the updated message.
m, err := ctx.Store.Message(up.ChannelID, up.ID)
if err != nil {
// It's probably safe to ignore this.
return nil
}
// Treat the message update as a message create event to avoid breaking
// changes.
msc = &gateway.MessageCreateEvent{Message: *m, Member: up.Member}
// Fill up member, if available.
if m.GuildID.Valid() && up.Member == nil {
if mem, err := ctx.Store.Member(m.GuildID, m.Author.ID); err == nil {
msc.Member = mem
}
}
// Update the reflect value as well.
evV = reflect.ValueOf(msc)
default:
// Unknown event, return.
return nil
}
return
// There's no need for an errNoBreak here, as the method already checked
// for that.
return ctx.callMessageCreate(msc, evV)
}
func (ctx *Context) callMessageCreate(mc *gateway.MessageCreateEvent, value reflect.Value) error {

View file

@ -12,6 +12,7 @@ import (
var (
typeMessageCreate = reflect.TypeOf((*gateway.MessageCreateEvent)(nil))
typeMessageUpdate = reflect.TypeOf((*gateway.MessageUpdateEvent)(nil))
typeString = reflect.TypeOf("")
typeEmbed = reflect.TypeOf((*discord.Embed)(nil))