-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcontext.go
177 lines (162 loc) · 5.83 KB
/
context.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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
//go:generate go run generate_wait_for_event.go
package gommand
import (
"context"
"github.com/andersfylling/disgord"
"strings"
)
// Context defines the information which might be required to run the command.
type Context struct {
ShardID uint `json:"shardId"`
Prefix string `json:"prefix"`
Message *disgord.Message `json:"message"`
BotUser *disgord.User `json:"botUser"`
Router *Router `json:"-"`
Session disgord.Session `json:"session"`
Command CommandInterface `json:"command"`
RawArgs string `json:"rawArgs"`
Args []interface{} `json:"args"`
WaitManager *WaitManager `json:"-"`
MiddlewareParams map[string]interface{} `json:"middlewareParams"`
State interface{} `json:"state"`
}
// Replay is used to replay a command.
func (c *Context) Replay() error {
c.Args = []interface{}{}
return runCommand(c, strings.NewReader(c.RawArgs), c.Command)
}
// BotMember is used to get the bot as a member of the server this was within.
func (c *Context) BotMember() (*disgord.Member, error) {
return c.Session.Guild(c.Message.GuildID).Member(c.BotUser.ID).Get()
}
// Guild is used to get the guild if the bot needs it.
func (c *Context) Guild() (*disgord.Guild, error) {
return c.Session.Guild(c.Message.Member.GuildID).Get()
}
// Channel is used to get the channel if the bot needs it.
func (c *Context) Channel() (*disgord.Channel, error) {
return c.Session.Channel(c.Message.ChannelID).Get()
}
// Reply is used to quickly reply to a command with a message.
func (c *Context) Reply(data ...interface{}) (*disgord.Message, error) {
return c.Session.SendMsg(c.Message.ChannelID, data...)
}
// EmbedTextFailover is used to check the permissions when sending a message and failover to sending text if we cannot send an embed but can send a message.
// If the bot doesn't have permissions to send a message, we return an error.
// If the bot has permission to send an embed, we use the embed generator, and if we don't we use the text generator.
func (c *Context) EmbedTextFailover(EmbedGenerator func() *disgord.Embed, TextGenerator func() string) (*disgord.Message, error) {
// Get the permissions in the channel.
m, err := c.BotMember()
if err != nil {
return nil, err
}
channel, err := c.Channel()
if err != nil {
return nil, err
}
perms, err := channel.GetPermissions(context.TODO(), c.Session, m)
if err != nil {
return nil, err
}
// Check if we have permission to send a message.
if (perms&disgord.PermissionSendMessages) != disgord.PermissionSendMessages && (perms&disgord.PermissionAdministrator) != disgord.PermissionAdministrator {
g, err := c.Guild()
if err != nil {
return nil, err
}
if g.OwnerID != m.UserID {
return nil, &disgord.ErrRest{
Code: 403,
Msg: "Permissions check failed.",
}
}
}
// Use the correct generator depending on permissions.
var content interface{}
if (perms&disgord.PermissionEmbedLinks) == disgord.PermissionEmbedLinks || (perms&disgord.PermissionAdministrator) == disgord.PermissionAdministrator {
content = EmbedGenerator()
} else {
content = TextGenerator()
}
// Return the message.
return c.Reply(content)
}
// PermissionVerifiedReply is used to reply to a command with a message.
// This is slower than the standard reply command since it checks it has permission first, but it also reduces the risk of a Cloudflare ban from the API.
func (c *Context) PermissionVerifiedReply(data ...interface{}) (*disgord.Message, error) {
m, err := c.BotMember()
if err != nil {
return nil, err
}
channel, err := c.Channel()
if err != nil {
return nil, err
}
perms, err := channel.GetPermissions(context.TODO(), c.Session, m)
if err != nil {
return nil, err
}
required := disgord.PermissionSendMessages
for _, v := range data {
switch v.(type) {
case disgord.Embed, *disgord.Embed:
required |= disgord.PermissionEmbedLinks
case disgord.CreateMessageFileParams, *disgord.CreateMessageFileParams:
required |= disgord.PermissionAttachFiles
case disgord.Message, *disgord.Message:
embedlen := 0
x, ok := v.(disgord.Message)
if ok {
embedlen = len(x.Embeds)
} else {
x := v.(*disgord.Message)
embedlen = len(x.Embeds)
}
if embedlen >= 1 {
required |= disgord.PermissionEmbedLinks
}
}
}
if (perms&required) != required && (perms&disgord.PermissionAdministrator) != disgord.PermissionAdministrator {
g, err := c.Guild()
if err != nil {
return nil, err
}
if g.OwnerID != m.UserID {
return nil, &disgord.ErrRest{
Code: 403,
Msg: "Permissions check failed.",
}
}
}
return c.Reply(data...)
}
// WaitForMessage allows you to wait for a message. This function uses WaitForMessageCreate internally and is mainly here for simplicity and compatibility. You should NOT block during the check function.
func (c *Context) WaitForMessage(ctx context.Context, CheckFunc func(s disgord.Session, evt *disgord.Message) bool) *disgord.Message {
x := c.WaitManager.WaitForMessageCreate(ctx, func(s disgord.Session, evt *disgord.MessageCreate) bool {
return CheckFunc(s, evt.Message)
})
if x == nil {
return nil
}
return x.Message
}
// DisplayEmbedMenu is used to allow you to easily display a embed menu.
func (c *Context) DisplayEmbedMenu(m *EmbedMenu) error {
return c.DisplayEmbedMenuWithLifetime(m, nil)
}
// DisplayEmbedMenuWithLifetime is used to easily display an embed menu with a lifetime.
func (c *Context) DisplayEmbedMenuWithLifetime(m *EmbedMenu, lifetime *EmbedLifetimeOptions) error {
msg, err := c.Reply("Loading...")
if err != nil {
return err
}
err = m.Display(c.Message.ChannelID, msg.ID, c.Session)
if err != nil {
return err
}
if lifetime != nil {
lifetime.Start(msg.ChannelID, msg.ID, c.Session)
}
return nil
}