Gateway: Added GatewayBot

This commit is contained in:
diamondburned (Forefront) 2020-04-19 09:17:04 -07:00
parent 0d81f9176a
commit b9384042bb
2 changed files with 64 additions and 24 deletions

View File

@ -10,11 +10,13 @@ package gateway
import (
"context"
"log"
"net/http"
"net/url"
"sync"
"time"
"github.com/diamondburned/arikawa/api"
"github.com/diamondburned/arikawa/discord"
"github.com/diamondburned/arikawa/utils/httputil"
"github.com/diamondburned/arikawa/utils/json"
"github.com/diamondburned/arikawa/utils/wsutil"
@ -48,18 +50,48 @@ var (
)
var (
ErrMissingForResume = errors.New(
"missing session ID or sequence for resuming")
ErrWSMaxTries = errors.New("max tries reached")
ErrMissingForResume = errors.New("missing session ID or sequence for resuming")
ErrWSMaxTries = errors.New("max tries reached")
)
func GatewayURL() (string, error) {
var Gateway struct {
URL string `json:"url"`
}
// GatewayBotData contains the GatewayURL as well as extra metadata on how to
// shard bots.
type GatewayBotData struct {
URL string `json:"url"`
Shards int `json:"shards,omitempty"`
StartLimit *SessionStartLimit `json:"session_start_limit"`
}
return Gateway.URL, httputil.DefaultClient.RequestJSON(
&Gateway, "GET", EndpointGateway)
// SessionStartLimit is the information on the current session start limit. It's
// used in GatewayBotData.
type SessionStartLimit struct {
Total int `json:"total"`
Remaining int `json:"remaining"`
ResetAfter discord.Milliseconds `json:"reset_after"`
}
// GatewayURL asks Discord for a Websocket URL to the Gateway.
func GatewayURL() (string, error) {
var g GatewayBotData
return g.URL, httputil.DefaultClient.RequestJSON(
&g, "GET",
EndpointGateway,
)
}
// GatewayBot fetches the Gateway URL along with extra metadata. The token
// passed in will NOT be prefixed with Bot.
func GatewayBot(token string) (*GatewayBotData, error) {
var g *GatewayBotData
return g, httputil.DefaultClient.RequestJSON(
&g, "GET",
EndpointGatewayBot,
httputil.WithHeaders(http.Header{
"Authorization": {token},
}),
)
}
type Gateway struct {
@ -117,16 +149,6 @@ func NewGatewayWithDriver(token string, driver json.Driver) (*Gateway, error) {
return nil, errors.Wrap(err, "Failed to get gateway endpoint")
}
g := &Gateway{
Driver: driver,
WSTimeout: WSTimeout,
Events: make(chan Event, WSBuffer),
Identifier: DefaultIdentifier(token),
Sequence: NewSequence(),
ErrorLog: WSError,
AfterClose: func(error) {},
}
// Parameters for the gateway
param := url.Values{
"v": {Version},
@ -136,11 +158,20 @@ func NewGatewayWithDriver(token string, driver json.Driver) (*Gateway, error) {
// Append the form to the URL
URL += "?" + param.Encode()
// Create a new undialed Websocket.
g.WS = wsutil.NewCustom(wsutil.NewConn(driver), URL)
return NewCustomGateway(URL, token, driver), nil
}
// Try and dial it
return g, nil
func NewCustomGateway(gatewayURL, token string, driver json.Driver) *Gateway {
return &Gateway{
WS: wsutil.NewCustom(wsutil.NewConn(driver), gatewayURL),
Driver: driver,
WSTimeout: WSTimeout,
Events: make(chan Event, WSBuffer),
Identifier: DefaultIdentifier(token),
Sequence: NewSequence(),
ErrorLog: WSError,
AfterClose: func(error) {},
}
}
// Close closes the underlying Websocket connection.
@ -282,7 +313,7 @@ func (g *Gateway) start() error {
// Expect either READY or RESUMED before continuing.
WSDebug("Waiting for either READY or RESUMED.")
// WaitForEvent should
// WaitForEvent should
err := WaitForEvent(g, ch, func(op *OP) bool {
switch op.EventName {
case "READY":

View File

@ -19,6 +19,15 @@ func MultipartRequest(r *http.Request) error {
return nil
}
func WithHeaders(headers http.Header) RequestOption {
return func(r *http.Request) error {
for key, values := range headers {
r.Header[key] = append(r.Header[key], values...)
}
return nil
}
}
func WithContentType(ctype string) RequestOption {
return func(r *http.Request) error {
r.Header.Set("Content-Type", ctype)