github.com/diamondburned/arikawa/v2@v2.1.0/api/api.go (about) 1 // Package api provides an interface to interact with the Discord REST API. It 2 // handles rate limiting, as well as authorizing and more. 3 package api 4 5 import ( 6 "context" 7 "net/http" 8 9 "github.com/diamondburned/arikawa/v2/api/rate" 10 "github.com/diamondburned/arikawa/v2/utils/httputil" 11 "github.com/diamondburned/arikawa/v2/utils/httputil/httpdriver" 12 ) 13 14 var ( 15 BaseEndpoint = "https://discord.com" 16 Version = "8" 17 Path = "/api/v" + Version 18 19 Endpoint = BaseEndpoint + Path + "/" 20 EndpointGateway = Endpoint + "gateway" 21 EndpointGatewayBot = EndpointGateway + "/bot" 22 ) 23 24 var UserAgent = "DiscordBot (https://github.com/diamondburned/arikawa/v2)" 25 26 type Client struct { 27 *httputil.Client 28 *Session 29 } 30 31 func NewClient(token string) *Client { 32 return NewCustomClient(token, httputil.NewClient()) 33 } 34 35 func NewCustomClient(token string, httpClient *httputil.Client) *Client { 36 ses := Session{ 37 Limiter: rate.NewLimiter(Path), 38 Token: token, 39 UserAgent: UserAgent, 40 } 41 42 hcl := httpClient.Copy() 43 hcl.OnRequest = append(hcl.OnRequest, ses.InjectRequest) 44 hcl.OnResponse = append(hcl.OnResponse, ses.OnResponse) 45 46 return &Client{ 47 Client: hcl, 48 Session: &ses, 49 } 50 } 51 52 // WithContext returns a shallow copy of Client with the given context. It's 53 // used for method timeouts and such. This method is thread-safe. 54 func (c *Client) WithContext(ctx context.Context) *Client { 55 return &Client{ 56 Client: c.Client.WithContext(ctx), 57 Session: c.Session, 58 } 59 } 60 61 // Session keeps a single session. This is typically wrapped around Client. 62 type Session struct { 63 Limiter *rate.Limiter 64 65 Token string 66 UserAgent string 67 } 68 69 func (s *Session) InjectRequest(r httpdriver.Request) error { 70 r.AddHeader(http.Header{ 71 "Authorization": {s.Token}, 72 "User-Agent": {s.UserAgent}, 73 }) 74 75 // Rate limit stuff 76 return s.Limiter.Acquire(r.GetContext(), r.GetPath()) 77 } 78 79 func (s *Session) OnResponse(r httpdriver.Request, resp httpdriver.Response) error { 80 return s.Limiter.Release(r.GetPath(), httpdriver.OptHeader(resp)) 81 }