Compare commits
2 Commits
356589df17
...
8f548d2607
Author | SHA1 | Date |
---|---|---|
Cléo Rebert | 8f548d2607 | |
Cléo Rebert | d36955acea |
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
|
@ -16,7 +17,6 @@ import (
|
|||
"github.com/diamondburned/arikawa/v3/voice"
|
||||
"github.com/diamondburned/arikawa/v3/voice/udp"
|
||||
"github.com/diamondburned/oggreader"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package cmdroute
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/api"
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// BulkCommandsOverwriter is an interface that allows to overwrite all commands
|
||||
|
@ -20,9 +21,9 @@ var _ BulkCommandsOverwriter = (*api.Client)(nil)
|
|||
func OverwriteCommands(client BulkCommandsOverwriter, cmds []api.CreateCommandData) error {
|
||||
app, err := client.CurrentApplication()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot get current app ID")
|
||||
return fmt.Errorf("cannot get current app ID: %w", err)
|
||||
}
|
||||
|
||||
_, err = client.BulkOverwriteCommands(app.ID, cmds)
|
||||
return errors.Wrap(err, "cannot overwrite commands")
|
||||
return fmt.Errorf("cannot overwrite commands: %w", err)
|
||||
}
|
||||
|
|
|
@ -3,11 +3,11 @@ package api
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/utils/json"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var ErrInvalidImageCT = errors.New("unknown image content-type")
|
||||
|
@ -43,11 +43,11 @@ func DecodeImage(data []byte) (*Image, error) {
|
|||
}
|
||||
|
||||
if !bytes.HasPrefix(parts[0], []byte("data:")) {
|
||||
return nil, errors.Wrap(ErrInvalidImageData, "invalid header")
|
||||
return nil, fmt.Errorf("invalid header: %w", ErrInvalidImageData)
|
||||
}
|
||||
|
||||
if !bytes.HasPrefix(parts[1], []byte("base64,")) {
|
||||
return nil, errors.Wrap(ErrInvalidImageData, "invalid base64")
|
||||
return nil, fmt.Errorf("invalid base64: %w", ErrInvalidImageData)
|
||||
}
|
||||
|
||||
var b64 = parts[1][len("base64,"):]
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/utils/json/option"
|
||||
|
@ -105,10 +103,9 @@ func (d InteractionResponseData) WriteMultipart(body *multipart.Writer) error {
|
|||
//
|
||||
// The following types implement this interface:
|
||||
//
|
||||
// - AutocompleteStringChoices
|
||||
// - AutocompleteIntegerChoices
|
||||
// - AutocompleteNumberChoices
|
||||
//
|
||||
// - AutocompleteStringChoices
|
||||
// - AutocompleteIntegerChoices
|
||||
// - AutocompleteNumberChoices
|
||||
type AutocompleteChoices interface {
|
||||
choices()
|
||||
}
|
||||
|
@ -158,7 +155,7 @@ func (c *Client) RespondInteraction(
|
|||
|
||||
if resp.Data.AllowedMentions != nil {
|
||||
if err := resp.Data.AllowedMentions.Verify(); err != nil {
|
||||
return errors.Wrap(err, "allowedMentions error")
|
||||
return fmt.Errorf("allowedMentions error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,7 +163,7 @@ func (c *Client) RespondInteraction(
|
|||
sum := 0
|
||||
for i, embed := range *resp.Data.Embeds {
|
||||
if err := embed.Validate(); err != nil {
|
||||
return errors.Wrap(err, "embed error at "+strconv.Itoa(i))
|
||||
return fmt.Errorf("embed error at %d: %w", i, err)
|
||||
}
|
||||
sum += embed.Length()
|
||||
if sum > 6000 {
|
||||
|
@ -225,7 +222,7 @@ func (c *Client) EditInteractionResponse(
|
|||
|
||||
if data.AllowedMentions != nil {
|
||||
if err := data.AllowedMentions.Verify(); err != nil {
|
||||
return nil, errors.Wrap(err, "allowedMentions error")
|
||||
return nil, fmt.Errorf("allowedMentions error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,7 +230,7 @@ func (c *Client) EditInteractionResponse(
|
|||
sum := 0
|
||||
for i, e := range *data.Embeds {
|
||||
if err := e.Validate(); err != nil {
|
||||
return nil, errors.Wrap(err, "embed error")
|
||||
return nil, fmt.Errorf("embed error: %w", err)
|
||||
}
|
||||
sum += e.Length()
|
||||
if sum > 6000 {
|
||||
|
@ -275,7 +272,7 @@ func (c *Client) FollowUpInteraction(
|
|||
|
||||
if data.AllowedMentions != nil {
|
||||
if err := data.AllowedMentions.Verify(); err != nil {
|
||||
return nil, errors.Wrap(err, "allowedMentions error")
|
||||
return nil, fmt.Errorf("allowedMentions error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,7 +280,7 @@ func (c *Client) FollowUpInteraction(
|
|||
sum := 0
|
||||
for i, embed := range *data.Embeds {
|
||||
if err := embed.Validate(); err != nil {
|
||||
return nil, errors.Wrap(err, "embed error at "+strconv.Itoa(i))
|
||||
return nil, fmt.Errorf("embed error at %d: %w", i, err)
|
||||
}
|
||||
sum += embed.Length()
|
||||
if sum > 6000 {
|
||||
|
@ -305,7 +302,7 @@ func (c *Client) EditInteractionFollowup(
|
|||
|
||||
if data.AllowedMentions != nil {
|
||||
if err := data.AllowedMentions.Verify(); err != nil {
|
||||
return nil, errors.Wrap(err, "allowedMentions error")
|
||||
return nil, fmt.Errorf("allowedMentions error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,7 +310,7 @@ func (c *Client) EditInteractionFollowup(
|
|||
sum := 0
|
||||
for i, e := range *data.Embeds {
|
||||
if err := e.Validate(); err != nil {
|
||||
return nil, errors.Wrap(err, "embed error")
|
||||
return nil, fmt.Errorf("embed error: %w", err)
|
||||
}
|
||||
sum += e.Length()
|
||||
if sum > 6000 {
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/internal/intmath"
|
||||
|
@ -370,7 +368,7 @@ func (c *Client) EditMessageComplex(
|
|||
|
||||
if data.AllowedMentions != nil {
|
||||
if err := data.AllowedMentions.Verify(); err != nil {
|
||||
return nil, errors.Wrap(err, "allowedMentions error")
|
||||
return nil, fmt.Errorf("allowedMentions error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,7 +376,7 @@ func (c *Client) EditMessageComplex(
|
|||
sum := 0
|
||||
for i, embed := range *data.Embeds {
|
||||
if err := embed.Validate(); err != nil {
|
||||
return nil, errors.Wrap(err, "embed error at "+strconv.Itoa(i))
|
||||
return nil, fmt.Errorf("embed error at %d: %w", i, err)
|
||||
}
|
||||
sum += embed.Length()
|
||||
if sum > 6000 {
|
||||
|
|
|
@ -2,6 +2,8 @@ package rate
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -10,7 +12,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/internal/moreatomic"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ExtraDelay because Discord is trash. I've seen this in both litcord and
|
||||
|
@ -209,7 +210,7 @@ func (l *Limiter) Release(path string, headers http.Header) error {
|
|||
case retryAfter != "":
|
||||
i, err := strconv.Atoi(retryAfter)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "invalid retryAfter %q", retryAfter)
|
||||
return fmt.Errorf("invalid retryAfter %q: %w", retryAfter, err)
|
||||
}
|
||||
|
||||
at := time.Now().Add(time.Duration(i) * time.Second)
|
||||
|
@ -223,7 +224,7 @@ func (l *Limiter) Release(path string, headers http.Header) error {
|
|||
case reset != "":
|
||||
unix, err := strconv.ParseFloat(reset, 64)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "invalid reset "+reset)
|
||||
return fmt.Errorf("invalid reset %q: %w", reset, err)
|
||||
}
|
||||
|
||||
sec := int64(unix)
|
||||
|
@ -235,7 +236,7 @@ func (l *Limiter) Release(path string, headers http.Header) error {
|
|||
if remaining != "" {
|
||||
u, err := strconv.ParseUint(remaining, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "invalid remaining "+remaining)
|
||||
return fmt.Errorf("invalid remaining %q: %w", remaining, err)
|
||||
}
|
||||
|
||||
b.remaining = u
|
||||
|
|
17
api/send.go
17
api/send.go
|
@ -1,10 +1,9 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/utils/json/option"
|
||||
|
@ -15,7 +14,7 @@ const AttachmentSpoilerPrefix = "SPOILER_"
|
|||
|
||||
// AllowedMentions is a allowlist of mentions for a message.
|
||||
//
|
||||
// Allowlists
|
||||
// # Allowlists
|
||||
//
|
||||
// Roles and Users are slices that act as allowlists for IDs that are allowed
|
||||
// to be mentioned. For example, if only 1 ID is provided in Users, then only
|
||||
|
@ -25,7 +24,7 @@ const AttachmentSpoilerPrefix = "SPOILER_"
|
|||
// If Parse is an empty slice and both Users and Roles are empty slices, then no
|
||||
// mentions will be parsed.
|
||||
//
|
||||
// Constraints
|
||||
// # Constraints
|
||||
//
|
||||
// If the Users slice is not empty, then Parse must not have AllowUserMention.
|
||||
// Likewise, if the Roles slice is not empty, then Parse must not have
|
||||
|
@ -65,10 +64,10 @@ const (
|
|||
// AllowedMentions' documentation. This will be called on SendMessageComplex.
|
||||
func (am AllowedMentions) Verify() error {
|
||||
if len(am.Roles) > 100 {
|
||||
return errors.Errorf("roles slice length %d is over 100", len(am.Roles))
|
||||
return fmt.Errorf("roles slice length %d is over 100", len(am.Roles))
|
||||
}
|
||||
if len(am.Users) > 100 {
|
||||
return errors.Errorf("users slice length %d is over 100", len(am.Users))
|
||||
return fmt.Errorf("users slice length %d is over 100", len(am.Users))
|
||||
}
|
||||
|
||||
for _, allowed := range am.Parse {
|
||||
|
@ -160,14 +159,14 @@ func (c *Client) SendMessageComplex(
|
|||
|
||||
if data.AllowedMentions != nil {
|
||||
if err := data.AllowedMentions.Verify(); err != nil {
|
||||
return nil, errors.Wrap(err, "allowedMentions error")
|
||||
return nil, fmt.Errorf("allowedMentions error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
sum := 0
|
||||
for i, embed := range data.Embeds {
|
||||
if err := embed.Validate(); err != nil {
|
||||
return nil, errors.Wrap(err, "embed error at "+strconv.Itoa(i))
|
||||
return nil, fmt.Errorf("embed error at %d: %w", i, err)
|
||||
}
|
||||
sum += embed.Length()
|
||||
if sum > 6000 {
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"crypto/ed25519"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
|
@ -12,7 +14,6 @@ import (
|
|||
|
||||
"github.com/diamondburned/arikawa/v3/api"
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func writeError(w http.ResponseWriter, code int, err error) {
|
||||
|
@ -94,7 +95,7 @@ type InteractionServer struct {
|
|||
func NewInteractionServer(pubkey string, handler InteractionHandler) (*InteractionServer, error) {
|
||||
pubkeyB, err := hex.DecodeString(pubkey)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot decode hex pubkey")
|
||||
return nil, fmt.Errorf("cannot decode hex pubkey: %w", err)
|
||||
}
|
||||
|
||||
s := InteractionServer{
|
||||
|
@ -125,7 +126,7 @@ func (s *InteractionServer) handle(w http.ResponseWriter, r *http.Request) {
|
|||
var ev discord.InteractionEvent
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&ev); err != nil {
|
||||
s.ErrorFunc(w, r, 400, errors.Wrap(err, "cannot decode interaction body"))
|
||||
s.ErrorFunc(w, r, 400, fmt.Errorf("cannot decode interaction : %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -165,7 +166,7 @@ func (s *InteractionServer) withVerification(next http.Handler) http.Handler {
|
|||
|
||||
sig, err := hex.DecodeString(signature)
|
||||
if err != nil {
|
||||
s.ErrorFunc(w, r, 400, errors.Wrap(err, "X-Signature-Ed25519 is not valid hex-encoded"))
|
||||
s.ErrorFunc(w, r, 400, fmt.Errorf("X-Signature-Ed25519 is not valid hex-encoded: %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -185,7 +186,7 @@ func (s *InteractionServer) withVerification(next http.Handler) http.Handler {
|
|||
msg.WriteString(timestamp)
|
||||
|
||||
if _, err := io.Copy(&msg, r.Body); err != nil {
|
||||
s.ErrorFunc(w, r, 500, errors.Wrap(err, "cannot read body"))
|
||||
s.ErrorFunc(w, r, 500, fmt.Errorf("cannot read body: %w", err))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -4,13 +4,13 @@ package webhook
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/api"
|
||||
"github.com/diamondburned/arikawa/v3/api/rate"
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
|
@ -34,7 +34,7 @@ func ParseURL(webhookURL string) (id discord.WebhookID, token string, err error)
|
|||
|
||||
idInt, err := strconv.ParseUint(matches[1], 10, 64)
|
||||
if err != nil {
|
||||
return 0, "", errors.Wrap(err, "failed to parse webhook ID")
|
||||
return 0, "", fmt.Errorf("failed to parse webhook ID: %w", err)
|
||||
}
|
||||
|
||||
return discord.WebhookID(idInt), matches[2], nil
|
||||
|
@ -222,14 +222,14 @@ func (c *Client) execute(data ExecuteData, wait bool) (*discord.Message, error)
|
|||
|
||||
if data.AllowedMentions != nil {
|
||||
if err := data.AllowedMentions.Verify(); err != nil {
|
||||
return nil, errors.Wrap(err, "allowedMentions error")
|
||||
return nil, fmt.Errorf("allowedMentions error: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
sum := 0
|
||||
for i, embed := range data.Embeds {
|
||||
if err := embed.Validate(); err != nil {
|
||||
return nil, errors.Wrap(err, "embed error at "+strconv.Itoa(i))
|
||||
return nil, fmt.Errorf("embed error at %d: %w", i, err)
|
||||
}
|
||||
sum += embed.Length()
|
||||
if sum > 6000 {
|
||||
|
@ -284,14 +284,14 @@ type EditMessageData struct {
|
|||
func (c *Client) EditMessage(messageID discord.MessageID, data EditMessageData) (*discord.Message, error) {
|
||||
if data.AllowedMentions != nil {
|
||||
if err := data.AllowedMentions.Verify(); err != nil {
|
||||
return nil, errors.Wrap(err, "allowedMentions error")
|
||||
return nil, fmt.Errorf("allowedMentions error: %w", err)
|
||||
}
|
||||
}
|
||||
if data.Embeds != nil {
|
||||
sum := 0
|
||||
for _, e := range *data.Embeds {
|
||||
if err := e.Validate(); err != nil {
|
||||
return nil, errors.Wrap(err, "embed error")
|
||||
return nil, fmt.Errorf("embed error: %w", err)
|
||||
}
|
||||
sum += e.Length()
|
||||
if sum > 6000 {
|
||||
|
|
15
arikawa.go
15
arikawa.go
|
@ -1,26 +1,26 @@
|
|||
// Package arikawa contains a set of modular packages that allows you to make a
|
||||
// Discord bot or any type of session (OAuth unsupported).
|
||||
//
|
||||
// Session
|
||||
// # Session
|
||||
//
|
||||
// Package session is the most simple abstraction, which combines the API
|
||||
// package and the Gateway websocket package together into one. This could be
|
||||
// used for minimal bots that only use gateway events and such.
|
||||
//
|
||||
// State
|
||||
// # State
|
||||
//
|
||||
// Package state abstracts on top of session and provides a local cache of API
|
||||
// calls and events. Bots that either don't need a command router or already has
|
||||
// its own should use this package.
|
||||
//
|
||||
// Bot
|
||||
// # Bot
|
||||
//
|
||||
// Package bot abstracts on top of state and provides a command router based on
|
||||
// Go code. This is similar to discord.py's API, only it's Go and there's no
|
||||
// optional arguments (yet, although it could be worked around). Most bots are
|
||||
// recommended to use this package, as it's the easiest way to make a bot.
|
||||
//
|
||||
// Voice
|
||||
// # Voice
|
||||
//
|
||||
// Package voice provides an abstraction on top of State and adds voice support.
|
||||
// This allows bots to join voice channels and talk. The package uses an
|
||||
|
@ -29,12 +29,11 @@
|
|||
package arikawa
|
||||
|
||||
import (
|
||||
// Low level packages.
|
||||
_ "github.com/diamondburned/arikawa/v3/api"
|
||||
_ "github.com/diamondburned/arikawa/v3/gateway"
|
||||
// Packages that most should use.
|
||||
_ "github.com/diamondburned/arikawa/v3/session"
|
||||
_ "github.com/diamondburned/arikawa/v3/state"
|
||||
_ "github.com/diamondburned/arikawa/v3/voice"
|
||||
|
||||
// Low level packages.
|
||||
_ "github.com/diamondburned/arikawa/v3/api"
|
||||
_ "github.com/diamondburned/arikawa/v3/gateway"
|
||||
)
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package discord
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/utils/json"
|
||||
)
|
||||
|
||||
|
@ -150,29 +149,28 @@ type AuditEntryInfo struct {
|
|||
// AuditLogChange is a single key type to changed value audit log entry. The
|
||||
// type can be found in the key's comment. Values can be nil.
|
||||
//
|
||||
// What
|
||||
// # What
|
||||
//
|
||||
// I'm glad to see the same reaction that I had on you. In short, in this
|
||||
// struct, the Key dictates what type NewValue and OldValue will have. They will
|
||||
// always be the same type, but I will leave that as JSON for the user.
|
||||
//
|
||||
// Usage
|
||||
// # Usage
|
||||
//
|
||||
// The usage of this is pretty simple, as AuditLogChange already has a
|
||||
// convenient method to use. Here's an example on how to do "owner_id":
|
||||
//
|
||||
// if change.Key != discord.AuditGuildOwnerID {
|
||||
// return errors.New("not owner ID")
|
||||
// }
|
||||
// if change.Key != discord.AuditGuildOwnerID {
|
||||
// return errors.New("not owner ID")
|
||||
// }
|
||||
//
|
||||
// // We know these are UserIDs because the comment said so for AuditGuildOwnerID.
|
||||
// var oldOwnerID, newOwnerID discord.UserID
|
||||
// if err := change.UnmarshalValues(&oldOwnerID, &newOwnerID); err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// log.Println("Transferred ownership from user", oldOwnerID, "to", newOwnerID)
|
||||
// // We know these are UserIDs because the comment said so for AuditGuildOwnerID.
|
||||
// var oldOwnerID, newOwnerID discord.UserID
|
||||
// if err := change.UnmarshalValues(&oldOwnerID, &newOwnerID); err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// log.Println("Transferred ownership from user", oldOwnerID, "to", newOwnerID)
|
||||
type AuditLogChange struct {
|
||||
// Key is the name of audit log change key.
|
||||
Key AuditLogChangeKey `json:"key"`
|
||||
|
@ -186,10 +184,10 @@ type AuditLogChange struct {
|
|||
// interfaces.
|
||||
func (a AuditLogChange) UnmarshalValues(old, new interface{}) error {
|
||||
if err := a.NewValue.UnmarshalTo(new); err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal old value")
|
||||
return fmt.Errorf("failed to unmarshal old value: %w", err)
|
||||
}
|
||||
if err := a.OldValue.UnmarshalTo(old); err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal new value")
|
||||
return fmt.Errorf("failed to unmarshal new value: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
|
||||
"github.com/diamondburned/arikawa/v3/utils/json"
|
||||
"github.com/diamondburned/arikawa/v3/utils/json/option"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// CommandType is the type of the command, which describes the intended
|
||||
|
@ -257,7 +256,7 @@ func (u *UnknownCommandOption) UnmarshalJSON(b []byte) error {
|
|||
type unknown UnknownCommandOption
|
||||
|
||||
if err := json.Unmarshal(b, (*unknown)(u)); err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal unknown")
|
||||
return fmt.Errorf("failed to unmarshal unknown: %w", err)
|
||||
}
|
||||
|
||||
switch u.Type() {
|
||||
|
@ -289,7 +288,7 @@ func (u *UnknownCommandOption) UnmarshalJSON(b []byte) error {
|
|||
}
|
||||
|
||||
if err := json.Unmarshal(b, u.data); err != nil {
|
||||
return errors.Wrapf(err, "failed to unmarshal type %d", u.Type())
|
||||
return fmt.Errorf("failed to unmarshal type %d: %w", u.Type(), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -319,18 +318,17 @@ const (
|
|||
//
|
||||
// The following types implement this interface:
|
||||
//
|
||||
// - *SubcommandGroupOption
|
||||
// - *SubcommandOption
|
||||
// - *StringOption
|
||||
// - *IntegerOption
|
||||
// - *BooleanOption
|
||||
// - *UserOption
|
||||
// - *ChannelOption
|
||||
// - *RoleOption
|
||||
// - *MentionableOption
|
||||
// - *NumberOption
|
||||
// - *AttachmentOption
|
||||
//
|
||||
// - *SubcommandGroupOption
|
||||
// - *SubcommandOption
|
||||
// - *StringOption
|
||||
// - *IntegerOption
|
||||
// - *BooleanOption
|
||||
// - *UserOption
|
||||
// - *ChannelOption
|
||||
// - *RoleOption
|
||||
// - *MentionableOption
|
||||
// - *NumberOption
|
||||
// - *AttachmentOption
|
||||
type CommandOption interface {
|
||||
Name() string
|
||||
Type() CommandOptionType
|
||||
|
@ -424,16 +422,15 @@ func (s *SubcommandOption) UnmarshalJSON(b []byte) error {
|
|||
//
|
||||
// The following types implement this interface:
|
||||
//
|
||||
// - *StringOption
|
||||
// - *IntegerOption
|
||||
// - *BooleanOption
|
||||
// - *UserOption
|
||||
// - *ChannelOption
|
||||
// - *RoleOption
|
||||
// - *MentionableOption
|
||||
// - *NumberOption
|
||||
// - *AttachmentOption
|
||||
//
|
||||
// - *StringOption
|
||||
// - *IntegerOption
|
||||
// - *BooleanOption
|
||||
// - *UserOption
|
||||
// - *ChannelOption
|
||||
// - *RoleOption
|
||||
// - *MentionableOption
|
||||
// - *NumberOption
|
||||
// - *AttachmentOption
|
||||
type CommandOptionValue interface {
|
||||
CommandOption
|
||||
_val()
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
|
||||
"github.com/diamondburned/arikawa/v3/internal/rfutil"
|
||||
"github.com/diamondburned/arikawa/v3/utils/json"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ComponentType is the type of a component.
|
||||
|
@ -78,14 +77,14 @@ func (c *ContainerComponents) Find(customID ComponentID) Component {
|
|||
// matching custom ID. The struct must be a flat struct that lists all the
|
||||
// components it needs using the custom ID.
|
||||
//
|
||||
// Supported Types
|
||||
// # Supported Types
|
||||
//
|
||||
// The following types are supported:
|
||||
//
|
||||
// - string (SelectComponent if range = [n, 1], TextInputComponent)
|
||||
// - int*, uint*, float* (uses Parse{Int,Uint,Float}, SelectComponent if range = [n, 1], TextInputComponent)
|
||||
// - bool (ButtonComponent or any component, true if present)
|
||||
// - []string (SelectComponent)
|
||||
// - string (SelectComponent if range = [n, 1], TextInputComponent)
|
||||
// - int*, uint*, float* (uses Parse{Int,Uint,Float}, SelectComponent if range = [n, 1], TextInputComponent)
|
||||
// - bool (ButtonComponent or any component, true if present)
|
||||
// - []string (SelectComponent)
|
||||
//
|
||||
// Any types that are derived from any of the above built-in types are also
|
||||
// supported.
|
||||
|
@ -248,15 +247,14 @@ func (c *ContainerComponents) UnmarshalJSON(b []byte) error {
|
|||
//
|
||||
// The following types satisfy this interface:
|
||||
//
|
||||
// - *ActionRowComponent
|
||||
// - *ButtonComponent
|
||||
// - *StringSelectComponent
|
||||
// - *TextInputComponent
|
||||
// - *UserSelectComponent
|
||||
// - *RoleSelectComponent
|
||||
// - *MentionableSelectComponent
|
||||
// - *ChannelSelectComponent
|
||||
//
|
||||
// - *ActionRowComponent
|
||||
// - *ButtonComponent
|
||||
// - *StringSelectComponent
|
||||
// - *TextInputComponent
|
||||
// - *UserSelectComponent
|
||||
// - *RoleSelectComponent
|
||||
// - *MentionableSelectComponent
|
||||
// - *ChannelSelectComponent
|
||||
type Component interface {
|
||||
// Type returns the type of the underlying component.
|
||||
Type() ComponentType
|
||||
|
@ -269,14 +267,13 @@ type Component interface {
|
|||
//
|
||||
// The following types satisfy this interface:
|
||||
//
|
||||
// - *ButtonComponent
|
||||
// - *SelectComponent
|
||||
// - *TextInputComponent
|
||||
// - *UserSelectComponent
|
||||
// - *RoleSelectComponent
|
||||
// - *MentionableSelectComponent
|
||||
// - *ChannelSelectComponent
|
||||
//
|
||||
// - *ButtonComponent
|
||||
// - *SelectComponent
|
||||
// - *TextInputComponent
|
||||
// - *UserSelectComponent
|
||||
// - *RoleSelectComponent
|
||||
// - *MentionableSelectComponent
|
||||
// - *ChannelSelectComponent
|
||||
type InteractiveComponent interface {
|
||||
Component
|
||||
// ID returns the ID of the underlying component.
|
||||
|
@ -290,8 +287,7 @@ type InteractiveComponent interface {
|
|||
//
|
||||
// The following types satisfy this interface:
|
||||
//
|
||||
// - *ActionRowComponent
|
||||
//
|
||||
// - *ActionRowComponent
|
||||
type ContainerComponent interface {
|
||||
Component
|
||||
_ctn()
|
||||
|
@ -305,7 +301,7 @@ func ParseComponent(b []byte) (Component, error) {
|
|||
}
|
||||
|
||||
if err := json.Unmarshal(b, &t); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal component type")
|
||||
return nil, fmt.Errorf("failed to unmarshal component type: %w", err)
|
||||
}
|
||||
|
||||
var c Component
|
||||
|
@ -324,7 +320,7 @@ func ParseComponent(b []byte) (Component, error) {
|
|||
}
|
||||
|
||||
if err := json.Unmarshal(b, c); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal component body")
|
||||
return nil, fmt.Errorf("failed to unmarshal component body: %w", err)
|
||||
}
|
||||
|
||||
return c, nil
|
||||
|
@ -342,14 +338,13 @@ type ActionRowComponent []InteractiveComponent
|
|||
//
|
||||
// Here's an example of how to use it:
|
||||
//
|
||||
// discord.Components(
|
||||
// discord.TextButtonComponent("Hello, world!"),
|
||||
// discord.Components(
|
||||
// discord.TextButtonComponent("Hello!"),
|
||||
// discord.TextButtonComponent("Delete."),
|
||||
// ),
|
||||
// )
|
||||
//
|
||||
// discord.Components(
|
||||
// discord.TextButtonComponent("Hello, world!"),
|
||||
// discord.Components(
|
||||
// discord.TextButtonComponent("Hello!"),
|
||||
// discord.TextButtonComponent("Delete."),
|
||||
// ),
|
||||
// )
|
||||
func Components(components ...Component) ContainerComponents {
|
||||
new := make([]ContainerComponent, len(components))
|
||||
|
||||
|
@ -421,7 +416,7 @@ func (a *ActionRowComponent) UnmarshalJSON(b []byte) error {
|
|||
for i, b := range row.Components {
|
||||
p, err := ParseComponent(b)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse component %d", i)
|
||||
return fmt.Errorf("failed to parse component %d: %w", i, err)
|
||||
}
|
||||
|
||||
ic, ok := p.(InteractiveComponent)
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
package discord
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/internal/rfutil"
|
||||
"github.com/diamondburned/arikawa/v3/utils/json"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InteractionEvent describes the full incoming interaction event. It may be a
|
||||
|
@ -93,7 +93,7 @@ func (e *InteractionEvent) UnmarshalJSON(b []byte) error {
|
|||
case ComponentInteractionType:
|
||||
d, err := ParseComponentInteraction(target.Data)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal component interaction event data")
|
||||
return fmt.Errorf("failed to unmarshal component interaction event data: %w", err)
|
||||
}
|
||||
e.Data = d
|
||||
return nil
|
||||
|
@ -110,7 +110,7 @@ func (e *InteractionEvent) UnmarshalJSON(b []byte) error {
|
|||
}
|
||||
|
||||
if err := json.Unmarshal(target.Data, e.Data); err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal interaction event data")
|
||||
return fmt.Errorf("failed to unmarshal interaction event data: %w", err)
|
||||
}
|
||||
|
||||
return err
|
||||
|
@ -155,17 +155,16 @@ const (
|
|||
//
|
||||
// The following types implement this interface:
|
||||
//
|
||||
// - *PingInteraction
|
||||
// - *AutocompleteInteraction
|
||||
// - *CommandInteraction
|
||||
// - *ModalInteraction
|
||||
// - *StringSelectInteraction (also ComponentInteraction)
|
||||
// - *RoleSelectInteraction (also ComponentInteraction)
|
||||
// - *UserSelectInteraction (also ComponentInteraction)
|
||||
// - *ChannelSelectInteraction (also ComponentInteraction)
|
||||
// - *MentionableSelectInteraction (also ComponentInteraction)
|
||||
// - *ButtonInteraction (also ComponentInteraction)
|
||||
//
|
||||
// - *PingInteraction
|
||||
// - *AutocompleteInteraction
|
||||
// - *CommandInteraction
|
||||
// - *ModalInteraction
|
||||
// - *StringSelectInteraction (also ComponentInteraction)
|
||||
// - *RoleSelectInteraction (also ComponentInteraction)
|
||||
// - *UserSelectInteraction (also ComponentInteraction)
|
||||
// - *ChannelSelectInteraction (also ComponentInteraction)
|
||||
// - *MentionableSelectInteraction (also ComponentInteraction)
|
||||
// - *ButtonInteraction (also ComponentInteraction)
|
||||
type InteractionData interface {
|
||||
InteractionType() InteractionDataType
|
||||
data()
|
||||
|
@ -289,13 +288,12 @@ func (o AutocompleteOption) FloatValue() (float64, error) {
|
|||
//
|
||||
// The following types implement this interface:
|
||||
//
|
||||
// - *StringSelectInteraction
|
||||
// - *ChannelSelectInteraction
|
||||
// - *RoleSelectInteraction
|
||||
// - *UserSelectInteraction
|
||||
// - *MentionableSelectInteraction
|
||||
// - *ButtonInteraction
|
||||
//
|
||||
// - *StringSelectInteraction
|
||||
// - *ChannelSelectInteraction
|
||||
// - *RoleSelectInteraction
|
||||
// - *UserSelectInteraction
|
||||
// - *MentionableSelectInteraction
|
||||
// - *ButtonInteraction
|
||||
type ComponentInteraction interface {
|
||||
InteractionData
|
||||
// ID returns the ID of the component in response. Not all component
|
||||
|
@ -439,7 +437,7 @@ func ParseComponentInteraction(b []byte) (ComponentInteraction, error) {
|
|||
}
|
||||
|
||||
if err := json.Unmarshal(b, &t); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal component interaction header")
|
||||
return nil, fmt.Errorf("failed to unmarshal component interaction header: %w", err)
|
||||
}
|
||||
|
||||
var d ComponentInteraction
|
||||
|
@ -467,7 +465,7 @@ func ParseComponentInteraction(b []byte) (ComponentInteraction, error) {
|
|||
}
|
||||
|
||||
if err := json.Unmarshal(b, d); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal component interaction data")
|
||||
return nil, fmt.Errorf("failed to unmarshal component interaction data: %w", err)
|
||||
}
|
||||
|
||||
return d, nil
|
||||
|
@ -565,20 +563,20 @@ var optionKindMap = map[reflect.Kind]CommandOptionType{
|
|||
// tag with a value "-" is ignored. Fields that aren't found in the list of
|
||||
// options and have a "?" at the end of the "discord" struct tag are ignored.
|
||||
//
|
||||
// Supported Types
|
||||
// # Supported Types
|
||||
//
|
||||
// The following types are supported:
|
||||
//
|
||||
// - ChannelID (ChannelOptionType)
|
||||
// - UserID (UserOptionType)
|
||||
// - RoleID (RoleOptionType)
|
||||
// - Snowflake (MentionableOptionType)
|
||||
// - string (StringOptionType)
|
||||
// - bool (BooleanOptionType)
|
||||
// - int* (int, int8, int16, int32, int64) (NumberOptionType)
|
||||
// - uint* (uint, uint8, uint16, uint32, uint64) (NumberOptionType)
|
||||
// - float* (float32, float64) (NumberOptionType)
|
||||
// - (any struct and struct pointer) (not Discord-type-checked)
|
||||
// - ChannelID (ChannelOptionType)
|
||||
// - UserID (UserOptionType)
|
||||
// - RoleID (RoleOptionType)
|
||||
// - Snowflake (MentionableOptionType)
|
||||
// - string (StringOptionType)
|
||||
// - bool (BooleanOptionType)
|
||||
// - int* (int, int8, int16, int32, int64) (NumberOptionType)
|
||||
// - uint* (uint, uint8, uint16, uint32, uint64) (NumberOptionType)
|
||||
// - float* (float32, float64) (NumberOptionType)
|
||||
// - (any struct and struct pointer) (not Discord-type-checked)
|
||||
//
|
||||
// Any types that are derived from any of the above built-in types are also
|
||||
// supported.
|
||||
|
@ -664,7 +662,7 @@ func unmarshalOptions(find func(string) unmarshalingOption, rv reflect.Value) er
|
|||
|
||||
var snowflake Snowflake
|
||||
if err := option.Value.UnmarshalTo(&snowflake); err != nil {
|
||||
return errors.Wrapf(err, "option %q is not a valid snowflake", name)
|
||||
return fmt.Errorf("option %q is not a valid snowflake: %w", name, err)
|
||||
}
|
||||
|
||||
fieldv.Set(reflect.ValueOf(snowflake).Convert(fieldt))
|
||||
|
@ -681,7 +679,7 @@ func unmarshalOptions(find func(string) unmarshalingOption, rv reflect.Value) er
|
|||
switch fieldk {
|
||||
case reflect.Struct:
|
||||
if err := unmarshalOptions(option.Find, fieldv.Addr()); err != nil {
|
||||
return errors.Wrapf(err, "option %q has invalid suboptions", name)
|
||||
return fmt.Errorf("option %q has invalid suboptions: %w", name, err)
|
||||
}
|
||||
|
||||
case reflect.Bool, reflect.String, reflect.Float32, reflect.Float64,
|
||||
|
@ -690,7 +688,7 @@ func unmarshalOptions(find func(string) unmarshalingOption, rv reflect.Value) er
|
|||
|
||||
v := reflect.New(fieldt)
|
||||
if err := option.Value.UnmarshalTo(v.Interface()); err != nil {
|
||||
return errors.Wrapf(err, "option %q is not a valid %s", name, fieldt)
|
||||
return fmt.Errorf("option %q is not a valid %s: %w", name, fieldt, err)
|
||||
}
|
||||
fieldv.Set(v.Elem())
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ import (
|
|||
"github.com/diamondburned/arikawa/v3/api"
|
||||
"github.com/diamondburned/arikawa/v3/internal/lazytime"
|
||||
"github.com/diamondburned/arikawa/v3/utils/ws"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -246,7 +245,7 @@ func (g *Gateway) Send(ctx context.Context, data ws.Event) error {
|
|||
// stable connection to the Discord gateway. To the user, the gateway should
|
||||
// appear to be working seamlessly.
|
||||
//
|
||||
// Behaviors
|
||||
// # Behaviors
|
||||
//
|
||||
// There are several behaviors that the gateway will overload onto the channel.
|
||||
//
|
||||
|
@ -264,12 +263,12 @@ func (g *Gateway) Send(ctx context.Context, data ws.Event) error {
|
|||
// BackgroundErrorEvent event. The user can type-assert the Op's data field,
|
||||
// like so:
|
||||
//
|
||||
// switch data := ev.Data.(type) {
|
||||
// case *gateway.BackgroundErrorEvent:
|
||||
// log.Println("gateway error:", data.Error)
|
||||
// }
|
||||
// switch data := ev.Data.(type) {
|
||||
// case *gateway.BackgroundErrorEvent:
|
||||
// log.Println("gateway error:", data.Error)
|
||||
// }
|
||||
//
|
||||
// Closing
|
||||
// # Closing
|
||||
//
|
||||
// As outlined in the first paragraph, closing the gateway would involve
|
||||
// cancelling the context that's given to gateway. If AlwaysCloseGracefully is
|
||||
|
@ -279,33 +278,32 @@ func (g *Gateway) Send(ctx context.Context, data ws.Event) error {
|
|||
// To wait until the gateway has completely successfully exited, the user can
|
||||
// keep spinning on the event loop:
|
||||
//
|
||||
// for op := range ch {
|
||||
// select op.Data.(type) {
|
||||
// case *gateway.ReadyEvent:
|
||||
// // Close the gateway on READY.
|
||||
// cancel()
|
||||
// }
|
||||
// }
|
||||
// for op := range ch {
|
||||
// select op.Data.(type) {
|
||||
// case *gateway.ReadyEvent:
|
||||
// // Close the gateway on READY.
|
||||
// cancel()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Gateway is now completely closed.
|
||||
// // Gateway is now completely closed.
|
||||
//
|
||||
// To capture the final close errors, the user can use the Error method once the
|
||||
// event channel is closed, like so:
|
||||
//
|
||||
// var err error
|
||||
// var err error
|
||||
//
|
||||
// for op := range ch {
|
||||
// switch data := op.Data.(type) {
|
||||
// case *gateway.ReadyEvent:
|
||||
// cancel()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Gateway is now completely closed.
|
||||
// if gateway.LastError() != nil {
|
||||
// return gateway.LastError()
|
||||
// }
|
||||
// for op := range ch {
|
||||
// switch data := op.Data.(type) {
|
||||
// case *gateway.ReadyEvent:
|
||||
// cancel()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Gateway is now completely closed.
|
||||
// if gateway.LastError() != nil {
|
||||
// return gateway.LastError()
|
||||
// }
|
||||
func (g *Gateway) Connect(ctx context.Context) <-chan ws.Op {
|
||||
return g.gateway.Connect(ctx, &gatewayImpl{Gateway: g})
|
||||
}
|
||||
|
@ -325,7 +323,7 @@ func (g *gatewayImpl) invalidate() {
|
|||
// with the given context for timeout.
|
||||
func (g *gatewayImpl) sendIdentify(ctx context.Context) error {
|
||||
if err := g.state.Identifier.Wait(ctx); err != nil {
|
||||
return errors.Wrap(err, "can't wait for identify()")
|
||||
return fmt.Errorf("can't wait for identify(): %w", err)
|
||||
}
|
||||
|
||||
return g.gateway.Send(ctx, &g.state.Identifier.IdentifyCommand)
|
||||
|
|
|
@ -2,6 +2,7 @@ package gateway
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -9,7 +10,6 @@ import (
|
|||
"github.com/diamondburned/arikawa/v3/api"
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/utils/json/option"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
|
@ -46,13 +46,13 @@ func NewIdentifier(data IdentifyCommand) Identifier {
|
|||
func (id *Identifier) Wait(ctx context.Context) error {
|
||||
if id.IdentifyShortLimit != nil {
|
||||
if err := id.IdentifyShortLimit.Wait(ctx); err != nil {
|
||||
return errors.Wrap(err, "can't wait for short limit")
|
||||
return fmt.Errorf("can't wait for short limit: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if id.IdentifyGlobalLimit != nil {
|
||||
if err := id.IdentifyGlobalLimit.Wait(ctx); err != nil {
|
||||
return errors.Wrap(err, "can't wait for global limit")
|
||||
return fmt.Errorf("can't wait for global limit: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,13 +67,13 @@ func (id *Identifier) QueryGateway(ctx context.Context) (gatewayURL string, err
|
|||
if strings.HasPrefix(id.Token, "Bot ") {
|
||||
botData, err = BotURL(ctx, id.Token)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to get bot data")
|
||||
return "", fmt.Errorf("failed to get bot data: %w", err)
|
||||
}
|
||||
gatewayURL = botData.URL
|
||||
} else {
|
||||
gatewayURL, err = URL(ctx)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "failed to get gateway endpoint")
|
||||
return "", fmt.Errorf("failed to get gateway endpoint: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
1
go.mod
1
go.mod
|
@ -5,7 +5,6 @@ go 1.16
|
|||
require (
|
||||
github.com/gorilla/schema v1.2.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/pkg/errors v0.9.1
|
||||
golang.org/x/crypto v0.1.0
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
|
||||
)
|
||||
|
|
2
go.sum
2
go.sum
|
@ -2,8 +2,6 @@ github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
|
|||
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
package testenv
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
@ -11,7 +13,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const PerseveranceTime = 50 * time.Minute
|
||||
|
@ -56,13 +57,13 @@ func getEnv() {
|
|||
|
||||
id, err := discord.ParseSnowflake(os.Getenv("CHANNEL_ID"))
|
||||
if err != nil {
|
||||
globalErr = errors.Wrap(err, "invalid $CHANNEL_ID")
|
||||
globalErr = fmt.Errorf("invalid $CHANNEL_ID: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
vid, err := discord.ParseSnowflake(os.Getenv("VOICE_ID"))
|
||||
if err != nil {
|
||||
globalErr = errors.Wrap(err, "invalid $VOICE_ID")
|
||||
globalErr = fmt.Errorf("invalid $VOICE_ID: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@ package zlib
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var Suffix = [4]byte{'\x00', '\x00', '\xff', '\xff'}
|
||||
|
@ -61,7 +61,7 @@ func (i *Inflator) Flush() ([]byte, error) {
|
|||
if i.zlib == nil {
|
||||
r, err := zlibStreamer(&i.wbuf)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to make a FLATE reader")
|
||||
return nil, fmt.Errorf("failed to make a FLATE reader: %w", err)
|
||||
}
|
||||
// safe assertion
|
||||
i.zlib = r
|
||||
|
@ -79,7 +79,7 @@ func (i *Inflator) Flush() ([]byte, error) {
|
|||
// to verify checksum. Discord doesn't send this.
|
||||
if err != nil {
|
||||
// Unexpected error, try and close.
|
||||
return nil, errors.Wrap(err, "failed to read from FLATE reader")
|
||||
return nil, fmt.Errorf("failed to read from FLATE reader: %w", err)
|
||||
}
|
||||
|
||||
// if err := i.zlib.Close(); err != nil && err != io.ErrUnexpectedEOF {
|
||||
|
|
|
@ -5,11 +5,11 @@ package session
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/api"
|
||||
"github.com/diamondburned/arikawa/v3/api/webhook"
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
|
@ -85,7 +85,7 @@ func Login(ctx context.Context, email, password, mfa string) (*Session, error) {
|
|||
// Try to login without TOTP
|
||||
l, err := client.Login(email, password)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to login")
|
||||
return nil, fmt.Errorf("failed to login: %w", err)
|
||||
}
|
||||
|
||||
if l.Token != "" && !l.MFA {
|
||||
|
@ -101,7 +101,7 @@ func Login(ctx context.Context, email, password, mfa string) (*Session, error) {
|
|||
// Retry logging in with a 2FA token
|
||||
l, err = client.TOTP(mfa, l.Ticket)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to login with 2FA")
|
||||
return nil, fmt.Errorf("failed to login with 2FA: %w", err)
|
||||
}
|
||||
|
||||
return New(l.Token), nil
|
||||
|
|
|
@ -2,6 +2,7 @@ package shard
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -9,7 +10,6 @@ import (
|
|||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
"github.com/diamondburned/arikawa/v3/internal/backoff"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func updateIdentifier(ctx context.Context, id *gateway.Identifier) (url string, err error) {
|
||||
|
@ -63,7 +63,7 @@ func NewManager(token string, fn NewShardFunc) (*Manager, error) {
|
|||
|
||||
url, err := updateIdentifier(context.Background(), &id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get gateway info")
|
||||
return nil, fmt.Errorf("failed to get gateway info: %w", err)
|
||||
}
|
||||
|
||||
return NewIdentifiedManagerWithURL(url, id, fn)
|
||||
|
@ -86,7 +86,7 @@ func NewIdentifiedManager(idData gateway.IdentifyCommand, fn NewShardFunc) (*Man
|
|||
|
||||
url, err := updateIdentifier(context.Background(), &id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get gateway info")
|
||||
return nil, fmt.Errorf("failed to get gateway info: %w", err)
|
||||
}
|
||||
|
||||
id.Shard = idData.Shard
|
||||
|
@ -121,7 +121,7 @@ func NewIdentifiedManagerWithURL(
|
|||
|
||||
m.shards[i].Shard, err = fn(&m, &m.shards[i].ID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to create shard %d/%d", i, len(m.shards)-1)
|
||||
return nil, fmt.Errorf("failed to create shard %d/%d: %w", i, len(m.shards)-1, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,12 @@ package shard
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/api"
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
"github.com/diamondburned/arikawa/v3/session"
|
||||
"github.com/diamondburned/arikawa/v3/utils/handler"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Shard defines a shard gateway interface that the shard manager can use.
|
||||
|
@ -57,7 +57,7 @@ func OpenShards(ctx context.Context, shards []ShardState) error {
|
|||
for i, shard := range shards {
|
||||
if err := shard.Shard.Open(ctx); err != nil {
|
||||
CloseShards(shards)
|
||||
return errors.Wrapf(err, "failed to open shard %d/%d", i, len(shards)-1)
|
||||
return fmt.Errorf("failed to open shard %d/%d: %w", i, len(shards)-1, err)
|
||||
}
|
||||
|
||||
// Mark as opened so we can close them.
|
||||
|
|
|
@ -4,6 +4,8 @@ package state
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/api"
|
||||
|
@ -14,8 +16,6 @@ import (
|
|||
"github.com/diamondburned/arikawa/v3/state/store"
|
||||
"github.com/diamondburned/arikawa/v3/state/store/defaultstore"
|
||||
"github.com/diamondburned/arikawa/v3/utils/handler"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -38,7 +38,7 @@ func NewShardFunc(opts func(*shard.Manager, *State)) shard.NewShardFunc {
|
|||
// State is the cache to store events coming from Discord as well as data from
|
||||
// API calls.
|
||||
//
|
||||
// Store
|
||||
// # Store
|
||||
//
|
||||
// The state basically provides abstractions on top of the API and the state
|
||||
// storage (Store). The state storage is effectively a set of interfaces which
|
||||
|
@ -54,7 +54,7 @@ func NewShardFunc(opts func(*shard.Manager, *State)) shard.NewShardFunc {
|
|||
// state fetch information from the API. The setters are all no-ops, so the
|
||||
// fetched data won't be updated.
|
||||
//
|
||||
// Handler
|
||||
// # Handler
|
||||
//
|
||||
// The state uses its own handler over session's to make all handlers run after
|
||||
// the state updates itself. A PreHandler is exposed in any case the user needs
|
||||
|
@ -289,7 +289,7 @@ func (s *State) Permissions(
|
|||
|
||||
ch, err := s.Channel(channelID)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "failed to get channel")
|
||||
return 0, fmt.Errorf("failed to get channel: %w", err)
|
||||
}
|
||||
|
||||
if !ch.GuildID.IsValid() {
|
||||
|
@ -332,10 +332,10 @@ func (s *State) Permissions(
|
|||
wg.Wait()
|
||||
|
||||
if gerr != nil {
|
||||
return 0, errors.Wrap(merr, "failed to get guild")
|
||||
return 0, fmt.Errorf("failed to get guild: %w", gerr)
|
||||
}
|
||||
if merr != nil {
|
||||
return 0, errors.Wrap(merr, "failed to get member")
|
||||
return 0, fmt.Errorf("failed to get member: %w", merr)
|
||||
}
|
||||
|
||||
return discord.CalcOverwrites(*g, *ch, *m), nil
|
||||
|
@ -590,13 +590,13 @@ func (s *State) Message(
|
|||
|
||||
m, err = s.Session.Message(channelID, messageID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to fetch message")
|
||||
return nil, fmt.Errorf("unable to fetch message: %w", err)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
if cerr != nil {
|
||||
return nil, errors.Wrap(cerr, "unable to fetch channel")
|
||||
return nil, fmt.Errorf("unable to fetch channel: %w", cerr)
|
||||
}
|
||||
|
||||
m.ChannelID = c.ID
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package state
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
|
@ -375,7 +375,7 @@ func (s *State) onEvent(iface interface{}) {
|
|||
}
|
||||
|
||||
func (s *State) stateErr(err error, wrap string) {
|
||||
s.StateLog(errors.Wrap(err, wrap))
|
||||
s.StateLog(fmt.Errorf("%s: %w", wrap, err))
|
||||
}
|
||||
|
||||
func (s *State) batchLog(errors []error) {
|
||||
|
@ -495,6 +495,6 @@ func storeGuildCreate(cab *store.Cabinet, guild *gateway.GuildCreateEvent) []err
|
|||
func newErrorStack() (*[]error, func(error, string)) {
|
||||
var errs = new([]error)
|
||||
return errs, func(err error, wrap string) {
|
||||
*errs = append(*errs, errors.Wrap(err, wrap))
|
||||
*errs = append(*errs, fmt.Errorf("%s: %w", wrap, err))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Package store contains interfaces of the state's storage and its
|
||||
// implementations.
|
||||
//
|
||||
// Getter Methods
|
||||
// # Getter Methods
|
||||
//
|
||||
// All getter methods will be wrapped by the State. If the State can't find
|
||||
// anything in the storage, it will call the API itself and automatically add
|
||||
|
@ -15,7 +15,7 @@
|
|||
// Getter methods should not care about returning slices in order, unless
|
||||
// explicitly stated against.
|
||||
//
|
||||
// ErrNotFound Rules
|
||||
// # ErrNotFound Rules
|
||||
//
|
||||
// If a getter method cannot find something, it should return ErrNotFound.
|
||||
// Callers including State may check if the error is ErrNotFound to do something
|
||||
|
@ -27,7 +27,7 @@
|
|||
// ErrNotFound when either happens. This will make State refetch from the API,
|
||||
// so it is not ideal.
|
||||
//
|
||||
// Remove Methods
|
||||
// # Remove Methods
|
||||
//
|
||||
// Remove methods should return a nil error if the item it wants to delete is
|
||||
// not found. This helps save some additional work in some cases.
|
||||
|
|
|
@ -8,11 +8,11 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
"github.com/diamondburned/arikawa/v3/utils/bot"
|
||||
"github.com/diamondburned/arikawa/v3/utils/bot/extras/arguments"
|
||||
"github.com/diamondburned/arikawa/v3/utils/bot/extras/middlewares"
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
)
|
||||
|
||||
type Bot struct {
|
||||
|
|
|
@ -6,9 +6,9 @@ import (
|
|||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
"github.com/diamondburned/arikawa/v3/utils/bot"
|
||||
"github.com/diamondburned/arikawa/v3/utils/bot/extras/middlewares"
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
)
|
||||
|
||||
// Flag for administrators only.
|
||||
|
|
|
@ -2,6 +2,7 @@ package bot
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
@ -11,8 +12,6 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/api"
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
"github.com/diamondburned/arikawa/v3/session"
|
||||
|
@ -61,7 +60,7 @@ func NewShardFunc(fn func(*state.State) (*Context, error)) shard.NewShardFunc {
|
|||
|
||||
bot, err := fn(state)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create bot instance")
|
||||
return nil, fmt.Errorf("failed to create bot instance: %w", err)
|
||||
}
|
||||
|
||||
return bot, nil
|
||||
|
@ -70,17 +69,17 @@ func NewShardFunc(fn func(*state.State) (*Context, error)) shard.NewShardFunc {
|
|||
|
||||
// Context is the bot state for commands and subcommands.
|
||||
//
|
||||
// Commands
|
||||
// # Commands
|
||||
//
|
||||
// A command can be created by making it a method of Commands, or whatever
|
||||
// struct was given to the constructor. This following example creates a command
|
||||
// with a single integer argument (which can be ran with "~example 123"):
|
||||
//
|
||||
// func (c *Commands) Example(
|
||||
// m *gateway.MessageCreateEvent, i int) (string, error) {
|
||||
// func (c *Commands) Example(
|
||||
// m *gateway.MessageCreateEvent, i int) (string, error) {
|
||||
//
|
||||
// return fmt.Sprintf("You sent: %d", i)
|
||||
// }
|
||||
// return fmt.Sprintf("You sent: %d", i)
|
||||
// }
|
||||
//
|
||||
// Commands' exported methods will all be used as commands. Messages are parsed
|
||||
// with its first argument (the command) mapped accordingly to c.MapName, which
|
||||
|
@ -91,15 +90,15 @@ func NewShardFunc(fn func(*state.State) (*Context, error)) shard.NewShardFunc {
|
|||
// types allowed are string, *discord.Embed, and *api.SendMessageData. Any other
|
||||
// return types will invalidate the method.
|
||||
//
|
||||
// Events
|
||||
// # Events
|
||||
//
|
||||
// An event can only have one argument, which is the pointer to the event
|
||||
// struct. It can also only return error.
|
||||
//
|
||||
// func (c *Commands) Example(o *gateway.TypingStartEvent) error {
|
||||
// log.Println("Someone's typing!")
|
||||
// return nil
|
||||
// }
|
||||
// func (c *Commands) Example(o *gateway.TypingStartEvent) error {
|
||||
// log.Println("Someone's typing!")
|
||||
// return nil
|
||||
// }
|
||||
type Context struct {
|
||||
*Subcommand
|
||||
*state.State
|
||||
|
@ -213,11 +212,11 @@ func Start(
|
|||
|
||||
m, err := shard.NewManager(token, newShard)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to create shard manager")
|
||||
return nil, fmt.Errorf("failed to create shard manager: %w", err)
|
||||
}
|
||||
|
||||
if err := m.Open(context.Background()); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to open")
|
||||
return nil, fmt.Errorf("failed to open: %w", err)
|
||||
}
|
||||
|
||||
return func() error {
|
||||
|
@ -264,12 +263,12 @@ func WaitForInterrupt() {
|
|||
// New makes a new context with a "~" as the prefix. cmds must be a pointer to a
|
||||
// struct with a *Context field. Example:
|
||||
//
|
||||
// type Commands struct {
|
||||
// Ctx *Context
|
||||
// }
|
||||
// type Commands struct {
|
||||
// Ctx *Context
|
||||
// }
|
||||
//
|
||||
// cmds := &Commands{}
|
||||
// c, err := bot.New(session, cmds)
|
||||
// cmds := &Commands{}
|
||||
// c, err := bot.New(session, cmds)
|
||||
//
|
||||
// The default prefix is "~", which means commands must start with "~" followed
|
||||
// by the command name in the first argument, else it will be ignored.
|
||||
|
@ -297,7 +296,7 @@ func New(s *state.State, cmd interface{}) (*Context, error) {
|
|||
}
|
||||
|
||||
if err := ctx.InitCommands(ctx); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to initialize with given cmds")
|
||||
return nil, fmt.Errorf("failed to initialize with given cmds: %w", err)
|
||||
}
|
||||
|
||||
return ctx, nil
|
||||
|
@ -319,11 +318,10 @@ func (ctx *Context) Subcommands() []*Subcommand {
|
|||
// FindMethod finds a method based on the struct and method name. The queried
|
||||
// names will have their flags stripped.
|
||||
//
|
||||
// // Find a command from the main context:
|
||||
// cmd := ctx.FindMethod("", "Method")
|
||||
// // Find a command from a subcommand:
|
||||
// cmd = ctx.FindMethod("Starboard", "Reset")
|
||||
//
|
||||
// // Find a command from the main context:
|
||||
// cmd := ctx.FindMethod("", "Method")
|
||||
// // 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)
|
||||
|
@ -361,7 +359,7 @@ func (ctx *Context) MustRegisterSubcommand(cmd interface{}, names ...string) *Su
|
|||
func (ctx *Context) RegisterSubcommand(cmd interface{}, names ...string) (*Subcommand, error) {
|
||||
s, err := NewSubcommand(cmd)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to add subcommand")
|
||||
return nil, fmt.Errorf("failed to add subcommand: %w", err)
|
||||
}
|
||||
|
||||
// Register the subcommand's name.
|
||||
|
@ -377,7 +375,7 @@ func (ctx *Context) RegisterSubcommand(cmd interface{}, names ...string) (*Subco
|
|||
}
|
||||
|
||||
if err := s.InitCommands(ctx); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to initialize subcommand")
|
||||
return nil, fmt.Errorf("failed to initialize subcommand: %w", err)
|
||||
}
|
||||
|
||||
// Check if the existing command name already exists. This could really be
|
||||
|
@ -417,7 +415,7 @@ func (ctx *Context) Start() func() {
|
|||
if ctx.stopFunc == nil {
|
||||
cancel := ctx.State.AddHandler(func(v interface{}) {
|
||||
if err := ctx.callCmd(v); err != nil {
|
||||
ctx.ErrorLogger(errors.Wrap(err, "command error"))
|
||||
ctx.ErrorLogger(fmt.Errorf("command error: %w", err))
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package bot
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
|
@ -8,7 +9,6 @@ import (
|
|||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
"github.com/diamondburned/arikawa/v3/utils/json/option"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Break is a non-fatal error that could be returned from middlewares to stop
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package middlewares
|
||||
|
||||
import (
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/utils/bot"
|
||||
"github.com/diamondburned/arikawa/v3/utils/bot/extras/infer"
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
)
|
||||
|
||||
func AdminOnly(ctx *bot.Context) func(interface{}) error {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package bot
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
)
|
||||
|
||||
|
@ -44,21 +44,20 @@ func underline(word string) string {
|
|||
// Subcommand is any form of command, which could be a top-level command or a
|
||||
// subcommand.
|
||||
//
|
||||
// Allowed method signatures
|
||||
// # Allowed method signatures
|
||||
//
|
||||
// These are the acceptable function signatures that would be parsed as commands
|
||||
// or events. A return type <T> implies that return value will be ignored.
|
||||
//
|
||||
// func(*gateway.MessageCreateEvent, ...) (string, error)
|
||||
// func(*gateway.MessageCreateEvent, ...) (*discord.Embed, error)
|
||||
// func(*gateway.MessageCreateEvent, ...) (*api.SendMessageData, error)
|
||||
// func(*gateway.MessageCreateEvent, ...) (T, error)
|
||||
// func(*gateway.MessageCreateEvent, ...) error
|
||||
// func(*gateway.MessageCreateEvent, ...)
|
||||
// func(<AnyEvent>) (T, error)
|
||||
// func(<AnyEvent>) error
|
||||
// func(<AnyEvent>)
|
||||
//
|
||||
// func(*gateway.MessageCreateEvent, ...) (string, error)
|
||||
// func(*gateway.MessageCreateEvent, ...) (*discord.Embed, error)
|
||||
// func(*gateway.MessageCreateEvent, ...) (*api.SendMessageData, error)
|
||||
// func(*gateway.MessageCreateEvent, ...) (T, error)
|
||||
// func(*gateway.MessageCreateEvent, ...) error
|
||||
// func(*gateway.MessageCreateEvent, ...)
|
||||
// func(<AnyEvent>) (T, error)
|
||||
// func(<AnyEvent>) error
|
||||
// func(<AnyEvent>)
|
||||
type Subcommand struct {
|
||||
// Description is a string that's appended after the subcommand name in
|
||||
// (*Context).Help().
|
||||
|
@ -122,11 +121,11 @@ func NewSubcommand(cmd interface{}) (*Subcommand, error) {
|
|||
sub := Subcommand{command: cmd}
|
||||
|
||||
if err := sub.reflectCommands(); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to reflect commands")
|
||||
return nil, fmt.Errorf("failed to reflect commands: %w", err)
|
||||
}
|
||||
|
||||
if err := sub.parseCommands(); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse commands")
|
||||
return nil, fmt.Errorf("failed to parse commands: %w", err)
|
||||
}
|
||||
|
||||
return &sub, nil
|
||||
|
@ -148,9 +147,8 @@ func lowerFirstLetter(name string) string {
|
|||
//
|
||||
// There are two ways to use FindCommand:
|
||||
//
|
||||
// sub.FindCommand("MethodName")
|
||||
// sub.FindCommand(thing.MethodName)
|
||||
//
|
||||
// sub.FindCommand("MethodName")
|
||||
// sub.FindCommand(thing.MethodName)
|
||||
func (sub *Subcommand) FindCommand(method interface{}) *MethodContext {
|
||||
return sub.findMethod(method, false)
|
||||
}
|
||||
|
@ -181,9 +179,8 @@ func (sub *Subcommand) findMethod(method interface{}, inclEvents bool) *MethodCo
|
|||
// runtimeMethodName returns the name of the method from the given method call.
|
||||
// It is used as such:
|
||||
//
|
||||
// fmt.Println(methodName(t.Method_dash))
|
||||
// // Output: main.T.Method_dash-fm
|
||||
//
|
||||
// fmt.Println(methodName(t.Method_dash))
|
||||
// // Output: main.T.Method_dash-fm
|
||||
func runtimeMethodName(v interface{}) string {
|
||||
// https://github.com/diamondburned/arikawa/issues/146
|
||||
|
||||
|
@ -402,15 +399,15 @@ func (sub *Subcommand) parseCommands() error {
|
|||
// methods, use a star (*). The given middleware argument can either be a
|
||||
// function with one of the allowed methods or a *MiddlewareContext.
|
||||
//
|
||||
// Allowed function signatures
|
||||
// # Allowed function signatures
|
||||
//
|
||||
// Below are the acceptable function signatures that would be parsed as a proper
|
||||
// middleware. A return value of type T will be ignored. If the given function
|
||||
// is invalid, then this method will panic.
|
||||
//
|
||||
// func(<AnyEvent>) (T, error)
|
||||
// func(<AnyEvent>) error
|
||||
// func(<AnyEvent>)
|
||||
// func(<AnyEvent>) (T, error)
|
||||
// func(<AnyEvent>) error
|
||||
// func(<AnyEvent>)
|
||||
//
|
||||
// Note that although technically all of the above function signatures are
|
||||
// acceptable, one should almost always return only an error.
|
||||
|
|
|
@ -2,7 +2,9 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"log"
|
||||
"os"
|
||||
|
@ -11,10 +13,6 @@ import (
|
|||
"strings"
|
||||
"text/template"
|
||||
"unicode"
|
||||
|
||||
_ "embed"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -110,7 +108,7 @@ var reEventStruct = regexp.MustCompile(eventStructRegex)
|
|||
func (r *registry) CrawlFile(name string) error {
|
||||
f, err := os.ReadFile(name)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to read file")
|
||||
return fmt.Errorf("failed to read file: %w", err)
|
||||
}
|
||||
|
||||
for _, match := range reEventStruct.FindAllSubmatch(f, -1) {
|
||||
|
|
|
@ -2,14 +2,13 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"flag"
|
||||
"go/format"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
|
||||
_ "embed"
|
||||
)
|
||||
|
||||
type data struct {
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
// Package handler handles incoming Gateway events. It reflects the function's
|
||||
// first argument and caches that for use in each event.
|
||||
//
|
||||
// Performance
|
||||
// # Performance
|
||||
//
|
||||
// Each call to the event would take 167 ns/op for roughly each handler. Scaling
|
||||
// that up to 100 handlers is roughly the same as multiplying 167 ns by 100,
|
||||
// which gives 16700 ns or 0.0167 ms.
|
||||
//
|
||||
// BenchmarkReflect-8 7260909 167 ns/op
|
||||
// BenchmarkReflect-8 7260909 167 ns/op
|
||||
//
|
||||
// Usage
|
||||
// # Usage
|
||||
//
|
||||
// Handler's usage is mostly similar to Discordgo, in that AddHandler expects a
|
||||
// function with only one argument or an event channel. For more information,
|
||||
|
@ -18,11 +18,10 @@ package handler
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Handler is a container for command handlers. A zero-value instance is a valid
|
||||
|
@ -125,15 +124,15 @@ func (h *Handler) ChanFor(fn func(interface{}) bool) (out <-chan interface{}, ca
|
|||
// handler when called. A handler type is either a single-argument no-return
|
||||
// function or a channel.
|
||||
//
|
||||
// Function
|
||||
// # Function
|
||||
//
|
||||
// A handler can be a function with a single argument that is the expected event
|
||||
// type. It must not have any returns or any other number of arguments.
|
||||
//
|
||||
// // An example of a valid function handler.
|
||||
// h.AddHandler(func(*gateway.MessageCreateEvent) {})
|
||||
// // An example of a valid function handler.
|
||||
// h.AddHandler(func(*gateway.MessageCreateEvent) {})
|
||||
//
|
||||
// Channel
|
||||
// # Channel
|
||||
//
|
||||
// A handler can also be a channel. The underlying type that the channel wraps
|
||||
// around will be the event type. As such, the type rules are the same as
|
||||
|
@ -146,10 +145,9 @@ func (h *Handler) ChanFor(fn func(interface{}) bool) (out <-chan interface{}, ca
|
|||
// When the rm callback that is returned is called, it will also guarantee that
|
||||
// all blocking sends will be cancelled. This helps prevent dangling goroutines.
|
||||
//
|
||||
// // An example of a valid channel handler.
|
||||
// ch := make(chan *gateway.MessageCreateEvent)
|
||||
// h.AddHandler(ch)
|
||||
//
|
||||
// // An example of a valid channel handler.
|
||||
// ch := make(chan *gateway.MessageCreateEvent)
|
||||
// h.AddHandler(ch)
|
||||
func (h *Handler) AddHandler(handler interface{}) (rm func()) {
|
||||
rm, err := h.addHandler(handler, false)
|
||||
if err != nil {
|
||||
|
@ -210,7 +208,7 @@ func (h *Handler) addHandler(fn interface{}, sync bool) (rm func(), err error) {
|
|||
// Reflect the handler
|
||||
r, err := newHandler(fn, sync)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "handler reflect failed")
|
||||
return nil, fmt.Errorf("handler reflect failed: %w", err)
|
||||
}
|
||||
|
||||
var id int
|
||||
|
|
|
@ -5,12 +5,11 @@ package httputil
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/utils/httputil/httpdriver"
|
||||
"github.com/diamondburned/arikawa/v3/utils/json"
|
||||
)
|
||||
|
@ -213,7 +212,7 @@ func (c *Client) request(
|
|||
fn(q, nil)
|
||||
}
|
||||
|
||||
doErr = errors.Wrap(err, "failed to apply http request options")
|
||||
doErr = fmt.Errorf("failed to apply http request options: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -239,7 +238,7 @@ func (c *Client) request(
|
|||
}
|
||||
|
||||
if onRespErr != nil {
|
||||
doErr = errors.Wrap(onRespErr, "OnResponse handler failed")
|
||||
doErr = fmt.Errorf("OnResponse handler failed: %w", onRespErr)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package sendpart
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/url"
|
||||
|
@ -8,7 +9,6 @@ import (
|
|||
|
||||
"github.com/diamondburned/arikawa/v3/utils/httputil"
|
||||
"github.com/diamondburned/arikawa/v3/utils/json"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// File represents a file to be uploaded to Discord.
|
||||
|
@ -80,11 +80,11 @@ func Write(body *multipart.Writer, item interface{}, files []File) error {
|
|||
// Encode the JSON body first
|
||||
w, err := body.CreateFormField("payload_json")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create bodypart for JSON")
|
||||
return fmt.Errorf("failed to create bodypart for JSON: %w", err)
|
||||
}
|
||||
|
||||
if err := json.EncodeStream(w, item); err != nil {
|
||||
return errors.Wrap(err, "failed to encode JSON")
|
||||
return fmt.Errorf("failed to encode JSON: %w", err)
|
||||
}
|
||||
|
||||
for i, file := range files {
|
||||
|
@ -92,11 +92,11 @@ func Write(body *multipart.Writer, item interface{}, files []File) error {
|
|||
|
||||
w, err := body.CreateFormFile("file"+num, file.Name)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create bodypart for "+num)
|
||||
return fmt.Errorf("failed to create bodypart for %q: %w", num, err)
|
||||
}
|
||||
|
||||
if _, err := io.Copy(w, file.Reader); err != nil {
|
||||
return errors.Wrap(err, "failed to write for file "+num)
|
||||
return fmt.Errorf("failed to write for file %q: %w", num, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,11 +2,11 @@ package ws
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/utils/json"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Codec holds the codec states for Websocket implementations to share with the
|
||||
|
@ -107,7 +107,7 @@ func (c *Codec) send(ctx context.Context, ch chan<- Op, op Op) error {
|
|||
|
||||
func newErrOp(err error, wrap string) Op {
|
||||
if wrap != "" {
|
||||
err = errors.Wrap(err, wrap)
|
||||
err = fmt.Errorf("%s: %w", wrap, err)
|
||||
}
|
||||
|
||||
ev := &BackgroundErrorEvent{
|
||||
|
|
|
@ -3,6 +3,7 @@ package ws
|
|||
import (
|
||||
"compress/zlib"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -10,7 +11,6 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const rwBufferSize = 1 << 15 // 32KB
|
||||
|
@ -99,7 +99,7 @@ func (c *Conn) Dial(ctx context.Context, addr string) (<-chan Op, error) {
|
|||
|
||||
conn, _, err := c.dialer.DialContext(ctx, addr, c.codec.Headers)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to dial WS")
|
||||
return nil, fmt.Errorf("failed to dial WS: %w", err)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
@ -270,12 +270,12 @@ func (state *loopState) handle(ctx context.Context, opCh chan<- Op) error {
|
|||
if state.zlib == nil {
|
||||
z, err := zlib.NewReader(r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create a zlib reader")
|
||||
return fmt.Errorf("failed to create a zlib reader: %w", err)
|
||||
}
|
||||
state.zlib = z
|
||||
} else {
|
||||
if err := state.zlib.(zlib.Resetter).Reset(r, nil); err != nil {
|
||||
return errors.Wrap(err, "failed to reset zlib reader")
|
||||
return fmt.Errorf("failed to reset zlib reader: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,7 +284,7 @@ func (state *loopState) handle(ctx context.Context, opCh chan<- Op) error {
|
|||
}
|
||||
|
||||
if err := state.codec.DecodeInto(ctx, r, &state.buf, opCh); err != nil {
|
||||
return errors.Wrap(err, "error distributing event")
|
||||
return fmt.Errorf("error distributing event: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -2,13 +2,13 @@ package ws
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/internal/lazytime"
|
||||
"github.com/diamondburned/arikawa/v3/utils/json"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ConnectionError is given to the user if the gateway fails to connect to the
|
||||
|
@ -178,7 +178,7 @@ func (g *Gateway) Send(ctx context.Context, data Event) error {
|
|||
|
||||
b, err := json.Marshal(op)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to encode payload")
|
||||
return fmt.Errorf("failed to encode payload: %w", err)
|
||||
}
|
||||
|
||||
// WS should already be thread-safe.
|
||||
|
@ -304,7 +304,7 @@ func (g *Gateway) SendError(err error) {
|
|||
|
||||
// SendErrorWrap is a convenient function over SendError.
|
||||
func (g *Gateway) SendErrorWrap(err error, message string) {
|
||||
g.SendError(errors.Wrap(err, message))
|
||||
g.SendError(fmt.Errorf("%s: %w", message, err))
|
||||
}
|
||||
|
||||
func (g *Gateway) spin(ctx context.Context, h Handler) {
|
||||
|
@ -391,7 +391,7 @@ func (g *Gateway) spin(ctx context.Context, h Handler) {
|
|||
|
||||
// Ensure that we've reconnected successfully. Exit otherwise.
|
||||
if g.srcOp == nil {
|
||||
err = errors.Wrap(err, "failed to reconnect after max attempts")
|
||||
err = fmt.Errorf("failed to reconnect after max attempts: %w", err)
|
||||
g.SendError(ConnectionError{err})
|
||||
return
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@ package ws
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/utils/json"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// OpCode is the type for websocket Op codes. Op codes less than 0 are
|
||||
|
|
|
@ -4,10 +4,10 @@ package ws
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
|
@ -54,7 +54,7 @@ func NewCustomWebsocket(conn Connection, addr string) *Websocket {
|
|||
func (ws *Websocket) Dial(ctx context.Context) (<-chan Op, error) {
|
||||
if err := ws.dialLimiter.Wait(ctx); err != nil {
|
||||
// Expired, fatal error
|
||||
return nil, errors.Wrap(err, "failed to wait for dial rate limiter")
|
||||
return nil, fmt.Errorf("failed to wait for dial rate limiter: %w", err)
|
||||
}
|
||||
|
||||
ws.mutex.Lock()
|
||||
|
@ -81,7 +81,7 @@ func (ws *Websocket) Send(ctx context.Context, b []byte) error {
|
|||
|
||||
if err := sendLimiter.Wait(ctx); err != nil {
|
||||
WSDebug("Send rate limiter timed out.")
|
||||
return errors.Wrap(err, "SendLimiter failed")
|
||||
return fmt.Errorf("SendLimiter failed: %w", err)
|
||||
}
|
||||
|
||||
WSDebug("Send has passed the rate limiting.")
|
||||
|
|
|
@ -2,20 +2,19 @@ package voice
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/state"
|
||||
"github.com/diamondburned/arikawa/v3/utils/handler"
|
||||
"github.com/diamondburned/arikawa/v3/utils/ws/ophandler"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/gateway"
|
||||
"github.com/diamondburned/arikawa/v3/internal/moreatomic"
|
||||
"github.com/diamondburned/arikawa/v3/session"
|
||||
"github.com/diamondburned/arikawa/v3/state"
|
||||
"github.com/diamondburned/arikawa/v3/utils/handler"
|
||||
"github.com/diamondburned/arikawa/v3/utils/ws"
|
||||
"github.com/diamondburned/arikawa/v3/utils/ws/ophandler"
|
||||
"github.com/diamondburned/arikawa/v3/voice/udp"
|
||||
"github.com/diamondburned/arikawa/v3/voice/voicegateway"
|
||||
)
|
||||
|
@ -106,7 +105,7 @@ type Session struct {
|
|||
func NewSession(state MainSession) (*Session, error) {
|
||||
u, err := state.Me()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get me")
|
||||
return nil, fmt.Errorf("failed to get me: %w", err)
|
||||
}
|
||||
|
||||
return NewSessionCustom(state, u.ID), nil
|
||||
|
@ -201,7 +200,7 @@ func (s *Session) updateState(ev *gateway.VoiceStateUpdateEvent) {
|
|||
// Speaking.
|
||||
func (s *Session) JoinChannelAndSpeak(ctx context.Context, chID discord.ChannelID, mute, deaf bool) error {
|
||||
if err := s.JoinChannel(ctx, chID, mute, deaf); err != nil {
|
||||
return errors.Wrap(err, "cannot join channel")
|
||||
return fmt.Errorf("cannot join channel: %w", err)
|
||||
}
|
||||
return s.Speaking(ctx, voicegateway.Microphone)
|
||||
}
|
||||
|
@ -219,7 +218,7 @@ func (s *Session) JoinChannel(ctx context.Context, chID discord.ChannelID, mute,
|
|||
var err error
|
||||
ch, err = s.session.Channel(chID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "invalid channel ID")
|
||||
return fmt.Errorf("invalid channel ID: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,7 +307,7 @@ func (s *Session) JoinChannel(ctx context.Context, chID discord.ChannelID, mute,
|
|||
case <-timer.C:
|
||||
continue
|
||||
case <-ctx.Done():
|
||||
return errors.Wrap(err, "cannot ask Discord for events")
|
||||
return fmt.Errorf("cannot ask Discord for events: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,12 +327,12 @@ func (s *Session) askDiscord(
|
|||
// https://discord.com/developers/docs/topics/voice-connections#retrieving-voice-server-information
|
||||
// Send a Voice State Update event to the gateway.
|
||||
if err := s.session.SendGateway(ctx, data); err != nil {
|
||||
return errors.Wrap(err, "failed to send Voice State Update event")
|
||||
return fmt.Errorf("failed to send Voice State Update event: %w", err)
|
||||
}
|
||||
|
||||
// Wait for 2 replies. The above command should reply with these 2 events.
|
||||
if err := s.waitForIncoming(ctx, chs); err != nil {
|
||||
return errors.Wrap(err, "failed to wait for needed gateway events")
|
||||
return fmt.Errorf("failed to wait for needed gateway events: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -381,7 +380,7 @@ func (s *Session) reconnectCtx(ctx context.Context) error {
|
|||
ws.WSDebug("Sending stop handle.")
|
||||
|
||||
if err := s.udpManager.Pause(ctx); err != nil {
|
||||
return errors.Wrap(err, "cannot pause UDP manager")
|
||||
return fmt.Errorf("cannot pause UDP manager: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
if !s.udpManager.Continue() {
|
||||
|
@ -410,7 +409,7 @@ func (s *Session) reconnectCtx(ctx context.Context) error {
|
|||
// Emit the error. It's fine to do this here since this is the only
|
||||
// place that can error out.
|
||||
s.Handler.Call(&ReconnectError{err})
|
||||
return errors.Wrap(err, "cannot wait for event sequence from voice gateway")
|
||||
return fmt.Errorf("cannot wait for event sequence from voice gateway: %w", err)
|
||||
}
|
||||
|
||||
// Start dispatching.
|
||||
|
@ -431,12 +430,12 @@ func (s *Session) spinGateway(ctx context.Context, gwch <-chan ws.Op) error {
|
|||
return ctx.Err()
|
||||
case ev, ok := <-gwch:
|
||||
if !ok {
|
||||
return errors.Wrap(s.gateway.LastError(), "voice gateway error")
|
||||
return fmt.Errorf("voice gateway error: %w", s.gateway.LastError())
|
||||
}
|
||||
|
||||
switch data := ev.Data.(type) {
|
||||
case *ws.CloseEvent:
|
||||
return errors.Wrap(err, "voice gateway error")
|
||||
return fmt.Errorf("voice gateway error: %w", err)
|
||||
|
||||
case *voicegateway.ReadyEvent:
|
||||
ws.WSDebug("Got ready from voice gateway, SSRC:", data.SSRC)
|
||||
|
@ -444,7 +443,7 @@ func (s *Session) spinGateway(ctx context.Context, gwch <-chan ws.Op) error {
|
|||
// Prepare the UDP voice connection.
|
||||
conn, err = s.udpManager.Dial(ctx, data.Addr(), data.SSRC)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to open voice UDP connection")
|
||||
return fmt.Errorf("failed to open voice UDP connection: %w", err)
|
||||
}
|
||||
|
||||
if err := s.gateway.Send(ctx, &voicegateway.SelectProtocolCommand{
|
||||
|
@ -455,7 +454,7 @@ func (s *Session) spinGateway(ctx context.Context, gwch <-chan ws.Op) error {
|
|||
Mode: Protocol,
|
||||
},
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "failed to send SelectProtocolCommand")
|
||||
return fmt.Errorf("failed to send SelectProtocolCommand: %w", err)
|
||||
}
|
||||
|
||||
case *voicegateway.SessionDescriptionEvent:
|
||||
|
@ -545,7 +544,7 @@ func (s *Session) Leave(ctx context.Context) error {
|
|||
}
|
||||
|
||||
if sendErr != nil {
|
||||
return errors.Wrap(sendErr, "failed to update voice state")
|
||||
return fmt.Errorf("failed to update voice state: %w", sendErr)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -559,7 +558,7 @@ func (s *Session) cancelGateway(ctx context.Context) error {
|
|||
// Wait for the previous gateway to finish closing up, but make sure to
|
||||
// bail if the context expires.
|
||||
if err := ophandler.WaitForDone(ctx, s.gwDone); err != nil {
|
||||
return errors.Wrap(err, "cannot wait for gateway to close")
|
||||
return fmt.Errorf("cannot wait for gateway to close: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ package voice
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
|
@ -20,7 +22,6 @@ import (
|
|||
"github.com/diamondburned/arikawa/v3/voice/testdata"
|
||||
"github.com/diamondburned/arikawa/v3/voice/udp"
|
||||
"github.com/diamondburned/arikawa/v3/voice/voicegateway"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
@ -165,7 +166,7 @@ func raceMe(t *testing.T, wrapErr string, fn func() error) {
|
|||
wgr.Wait()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal("race test failed:", errors.Wrap(err, wrapErr))
|
||||
t.Fatal("race test failed:", fmt.Errorf("%s: %w", wrapErr, err))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,10 +2,9 @@ package testdata
|
|||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const Nico = "testdata/nico.dca"
|
||||
|
@ -15,7 +14,7 @@ const Nico = "testdata/nico.dca"
|
|||
func WriteOpus(w io.Writer, file string) error {
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to open "+file)
|
||||
return fmt.Errorf("failed to open %s: %w", file, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
|
@ -26,7 +25,7 @@ func WriteOpus(w io.Writer, file string) error {
|
|||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "failed to read "+file)
|
||||
return fmt.Errorf("failed to read %s: %w", file, err)
|
||||
}
|
||||
|
||||
// Read the integer
|
||||
|
@ -35,7 +34,7 @@ func WriteOpus(w io.Writer, file string) error {
|
|||
// Copy the frame.
|
||||
_, err = io.CopyN(w, f, framelen)
|
||||
if err != nil && err != io.EOF {
|
||||
return errors.Wrap(err, "failed to write")
|
||||
return fmt.Errorf("failed to write: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,13 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/crypto/nacl/secretbox"
|
||||
)
|
||||
|
||||
|
@ -86,7 +87,7 @@ func DialConnectionCustom(
|
|||
// Create a new UDP connection.
|
||||
conn, err := dialer.DialContext(ctx, "udp", addr)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to dial host")
|
||||
return nil, fmt.Errorf("failed to dial host: %w", err)
|
||||
}
|
||||
|
||||
// https://discord.com/developers/docs/topics/voice-connections#ip-discovery
|
||||
|
@ -97,7 +98,7 @@ func DialConnectionCustom(
|
|||
|
||||
_, err = conn.Write(ssrcBuffer[:])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to write SSRC buffer")
|
||||
return nil, fmt.Errorf("failed to write SSRC buffer: %w", err)
|
||||
}
|
||||
|
||||
var ipBuffer [74]byte
|
||||
|
@ -105,7 +106,7 @@ func DialConnectionCustom(
|
|||
// ReadFull makes sure to read all 74 bytes.
|
||||
_, err = io.ReadFull(conn, ipBuffer[:])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to read IP buffer")
|
||||
return nil, fmt.Errorf("failed to read IP buffer: %w", err)
|
||||
}
|
||||
|
||||
ipbody := ipBuffer[8:72]
|
||||
|
@ -155,15 +156,15 @@ func DialConnectionCustom(
|
|||
// be consistent with th given frameDuration. For the right combination, refer
|
||||
// to the Valid Parameters section below.
|
||||
//
|
||||
// Valid Parameters
|
||||
// # Valid Parameters
|
||||
//
|
||||
// The following table lists the recommended parameters for these variables.
|
||||
//
|
||||
// +---------+-----+-----+------+------+
|
||||
// | Mode | 10 | 20 | 40 | 60 |
|
||||
// +---------+-----+-----+------+------+
|
||||
// | ts incr | 480 | 960 | 1920 | 2880 |
|
||||
// +---------+-----+-----+------+------+
|
||||
// +---------+-----+-----+------+------+
|
||||
// | Mode | 10 | 20 | 40 | 60 |
|
||||
// +---------+-----+-----+------+------+
|
||||
// | ts incr | 480 | 960 | 1920 | 2880 |
|
||||
// +---------+-----+-----+------+------+
|
||||
//
|
||||
// Note that audio mode is omitted, as it is not recommended. For the full
|
||||
// table, refer to the IETF RFC7587 section 4.2 link above.
|
||||
|
@ -222,7 +223,7 @@ func (c *Connection) Write(b []byte) (int, error) {
|
|||
case <-c.frequency.C:
|
||||
// ok
|
||||
case <-c.stopFreq:
|
||||
return 0, errors.Wrap(net.ErrClosed, "frequency ticker stopped")
|
||||
return 0, fmt.Errorf("frequency ticker stopped: %w", net.ErrClosed)
|
||||
}
|
||||
|
||||
_, err := c.conn.Write(toSend)
|
||||
|
|
|
@ -2,11 +2,12 @@ package udp
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/utils/ws"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ErrManagerClosed is returned when a Manager that is already closed is dialed,
|
||||
|
@ -152,7 +153,7 @@ func (m *Manager) Dial(ctx context.Context, addr string, ssrc uint32) (*Connecti
|
|||
if err != nil {
|
||||
// Unlock if we failed.
|
||||
<-m.connLock
|
||||
return nil, errors.Wrap(err, "failed to dial")
|
||||
return nil, fmt.Errorf("failed to dial: %w", err)
|
||||
}
|
||||
|
||||
if m.frequency > 0 && m.timeIncr > 0 {
|
||||
|
|
|
@ -11,12 +11,11 @@ package voicegateway
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/diamondburned/arikawa/v3/discord"
|
||||
"github.com/diamondburned/arikawa/v3/utils/ws"
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue