mirror of
https://github.com/diamondburned/arikawa.git
synced 2025-01-20 19:47:12 +00:00
*: Linting and typo fixes (#134)
* Linting and typo fixes * Linting and typo fixes * revert comma fix
This commit is contained in:
parent
8baf8ee84b
commit
1585797b52
12
README.md
12
README.md
|
@ -3,7 +3,7 @@
|
|||
[![Pipeline status](https://gitlab.com/diamondburned/arikawa/badges/master/pipeline.svg?style=flat-square)](https://gitlab.com/diamondburned/arikawa/pipelines )
|
||||
[![ Coverage](https://gitlab.com/diamondburned/arikawa/badges/master/coverage.svg?style=flat-square)](https://gitlab.com/diamondburned/arikawa/commits/master )
|
||||
[![ Report Card](https://goreportcard.com/badge/github.com/diamondburned/arikawa?style=flat-square )](https://goreportcard.com/report/github.com/diamondburned/arikawa)
|
||||
[![Godoc Reference](https://img.shields.io/badge/godoc-reference-blue?style=flat-square )](https://godoc.org/github.com/diamondburned/arikawa )
|
||||
[![Godoc Reference](https://img.shields.io/badge/godoc-reference-blue?style=flat-square )](https://pkg.go.dev/github.com/diamondburned/arikawa )
|
||||
[![ Examples](https://img.shields.io/badge/Example-__example%2F-blueviolet?style=flat-square )](https://github.com/diamondburned/arikawa/tree/master/_example )
|
||||
[![Discord Gophers](https://img.shields.io/badge/Discord%20Gophers-%23arikawa-%237289da?style=flat-square)](https://discord.gg/7jSf85J )
|
||||
[![ Hime Arikawa](https://img.shields.io/badge/Hime-Arikawa-ea75a2?style=flat-square )](https://hime-goto.fandom.com/wiki/Hime_Arikawa )
|
||||
|
@ -15,7 +15,7 @@ A Golang library for the Discord API.
|
|||
### [Simple](https://github.com/diamondburned/arikawa/tree/master/_example/simple)
|
||||
|
||||
Simple bot example without any state. All it does is logging messages sent into
|
||||
the console. Run with `BOT_TOKEN="TOKEN" go run .`
|
||||
the console. Run with `BOT_TOKEN="TOKEN" go run .`.
|
||||
|
||||
### [Undeleter](https://github.com/diamondburned/arikawa/tree/master/_example/undeleter)
|
||||
|
||||
|
@ -24,8 +24,8 @@ everything, including messages. It detects when someone deletes a message,
|
|||
logging the content into the console.
|
||||
|
||||
This example demonstrates the PreHandler feature of this library. PreHandler
|
||||
calls all handlers that are registered (separately from session), calling them
|
||||
before the state is updated.
|
||||
calls all handlers that are registered (separately from the session), calling
|
||||
them before the state is updated.
|
||||
|
||||
### [Advanced Bot](https://github.com/diamondburned/arikawa/tree/master/_example/advanced_bot)
|
||||
|
||||
|
@ -34,7 +34,7 @@ that's built-in. The router turns exported struct methods into commands, its
|
|||
arguments into command arguments, and more.
|
||||
|
||||
The library has a pretty detailed documentation available in [GoDoc
|
||||
Reference](https://godoc.org/github.com/diamondburned/arikawa/bot).
|
||||
Reference](https://pkg.go.dev/github.com/diamondburned/arikawa/bot).
|
||||
|
||||
## Comparison: Why not discordgo?
|
||||
|
||||
|
@ -66,7 +66,7 @@ things in the state, which is useful for keeping it updated.
|
|||
## Testing
|
||||
|
||||
The package includes integration tests that require `$BOT_TOKEN`. To run these
|
||||
tests, do
|
||||
tests, do:
|
||||
|
||||
```sh
|
||||
export BOT_TOKEN="<BOT_TOKEN>"
|
||||
|
|
|
@ -26,22 +26,22 @@ func (bot *Bot) Setup(sub *bot.Subcommand) {
|
|||
}
|
||||
|
||||
// Help prints the default help message.
|
||||
func (bot *Bot) Help(m *gateway.MessageCreateEvent) (string, error) {
|
||||
func (bot *Bot) Help(*gateway.MessageCreateEvent) (string, error) {
|
||||
return bot.Ctx.Help(), nil
|
||||
}
|
||||
|
||||
// Add demonstrates the usage of typed arguments. Run it with "~add 1 2".
|
||||
func (bot *Bot) Add(m *gateway.MessageCreateEvent, a, b int) (string, error) {
|
||||
func (bot *Bot) Add(_ *gateway.MessageCreateEvent, a, b int) (string, error) {
|
||||
return fmt.Sprintf("%d + %d = %d", a, b, a+b), nil
|
||||
}
|
||||
|
||||
// Ping is a simple ping example, perhaps the most simple you could make it.
|
||||
func (bot *Bot) Ping(m *gateway.MessageCreateEvent) (string, error) {
|
||||
func (bot *Bot) Ping(*gateway.MessageCreateEvent) (string, error) {
|
||||
return "Pong!", nil
|
||||
}
|
||||
|
||||
// Say demonstrates how arguments.Flag could be used without the flag library.
|
||||
func (bot *Bot) Say(m *gateway.MessageCreateEvent, f bot.RawArguments) (string, error) {
|
||||
func (bot *Bot) Say(_ *gateway.MessageCreateEvent, f bot.RawArguments) (string, error) {
|
||||
if f != "" {
|
||||
return string(f), nil
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ func (bot *Bot) Repeat(m *gateway.MessageCreateEvent) (string, error) {
|
|||
|
||||
// Embed is a simple embed creator. Its purpose is to demonstrate the usage of
|
||||
// the ParseContent interface, as well as using the stdlib flag package.
|
||||
func (bot *Bot) Embed(m *gateway.MessageCreateEvent, f arguments.Flag) (*discord.Embed, error) {
|
||||
func (bot *Bot) Embed(_ *gateway.MessageCreateEvent, f arguments.Flag) (*discord.Embed, error) {
|
||||
fs := arguments.NewFlagSet()
|
||||
|
||||
var (
|
||||
|
|
|
@ -27,7 +27,7 @@ func (d *Debug) Setup(sub *bot.Subcommand) {
|
|||
// Manually set the usage for each function.
|
||||
|
||||
sub.ChangeCommandInfo("GOOS", "GOOS", "Prints the current operating system")
|
||||
sub.ChangeCommandInfo("GC", "GC", "Triggers the garbage collecto")
|
||||
sub.ChangeCommandInfo("GC", "GC", "Triggers the garbage collector")
|
||||
sub.ChangeCommandInfo("Goroutines", "", "Prints the current number of Goroutines")
|
||||
|
||||
sub.Hide("Die")
|
||||
|
@ -35,7 +35,7 @@ func (d *Debug) Setup(sub *bot.Subcommand) {
|
|||
}
|
||||
|
||||
// ~go goroutines
|
||||
func (d *Debug) Goroutines(m *gateway.MessageCreateEvent) (string, error) {
|
||||
func (d *Debug) Goroutines(*gateway.MessageCreateEvent) (string, error) {
|
||||
return fmt.Sprintf(
|
||||
"goroutines: %d",
|
||||
runtime.NumGoroutine(),
|
||||
|
@ -43,12 +43,12 @@ func (d *Debug) Goroutines(m *gateway.MessageCreateEvent) (string, error) {
|
|||
}
|
||||
|
||||
// ~go GOOS
|
||||
func (d *Debug) GOOS(m *gateway.MessageCreateEvent) (string, error) {
|
||||
func (d *Debug) GOOS(*gateway.MessageCreateEvent) (string, error) {
|
||||
return strings.Title(runtime.GOOS), nil
|
||||
}
|
||||
|
||||
// ~go GC
|
||||
func (d *Debug) GC(m *gateway.MessageCreateEvent) (string, error) {
|
||||
func (d *Debug) GC(*gateway.MessageCreateEvent) (string, error) {
|
||||
runtime.GC()
|
||||
return "Done.", nil
|
||||
}
|
||||
|
|
|
@ -13,10 +13,10 @@ import (
|
|||
|
||||
var (
|
||||
BaseEndpoint = "https://discord.com"
|
||||
APIVersion = "6"
|
||||
APIPath = "/api/v" + APIVersion
|
||||
Version = "6"
|
||||
Path = "/api/v" + Version
|
||||
|
||||
Endpoint = BaseEndpoint + APIPath + "/"
|
||||
Endpoint = BaseEndpoint + Path + "/"
|
||||
EndpointGateway = Endpoint + "gateway"
|
||||
EndpointGatewayBot = EndpointGateway + "/bot"
|
||||
)
|
||||
|
@ -34,7 +34,7 @@ func NewClient(token string) *Client {
|
|||
|
||||
func NewCustomClient(token string, httpClient *httputil.Client) *Client {
|
||||
ses := Session{
|
||||
Limiter: rate.NewLimiter(APIPath),
|
||||
Limiter: rate.NewLimiter(Path),
|
||||
Token: token,
|
||||
UserAgent: UserAgent,
|
||||
}
|
||||
|
|
|
@ -87,10 +87,10 @@ type MoveChannelData struct {
|
|||
// MoveChannel modifies the position of channels in the guild.
|
||||
//
|
||||
// Requires MANAGE_CHANNELS.
|
||||
func (c *Client) MoveChannel(guildID discord.GuildID, datum []MoveChannelData) error {
|
||||
func (c *Client) MoveChannel(guildID discord.GuildID, data []MoveChannelData) error {
|
||||
return c.FastRequest(
|
||||
"PATCH",
|
||||
EndpointGuilds+guildID.String()+"/channels", httputil.WithJSONBody(datum),
|
||||
EndpointGuilds+guildID.String()+"/channels", httputil.WithJSONBody(data),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ func (c *Client) EditChannelPermission(
|
|||
// role in a channel. Only usable for guild channels.
|
||||
//
|
||||
// Requires the MANAGE_ROLES permission.
|
||||
func (c *Client) DeleteChannelPermission(channelID, overwriteID discord.Snowflake) error {
|
||||
func (c *Client) DeleteChannelPermission(channelID discord.ChannelID, overwriteID discord.Snowflake) error {
|
||||
return c.FastRequest(
|
||||
"DELETE",
|
||||
EndpointChannels+channelID.String()+"/permissions/"+overwriteID.String(),
|
||||
|
|
|
@ -18,8 +18,8 @@ func NewCustomEmoji(id discord.EmojiID, name string) Emoji {
|
|||
|
||||
// Emojis returns a list of emoji objects for the given guild.
|
||||
func (c *Client) Emojis(guildID discord.GuildID) ([]discord.Emoji, error) {
|
||||
var emjs []discord.Emoji
|
||||
return emjs, c.RequestJSON(&emjs, "GET", EndpointGuilds+guildID.String()+"/emojis")
|
||||
var e []discord.Emoji
|
||||
return e, c.RequestJSON(&e, "GET", EndpointGuilds+guildID.String()+"/emojis")
|
||||
}
|
||||
|
||||
// Emoji returns an emoji object for the given guild and emoji IDs.
|
||||
|
|
|
@ -28,9 +28,8 @@ type Limiter struct {
|
|||
|
||||
Prefix string
|
||||
|
||||
global *int64 // atomic guarded, unixnano
|
||||
buckets sync.Map
|
||||
globalRate time.Duration
|
||||
global *int64 // atomic guarded, unixnano
|
||||
buckets sync.Map
|
||||
}
|
||||
|
||||
type CustomRateLimit struct {
|
||||
|
@ -43,7 +42,6 @@ type bucket struct {
|
|||
custom *CustomRateLimit
|
||||
|
||||
remaining uint64
|
||||
limit uint
|
||||
|
||||
reset time.Time
|
||||
lastReset time.Time // only for custom
|
||||
|
@ -102,7 +100,7 @@ func (l *Limiter) Acquire(ctx context.Context, path string) error {
|
|||
|
||||
if b.remaining == 0 && b.reset.After(time.Now()) {
|
||||
// out of turns, gotta wait
|
||||
sleep = b.reset.Sub(time.Now())
|
||||
sleep = time.Until(b.reset)
|
||||
} else {
|
||||
// maybe global rate limit has it
|
||||
now := time.Now()
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"io"
|
||||
"mime/multipart"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
|
@ -15,8 +14,6 @@ import (
|
|||
|
||||
const AttachmentSpoilerPrefix = "SPOILER_"
|
||||
|
||||
var quoteEscaper = strings.NewReplacer(`\`, `\\`, `"`, `\"`)
|
||||
|
||||
// AllowedMentions is a whitelist of mentions for a message.
|
||||
// https://discordapp.com/developers/docs/resources/channel#allowed-mentions-object
|
||||
//
|
||||
|
|
|
@ -115,7 +115,7 @@ var ShellwordsEscaper = strings.NewReplacer(
|
|||
var nilV = reflect.Value{}
|
||||
|
||||
func newArgument(t reflect.Type, variadic bool) (*Argument, error) {
|
||||
// Allow array types if varidic is true.
|
||||
// Allow array types if variadic is true.
|
||||
if variadic && t.Kind() == reflect.Slice {
|
||||
t = t.Elem()
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ func newArgument(t reflect.Type, variadic bool) (*Argument, error) {
|
|||
ptr = true
|
||||
}
|
||||
|
||||
// This shouldn't be varidic.
|
||||
// This shouldn't be variadic.
|
||||
if !variadic && typeI.Implements(typeICusP) {
|
||||
mt, _ := typeI.MethodByName("CustomParse")
|
||||
|
||||
|
|
23
bot/ctx.go
23
bot/ctx.go
|
@ -7,11 +7,12 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/diamondburned/arikawa/api"
|
||||
"github.com/diamondburned/arikawa/bot/extras/shellwords"
|
||||
"github.com/diamondburned/arikawa/gateway"
|
||||
"github.com/diamondburned/arikawa/state"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Prefixer checks a message if it starts with the desired prefix. By default,
|
||||
|
@ -181,7 +182,7 @@ func Start(
|
|||
|
||||
// Wait blocks until SIGINT.
|
||||
func Wait() {
|
||||
sigs := make(chan os.Signal)
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, os.Interrupt)
|
||||
<-sigs
|
||||
}
|
||||
|
@ -249,13 +250,13 @@ func (ctx *Context) Subcommands() []*Subcommand {
|
|||
// // Find a command from a subcommand:
|
||||
// cmd = ctx.FindMethod("Starboard", "Reset")
|
||||
//
|
||||
func (ctx *Context) FindCommand(structname, methodname string) *MethodContext {
|
||||
if structname == "" {
|
||||
return ctx.Subcommand.FindCommand(methodname)
|
||||
func (ctx *Context) FindCommand(structName, methodName string) *MethodContext {
|
||||
if structName == "" {
|
||||
return ctx.Subcommand.FindCommand(methodName)
|
||||
}
|
||||
for _, sub := range ctx.subcommands {
|
||||
if sub.StructName == structname {
|
||||
return sub.FindCommand(methodname)
|
||||
if sub.StructName == structName {
|
||||
return sub.FindCommand(methodName)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@ -268,8 +269,8 @@ func (ctx *Context) MustRegisterSubcommand(cmd interface{}) *Subcommand {
|
|||
return ctx.MustRegisterSubcommandCustom(cmd, "")
|
||||
}
|
||||
|
||||
// MustReisterSubcommandCustom works similarly to MustRegisterSubcommand, but
|
||||
// takeks an extra argument for a command name override.
|
||||
// MustRegisterSubcommandCustom works similarly to MustRegisterSubcommand, but
|
||||
// takes an extra argument for a command name override.
|
||||
func (ctx *Context) MustRegisterSubcommandCustom(cmd interface{}, name string) *Subcommand {
|
||||
s, err := ctx.RegisterSubcommandCustom(cmd, name)
|
||||
if err != nil {
|
||||
|
@ -314,8 +315,8 @@ func (ctx *Context) RegisterSubcommandCustom(cmd interface{}, name string) (*Sub
|
|||
return s, nil
|
||||
}
|
||||
|
||||
// Start adds itself into the discordgo Session handlers. This needs to be run.
|
||||
// The returned function is a delete function, which removes itself from the
|
||||
// Start adds itself into the session handlers. This needs to be run. The
|
||||
// returned function is a delete function, which removes itself from the
|
||||
// Session handlers.
|
||||
func (ctx *Context) Start() func() {
|
||||
return ctx.State.AddHandler(func(v interface{}) {
|
||||
|
|
|
@ -117,7 +117,7 @@ func (ctx *Context) callMessageCreate(mc *gateway.MessageCreateEvent, value refl
|
|||
return nil
|
||||
}
|
||||
|
||||
// trim the prefix before splitting, this way multi-words prefices work
|
||||
// trim the prefix before splitting, this way multi-words prefixes work
|
||||
content := mc.Content[len(pf):]
|
||||
|
||||
if content == "" {
|
||||
|
@ -226,7 +226,7 @@ func (ctx *Context) callMessageCreate(mc *gateway.MessageCreateEvent, value refl
|
|||
vars := make([]reflect.Value, 0, len(arguments))
|
||||
|
||||
// Parse the rest with variadic arguments. Go's reflect states that
|
||||
// varidic parameters will automatically be copied, which is good.
|
||||
// variadic parameters will automatically be copied, which is good.
|
||||
for i := 0; len(arguments) > 0; i++ {
|
||||
v, err := last.fn(arguments[0])
|
||||
if err != nil {
|
||||
|
|
|
@ -30,11 +30,11 @@ func (h *hasPlumb) Plumber(_ *gateway.MessageCreateEvent, c RawArguments) error
|
|||
}
|
||||
|
||||
func TestSubcommandPlumb(t *testing.T) {
|
||||
var state = &state.State{
|
||||
var s = &state.State{
|
||||
Store: state.NewDefaultStore(nil),
|
||||
}
|
||||
|
||||
c, err := New(state, &testc{})
|
||||
c, err := New(s, &testc{})
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create new context:", err)
|
||||
}
|
||||
|
@ -78,11 +78,11 @@ func (h *onlyPlumb) Plumber(_ *gateway.MessageCreateEvent, c RawArguments) error
|
|||
}
|
||||
|
||||
func TestSubcommandOnlyPlumb(t *testing.T) {
|
||||
var state = &state.State{
|
||||
var s = &state.State{
|
||||
Store: state.NewDefaultStore(nil),
|
||||
}
|
||||
|
||||
c, err := New(state, &testc{})
|
||||
c, err := New(s, &testc{})
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create new context:", err)
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ func (t *testc) Custom(_ *gateway.MessageCreateEvent, c *ArgumentParts) {
|
|||
func (t *testc) Variadic(_ *gateway.MessageCreateEvent, c ...*customParsed) {
|
||||
t.Return <- c[len(c)-1]
|
||||
}
|
||||
func (t *testc) TrailCustom(_ *gateway.MessageCreateEvent, s string, c ArgumentParts) {
|
||||
func (t *testc) TrailCustom(_ *gateway.MessageCreateEvent, _ string, c ArgumentParts) {
|
||||
t.Return <- c
|
||||
}
|
||||
func (t *testc) Content(_ *gateway.MessageCreateEvent, c RawArguments) {
|
||||
|
@ -64,11 +64,11 @@ func (t *testc) OnTyping(*gateway.TypingStartEvent) {
|
|||
}
|
||||
|
||||
func TestNewContext(t *testing.T) {
|
||||
var state = &state.State{
|
||||
var s = &state.State{
|
||||
Store: state.NewDefaultStore(nil),
|
||||
}
|
||||
|
||||
c, err := New(state, &testc{})
|
||||
c, err := New(s, &testc{})
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create new context:", err)
|
||||
}
|
||||
|
@ -80,12 +80,12 @@ func TestNewContext(t *testing.T) {
|
|||
|
||||
func TestContext(t *testing.T) {
|
||||
var given = &testc{}
|
||||
var state = &state.State{
|
||||
var s = &state.State{
|
||||
Store: state.NewDefaultStore(nil),
|
||||
Handler: handler.New(),
|
||||
}
|
||||
|
||||
s, err := NewSubcommand(given)
|
||||
sub, err := NewSubcommand(given)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to create subcommand:", err)
|
||||
}
|
||||
|
@ -94,8 +94,8 @@ func TestContext(t *testing.T) {
|
|||
Name: "arikawa/bot test",
|
||||
Description: "Just a test.",
|
||||
|
||||
Subcommand: s,
|
||||
State: state,
|
||||
Subcommand: sub,
|
||||
State: s,
|
||||
ParseArgs: DefaultArgsParser(),
|
||||
}
|
||||
|
||||
|
@ -105,11 +105,11 @@ func TestContext(t *testing.T) {
|
|||
}
|
||||
|
||||
if given.Ctx == nil {
|
||||
t.Fatal("given's Context field is nil")
|
||||
t.Fatal("given'sub Context field is nil")
|
||||
}
|
||||
|
||||
if given.Ctx.State.Store == nil {
|
||||
t.Fatal("given's State is nil")
|
||||
t.Fatal("given'sub State is nil")
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -167,11 +167,11 @@ func TestContext(t *testing.T) {
|
|||
ctx.HasPrefix = NewPrefix("~")
|
||||
|
||||
var (
|
||||
strings = "hacka doll no. 3"
|
||||
send = "hacka doll no. 3"
|
||||
expects = []string{"hacka", "doll", "no.", "3"}
|
||||
)
|
||||
|
||||
if err := expect(ctx, given, expects, "~send "+strings); err.Error() != "oh no" {
|
||||
if err := expect(ctx, given, expects, "~send "+send); err.Error() != "oh no" {
|
||||
t.Fatal("Unexpected error:", err)
|
||||
}
|
||||
})
|
||||
|
@ -355,26 +355,26 @@ func sendMsg(ctx *Context, given *testc, into interface{}, content string) (call
|
|||
}
|
||||
|
||||
func BenchmarkConstructor(b *testing.B) {
|
||||
var state = &state.State{
|
||||
var s = &state.State{
|
||||
Store: state.NewDefaultStore(nil),
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = New(state, &testc{})
|
||||
_, _ = New(s, &testc{})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCall(b *testing.B) {
|
||||
var given = &testc{}
|
||||
var state = &state.State{
|
||||
var s = &state.State{
|
||||
Store: state.NewDefaultStore(nil),
|
||||
}
|
||||
|
||||
s, _ := NewSubcommand(given)
|
||||
sub, _ := NewSubcommand(given)
|
||||
|
||||
var ctx = &Context{
|
||||
Subcommand: s,
|
||||
State: state,
|
||||
Subcommand: sub,
|
||||
State: s,
|
||||
HasPrefix: NewPrefix("~"),
|
||||
ParseArgs: DefaultArgsParser(),
|
||||
}
|
||||
|
@ -394,15 +394,15 @@ func BenchmarkCall(b *testing.B) {
|
|||
|
||||
func BenchmarkHelp(b *testing.B) {
|
||||
var given = &testc{}
|
||||
var state = &state.State{
|
||||
var s = &state.State{
|
||||
Store: state.NewDefaultStore(nil),
|
||||
}
|
||||
|
||||
s, _ := NewSubcommand(given)
|
||||
sub, _ := NewSubcommand(given)
|
||||
|
||||
var ctx = &Context{
|
||||
Subcommand: s,
|
||||
State: state,
|
||||
Subcommand: sub,
|
||||
State: s,
|
||||
HasPrefix: NewPrefix("~"),
|
||||
ParseArgs: DefaultArgsParser(),
|
||||
}
|
||||
|
|
|
@ -2,18 +2,20 @@ package arguments
|
|||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/diamondburned/arikawa/discord"
|
||||
)
|
||||
|
||||
func TestChannelMention(t *testing.T) {
|
||||
test := new(ChannelMention)
|
||||
str := "<#123123>"
|
||||
id := 123123
|
||||
var id discord.ChannelID = 123123
|
||||
|
||||
if err := test.Parse(str); err != nil {
|
||||
t.Fatal("Expected", id, "error:", err)
|
||||
}
|
||||
|
||||
if id := test.ID(); id != id {
|
||||
if actualID := test.ID(); actualID != id {
|
||||
t.Fatal("Expected", id, "got", id)
|
||||
}
|
||||
|
||||
|
@ -25,13 +27,13 @@ func TestChannelMention(t *testing.T) {
|
|||
func TestUserMention(t *testing.T) {
|
||||
test := new(UserMention)
|
||||
str := "<@123123>"
|
||||
id := 123123
|
||||
var id discord.UserID = 123123
|
||||
|
||||
if err := test.Parse(str); err != nil {
|
||||
t.Fatal("Expected", id, "error:", err)
|
||||
}
|
||||
|
||||
if id := test.ID(); id != id {
|
||||
if actualID := test.ID(); actualID != id {
|
||||
t.Fatal("Expected", id, "got", id)
|
||||
}
|
||||
|
||||
|
@ -43,13 +45,13 @@ func TestUserMention(t *testing.T) {
|
|||
func TestRoleMention(t *testing.T) {
|
||||
test := new(RoleMention)
|
||||
str := "<@&123123>"
|
||||
id := 123123
|
||||
var id discord.RoleID = 123123
|
||||
|
||||
if err := test.Parse(str); err != nil {
|
||||
t.Fatal("Expected", id, "error:", err)
|
||||
}
|
||||
|
||||
if id := test.ID(); id != id {
|
||||
if actualID := test.ID(); actualID != id {
|
||||
t.Fatal("Expected", id, "got", id)
|
||||
}
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ func (s *mockStore) Guild(id discord.GuildID) (*discord.Guild, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (s *mockStore) Member(guildID discord.GuildID, userID discord.UserID) (*discord.Member, error) {
|
||||
func (s *mockStore) Member(_ discord.GuildID, userID discord.UserID) (*discord.Member, error) {
|
||||
return &discord.Member{
|
||||
User: discord.User{ID: userID},
|
||||
RoleIDs: []discord.RoleID{discord.RoleID(userID)},
|
||||
|
|
|
@ -10,7 +10,7 @@ type ErrParse struct {
|
|||
}
|
||||
|
||||
func Parse(line string) ([]string, error) {
|
||||
args := []string{}
|
||||
var args []string
|
||||
buf := ""
|
||||
var escaped, doubleQuoted, singleQuoted bool
|
||||
backtick := ""
|
||||
|
|
|
@ -4,29 +4,21 @@ import (
|
|||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/diamondburned/arikawa/api"
|
||||
"github.com/diamondburned/arikawa/discord"
|
||||
"github.com/diamondburned/arikawa/gateway"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/diamondburned/arikawa/gateway"
|
||||
)
|
||||
|
||||
var (
|
||||
typeMessageCreate = reflect.TypeOf((*gateway.MessageCreateEvent)(nil))
|
||||
typeMessageUpdate = reflect.TypeOf((*gateway.MessageUpdateEvent)(nil))
|
||||
|
||||
typeString = reflect.TypeOf("")
|
||||
typeEmbed = reflect.TypeOf((*discord.Embed)(nil))
|
||||
typeSend = reflect.TypeOf((*api.SendMessageData)(nil))
|
||||
|
||||
typeSubcmd = reflect.TypeOf((*Subcommand)(nil))
|
||||
|
||||
typeIError = reflect.TypeOf((*error)(nil)).Elem()
|
||||
typeIManP = reflect.TypeOf((*ManualParser)(nil)).Elem()
|
||||
typeICusP = reflect.TypeOf((*CustomParser)(nil)).Elem()
|
||||
typeIParser = reflect.TypeOf((*Parser)(nil)).Elem()
|
||||
typeIUsager = reflect.TypeOf((*Usager)(nil)).Elem()
|
||||
typeSetupFn = methodType((*CanSetup)(nil), "Setup")
|
||||
typeHelpFn = methodType((*CanHelp)(nil), "Help")
|
||||
)
|
||||
|
||||
func methodType(iface interface{}, name string) reflect.Type {
|
||||
|
|
|
@ -64,8 +64,8 @@ type UserFlags uint32
|
|||
const NoFlag UserFlags = 0
|
||||
|
||||
const (
|
||||
DiscordEmployee UserFlags = 1 << iota
|
||||
DiscordPartner
|
||||
Employee UserFlags = 1 << iota
|
||||
Partner
|
||||
HypeSquadEvents
|
||||
BugHunterLvl1
|
||||
_
|
||||
|
|
|
@ -36,16 +36,16 @@ var (
|
|||
ErrWSMaxTries = errors.New("max tries reached")
|
||||
)
|
||||
|
||||
// GatewayBotData contains the GatewayURL as well as extra metadata on how to
|
||||
// BotData contains the GatewayURL as well as extra metadata on how to
|
||||
// shard bots.
|
||||
type GatewayBotData struct {
|
||||
type BotData struct {
|
||||
URL string `json:"url"`
|
||||
Shards int `json:"shards,omitempty"`
|
||||
StartLimit *SessionStartLimit `json:"session_start_limit"`
|
||||
}
|
||||
|
||||
// SessionStartLimit is the information on the current session start limit. It's
|
||||
// used in GatewayBotData.
|
||||
// used in BotData.
|
||||
type SessionStartLimit struct {
|
||||
Total int `json:"total"`
|
||||
Remaining int `json:"remaining"`
|
||||
|
@ -54,7 +54,7 @@ type SessionStartLimit struct {
|
|||
|
||||
// URL asks Discord for a Websocket URL to the Gateway.
|
||||
func URL() (string, error) {
|
||||
var g GatewayBotData
|
||||
var g BotData
|
||||
|
||||
return g.URL, httputil.NewClient().RequestJSON(
|
||||
&g, "GET",
|
||||
|
@ -64,8 +64,8 @@ func URL() (string, error) {
|
|||
|
||||
// BotURL fetches the Gateway URL along with extra metadata. The token
|
||||
// passed in will NOT be prefixed with Bot.
|
||||
func BotURL(token string) (*GatewayBotData, error) {
|
||||
var g *GatewayBotData
|
||||
func BotURL(token string) (*BotData, error) {
|
||||
var g *BotData
|
||||
|
||||
return g, httputil.NewClient().RequestJSON(
|
||||
&g, "GET",
|
||||
|
@ -214,7 +214,7 @@ func (g *Gateway) Reconnect() {
|
|||
|
||||
// ReconnectCtx attempts to reconnect until context expires. If context cannot
|
||||
// expire, then the gateway will try to reconnect forever.
|
||||
func (g *Gateway) ReconnectCtx(ctx context.Context) error {
|
||||
func (g *Gateway) ReconnectCtx(ctx context.Context) (err error) {
|
||||
wsutil.WSDebug("Reconnecting...")
|
||||
|
||||
// Guarantee the gateway is already closed. Ignore its error, as we're
|
||||
|
@ -222,18 +222,27 @@ func (g *Gateway) ReconnectCtx(ctx context.Context) error {
|
|||
g.Close()
|
||||
|
||||
for i := 1; ; i++ {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return err
|
||||
default:
|
||||
}
|
||||
|
||||
wsutil.WSDebug("Trying to dial, attempt", i)
|
||||
|
||||
// Condition: err == ErrInvalidSession:
|
||||
// If the connection is rate limited (documented behavior):
|
||||
// https://discordapp.com/developers/docs/topics/gateway#rate-limiting
|
||||
|
||||
if err := g.OpenContext(ctx); err != nil {
|
||||
return errors.Wrap(err, "failed to open gateway")
|
||||
// make sure we don't overwrite our last error
|
||||
if err = g.OpenContext(ctx); err != nil {
|
||||
g.ErrorLog(err)
|
||||
continue
|
||||
}
|
||||
|
||||
wsutil.WSDebug("Started after attempt:", i)
|
||||
return nil
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,7 +255,7 @@ func (g *Gateway) Open() error {
|
|||
return g.OpenContext(ctx)
|
||||
}
|
||||
|
||||
// OpenContext connects to the Websocket and authenticates it. Yuo should
|
||||
// OpenContext connects to the Websocket and authenticates it. You should
|
||||
// usually use this function over Start(). The given context provides
|
||||
// cancellation and timeout.
|
||||
func (g *Gateway) OpenContext(ctx context.Context) error {
|
||||
|
|
|
@ -84,7 +84,7 @@ func (g *Gateway) HandleOP(op *wsutil.OP) error {
|
|||
fn, ok := EventCreator[op.EventName]
|
||||
if !ok {
|
||||
return fmt.Errorf(
|
||||
"Unknown event %s: %s",
|
||||
"unknown event %s: %s",
|
||||
op.EventName, string(op.Data),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ type UserSettings struct {
|
|||
DeveloperMode bool `json:"developer_mode"`
|
||||
DetectPlatformAccounts bool `json:"detect_platform_accounts"`
|
||||
StreamNotification bool `json:"stream_notification_enabled"`
|
||||
AccessibilityDetection bool `json:"allow_accessbility_detection"`
|
||||
AccessibilityDetection bool `json:"allow_accessibility_detection"`
|
||||
ContactSync bool `json:"contact_sync_enabled"`
|
||||
NativePhoneIntegration bool `json:"native_phone_integration_enabled"`
|
||||
|
||||
|
@ -71,10 +71,10 @@ type UserSettings struct {
|
|||
type UserGuildSettings struct {
|
||||
GuildID discord.GuildID `json:"guild_id"`
|
||||
|
||||
SupressEveryone bool `json:"suppress_everyone"`
|
||||
SupressRoles bool `json:"suppress_roles"`
|
||||
Muted bool `json:"muted"`
|
||||
MobilePush bool `json:"mobile_push"`
|
||||
SuppressEveryone bool `json:"suppress_everyone"`
|
||||
SuppressRoles bool `json:"suppress_roles"`
|
||||
Muted bool `json:"muted"`
|
||||
MobilePush bool `json:"mobile_push"`
|
||||
|
||||
MessageNotifications UserNotification `json:"message_notifications"`
|
||||
ChannelOverrides []SettingsChannelOverride `json:"channel_overrides"`
|
||||
|
|
|
@ -83,7 +83,7 @@ type State struct {
|
|||
// List of channels with few messages, so it doesn't bother hitting the API
|
||||
// again.
|
||||
fewMessages map[discord.ChannelID]struct{}
|
||||
fewMutex sync.Mutex
|
||||
fewMutex *sync.Mutex
|
||||
|
||||
// unavailableGuilds is a set of discord.GuildIDs of guilds that became
|
||||
// unavailable when already connected to the gateway, i.e. sent in a
|
||||
|
@ -129,7 +129,7 @@ func NewFromSession(s *session.Session, store Store) (*State, error) {
|
|||
Handler: handler.New(),
|
||||
StateLog: func(err error) {},
|
||||
fewMessages: map[discord.ChannelID]struct{}{},
|
||||
fewMutex: sync.Mutex{},
|
||||
fewMutex: new(sync.Mutex),
|
||||
unavailableGuilds: moreatomic.NewGuildIDSet(),
|
||||
unreadyGuilds: moreatomic.NewGuildIDSet(),
|
||||
}
|
||||
|
|
|
@ -180,7 +180,7 @@ func (s *State) onEvent(iface interface{}) {
|
|||
case *gateway.MessageDeleteBulkEvent:
|
||||
for _, id := range ev.IDs {
|
||||
if err := s.Store.MessageRemove(ev.ChannelID, id); err != nil {
|
||||
s.stateErr(err, "failed to delete bulk meessages in state")
|
||||
s.stateErr(err, "failed to delete bulk messages in state")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -158,9 +158,9 @@ func (c *Conn) readLoop() {
|
|||
}
|
||||
|
||||
func (c *Conn) writeLoop() {
|
||||
// Closig c.writes would break the loop immediately.
|
||||
for bytes := range c.writes {
|
||||
c.errors <- c.Conn.WriteMessage(websocket.TextMessage, bytes)
|
||||
// Closing c.writes would break the loop immediately.
|
||||
for b := range c.writes {
|
||||
c.errors <- c.Conn.WriteMessage(websocket.TextMessage, b)
|
||||
}
|
||||
|
||||
// Quick deadline:
|
||||
|
|
|
@ -54,7 +54,7 @@ func AssertEvent(ev Event, code OPCode, v interface{}) (*OP, error) {
|
|||
|
||||
if op.Code != code {
|
||||
return op, fmt.Errorf(
|
||||
"Unexpected OP Code: %d, expected %d (%s)",
|
||||
"unexpected OP Code: %d, expected %d (%s)",
|
||||
op.Code, code, op.Data,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ from the **Discord Gateway**.
|
|||
which will be used to create a new `*heart.PacemakerLoop` and start sending heartbeats to the **Discord Voice Gateway**.
|
||||
* Afterwards, an [Identify Command](https://discordapp.com/developers/docs/topics/voice-connections#establishing-a-voice-websocket-connection-example-voice-identify-payload)
|
||||
or [Resume Command](https://discordapp.com/developers/docs/topics/voice-connections#resuming-voice-connection-example-resume-connection-payload)
|
||||
is sent to the **Discord Voice Gateway** depending on whether or not the **library** is reconnecting.
|
||||
is sent to the **Discord Voice Gateway** depending on whether the **library** is reconnecting.
|
||||
|
||||
---
|
||||
|
||||
|
|
Loading…
Reference in a new issue