-
Notifications
You must be signed in to change notification settings - Fork 1
/
bcr.go
162 lines (129 loc) · 4.35 KB
/
bcr.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package bcr
import (
"strings"
"sync"
"time"
"github.com/diamondburned/arikawa/v3/api"
"github.com/diamondburned/arikawa/v3/discord"
"github.com/diamondburned/arikawa/v3/gateway"
"github.com/diamondburned/arikawa/v3/session/shard"
"github.com/diamondburned/arikawa/v3/state"
)
// Version returns the current brc version
func Version() string {
return "0.18.0"
}
// RequiredIntents are the intents required for the command handler
const RequiredIntents = gateway.IntentGuildMessages | gateway.IntentGuildMessageReactions | gateway.IntentDirectMessages | gateway.IntentDirectMessageReactions | gateway.IntentGuilds
// Router is the command router
type Router struct {
BotOwners []string
Prefixes []string
Prefixer Prefixer
ShardManager *shard.Manager
Bot *discord.User
Logger *Logger
BlacklistFunc func(Contexter) bool
HelpCommand func(*Context) error
DefaultMentions *api.AllowedMentions
EmbedColor discord.Color
// global permission check
// "routing" is true if it's being executed during routing, false if it's executed just for the name
// return: permission name, allowed/blocked, error message
PermissionCheck func(ctx *Context, routing bool) (name string, allowed bool, data api.SendMessageData)
ReactTimeout time.Duration
cooldowns *CooldownCache
cmds map[string]*Command
cmdMu sync.RWMutex
SlashGroups []*Group
// maps + mutexes
reactions map[reactionKey]reactionInfo
reactionMu sync.RWMutex
messages map[messageKey]messageInfo
messageMu sync.RWMutex
buttons map[buttonKey]buttonInfo
buttonMu sync.RWMutex
slashButtons map[buttonKey]slashButtonInfo
slashButtonMu sync.RWMutex
}
// New creates a new router object
func New(s *shard.Manager, owners, prefixes []string) *Router {
r := &Router{
ShardManager: s,
BotOwners: owners,
Prefixes: prefixes,
EmbedColor: discord.DefaultEmbedColor,
Logger: NewStdlibLogger(false),
DefaultMentions: &api.AllowedMentions{
Parse: []api.AllowedMentionType{api.AllowUserMention},
},
ReactTimeout: 15 * time.Minute,
cmds: make(map[string]*Command),
reactions: make(map[reactionKey]reactionInfo),
messages: make(map[messageKey]messageInfo),
buttons: make(map[buttonKey]buttonInfo),
slashButtons: make(map[buttonKey]slashButtonInfo),
cooldowns: newCooldownCache(),
}
// set prefixer
r.Prefixer = r.DefaultPrefixer
// add required handlers
r.AddHandler(r.ReactionAdd)
r.AddHandler(r.ReactionRemove)
r.AddHandler(r.ReactionMessageDelete)
r.AddHandler(r.MsgHandlerCreate)
r.AddHandler(r.ButtonHandler)
return r
}
// NewWithState creates a new router with a state.
// The token is automatically prefixed with `Bot `.
func NewWithState(token string, owners []discord.UserID, prefixes []string) (*Router, error) {
return NewWithIntents(token, owners, prefixes, RequiredIntents)
}
// NewWithIntents creates a new router with a state, with the specified intents.
// The token is automatically prefixed with `Bot `.
func NewWithIntents(token string, owners []discord.UserID, prefixes []string, intents gateway.Intents) (*Router, error) {
ownerStrings := make([]string, 0)
for _, o := range owners {
ownerStrings = append(ownerStrings, o.String())
}
newShard := state.NewShardFunc(func(m *shard.Manager, s *state.State) {
s.AddIntents(intents)
})
m, err := shard.NewManager("Bot "+token, newShard)
if err != nil {
return nil, err
}
r := New(m, ownerStrings, prefixes)
return r, nil
}
// AddCommand adds a command to the router
func (r *Router) AddCommand(c *Command) *Command {
if c.Options != nil && c.SlashCommand == nil {
panic("command.Options set without command.SlashCommand being set")
}
c.id = sGen.Get()
r.cmdMu.Lock()
defer r.cmdMu.Unlock()
r.cmds[strings.ToLower(c.Name)] = c
for _, a := range c.Aliases {
r.cmds[strings.ToLower(a)] = c
}
return c
}
// AddHandler adds a handler to all States in this Router
func (r *Router) AddHandler(v interface{}) {
r.ShardManager.ForEach(func(s shard.Shard) {
state := s.(*state.State)
state.AddHandler(v)
})
}
// StateFromGuildID returns the state.State for the given guild ID
func (r *Router) StateFromGuildID(guildID discord.GuildID) (st *state.State, id int) {
if guildID.IsValid() {
s, shardID := r.ShardManager.FromGuildID(guildID)
return s.(*state.State), shardID
}
s := r.ShardManager.Shard(0)
return s.(*state.State), 0
}