Documentation ¶
Index ¶
- Constants
- Variables
- func HeaderToTime(header http.Header) (t time.Time, err error)
- func NormalizeDiscordHeader(statusCode int, header http.Header, body []byte) (h http.Header, err error)
- func SupportsDiscordAPIVersion(version int) bool
- type Client
- type Config
- type Details
- type ErrREST
- type Error
- type HttpClientDoer
- type Manager
- type RESTBucket
- type RESTBucketManager
- type RateLimitResponseStructure
- type Request
- type Requester
- type Snowflake
Constants ¶
const ( BaseURL = "https://discord.com/api" RegexpSnowflakes = `([0-9]+)` RegexpURLSnowflakes = `\/` + RegexpSnowflakes + `\/?` RegexpEmoji = `([.^/]+)\s?` RegexpReactionPrefix = `\/channels\/([0-9]+)\/messages\/\{id\}\/reactions\/` // Header AuthorizationFormat = "%s" UserAgentFormat = "DiscordBot (%s, %s) %s" ContentEncoding = "Content-Encoding" ContentType = "Content-Type" ContentTypeJSON = "application/json" GZIPCompression = "gzip" )
defaults and string format's for Discord interaction
const ( XAuditLogReason = "X-Audit-Log-Reason" XRateLimitPrecision = "X-RateLimit-Precision" XRateLimitBucket = "X-RateLimit-Bucket" XRateLimitLimit = "X-RateLimit-Limit" XRateLimitRemaining = "X-RateLimit-Remaining" XRateLimitReset = "X-RateLimit-Reset" XRateLimitResetAfter = "X-RateLimit-Reset-After" XRateLimitGlobal = "X-RateLimit-Global" RateLimitRetryAfter = "Retry-After" DisgordNormalizedHeader = "X-Disgord-Normalized-Kufdsfksduhf-S47yf" XDisgordNow = "X-Disgord-Now-fsagkhf" )
http rate limit identifiers
const ( MethodGet httpMethod = http.MethodGet MethodDelete httpMethod = http.MethodDelete MethodPost httpMethod = http.MethodPost MethodPatch httpMethod = http.MethodPatch MethodPut httpMethod = http.MethodPut )
const GlobalHash = "global"
Variables ¶
var (
ErrRateLimited error = &Error{"rate limited", time.Unix(0, 0)}
)
Functions ¶
func HeaderToTime ¶
HeaderToTime takes the response header from Discord and extracts the timestamp. Useful for detecting time desync between discord and client
func NormalizeDiscordHeader ¶
func NormalizeDiscordHeader(statusCode int, header http.Header, body []byte) (h http.Header, err error)
NormalizeDiscordHeader overrides header fields with body content and make sure every header field uses milliseconds and not seconds. Regards rate limits only.
func SupportsDiscordAPIVersion ¶
SupportsDiscordAPIVersion check if a given discord api version is supported by this package.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client for handling Discord REST requests
func (*Client) BucketGrouping ¶
type Config ¶
type Config struct { APIVersion int BotToken string HttpClient HttpClientDoer CancelRequestWhenRateLimited bool // RESTBucketManager stores all rate limit buckets and dictates the behaviour of how rate limiting is respected RESTBucketManager RESTBucketManager // Header field: `User-Agent: DiscordBot ({Source}, {Version}) {Extra}` UserAgentVersion string UserAgentSourceURL string UserAgentExtra string }
Config is the configuration options for the httd.Client structure. Essentially the behaviour of all requests sent to Discord.
type Details ¶
type Details struct { Ratelimiter string Endpoint string // always as a suffix to Ratelimiter(!) ResponseStruct interface{} SuccessHTTPCode int }
Details ...
type ErrREST ¶
type HttpClientDoer ¶
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
func NewManager ¶
func (*Manager) Bucket ¶
func (r *Manager) Bucket(id string, cb func(bucket RESTBucket))
func (*Manager) BucketGrouping ¶
func (*Manager) Consolidate ¶
func (r *Manager) Consolidate()
func (*Manager) UpdateProxyID ¶
type RESTBucket ¶
type RESTBucket interface { // Transaction allows a selective atomic transaction. For distributed systems, the buckets can be // eventual consistent until a rate limit is hit then they must be strongly consistent. The global bucket // must always be strongly consistent. Tip: it might be easier/best to keep everything strongly consistent, // and only care about eventual consistency to get better performance as a "bug"/"accident". Transaction(context.Context, func() (*http.Response, []byte, error)) (*http.Response, []byte, error) }
RESTBucket is a REST bucket for one endpoint or several endpoints. This includes the global bucket.
type RESTBucketManager ¶
type RESTBucketManager interface { // Bucket returns the bucket for a given local hash. Note that a local hash simply means // a hashed endpoint. This is because Discord does not specify bucket hashed ahead of time. // Note you should map localHashes to Discord bucket hashes once that insight have been gained. // Discord Bucket hashes are found in the response header, field name `X-RateLimit-Bucket`. Bucket(localHash string, cb func(bucket RESTBucket)) // BucketGrouping shows which hashed endpoints falls under which bucket hash // here a bucket hash is defined by discord, otherwise the bucket hash // is the same as the hashed endpoint. // // Hashed endpoints are generated by the Request struct. BucketGrouping() (group map[string][]string) }
RESTBucketManager manages the buckets and the global bucket.
type RateLimitResponseStructure ¶
type RateLimitResponseStructure struct { Message string `json:"message"` // A message saying you are being rate limited. RetryAfter float64 `json:"retry_after"` // The number of seconds to wait before submitting another request. Global bool `json:"global"` // A value indicating if you are being globally rate limited or not }
type Request ¶
type Request struct { Ctx context.Context Method httpMethod Endpoint string Body interface{} // will automatically marshal to JSON if the ContentType is httd.ContentTypeJSON ContentType string // Reason is a X-Audit-Log-Reason header field that will show up on the audit log for this action. Reason string // contains filtered or unexported fields }
Request is populated before executing a Discord request to correctly generate a http request
func (*Request) HashEndpoint ¶
func (*Request) PopulateMissing ¶
func (r *Request) PopulateMissing()