From 3d4853490335c413935be651e7a2db692779d8df Mon Sep 17 00:00:00 2001 From: Laurent Toussaint Date: Wed, 21 Nov 2018 12:02:52 +0100 Subject: [PATCH] Add support for rate_limit_status endpoint --- README.md | 1 + twitter/rate_limits.go | 68 +++++++++++++++++++++++++++++++++++++ twitter/rate_limits_test.go | 39 +++++++++++++++++++++ twitter/twitter.go | 2 ++ 4 files changed, 110 insertions(+) create mode 100644 twitter/rate_limits.go create mode 100644 twitter/rate_limits_test.go diff --git a/README.md b/README.md index 82d1e02..3ad76c8 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ go-twitter is a Go client library for the [Twitter API](https://dev.twitter.com/ * Friends * Friendships * Followers + * RateLimits * Search * Statuses * Timelines diff --git a/twitter/rate_limits.go b/twitter/rate_limits.go new file mode 100644 index 0000000..61ca4f9 --- /dev/null +++ b/twitter/rate_limits.go @@ -0,0 +1,68 @@ +package twitter + +import ( + "net/http" + + "github.com/dghubble/sling" +) + +// RateLimitService provides methods for accessing Twitter rate limits +// API endpoints. +type RateLimitService struct { + sling *sling.Sling +} + +// newRateLimitService returns a new RateLimitService. +func newRateLimitService(sling *sling.Sling) *RateLimitService { + return &RateLimitService{ + sling: sling.Path("application/"), + } +} + +// RateLimit summarizes current rate limits of resource families. +type RateLimit struct { + RateLimitContext *RateLimitContext `json:"rate_limit_context"` + Resources *RateLimitResources `json:"resources"` +} + +// RateLimitContext contains auth context +type RateLimitContext struct { + AccessToken string `json:"access_token"` +} + +// RateLimitResources contains all limit status data for endpoints group by resources +type RateLimitResources struct { + Application map[string]*RateLimitResource `json:"application"` + Favorites map[string]*RateLimitResource `json:"favorites"` + Followers map[string]*RateLimitResource `json:"followers"` + Friends map[string]*RateLimitResource `json:"friends"` + Friendships map[string]*RateLimitResource `json:"friendships"` + Geo map[string]*RateLimitResource `json:"geo"` + Help map[string]*RateLimitResource `json:"help"` + Lists map[string]*RateLimitResource `json:"lists"` + Search map[string]*RateLimitResource `json:"search"` + Statuses map[string]*RateLimitResource `json:"statuses"` + Trends map[string]*RateLimitResource `json:"trends"` + Users map[string]*RateLimitResource `json:"users"` +} + +// RateLimitResource contains limit status data for a single endpoint +type RateLimitResource struct { + Limit int `json:"limit"` + Remaining int `json:"remaining"` + Reset int `json:"reset"` +} + +// RateLimitParams are the parameters for RateLimitService.Status. +type RateLimitParams struct { + Resources []string `url:"resources,omitempty,comma"` +} + +// Status summarizes the current rate limits of specified resource families. +// https://developer.twitter.com/en/docs/developer-utilities/rate-limit-status/api-reference/get-application-rate_limit_status +func (s *RateLimitService) Status(params *RateLimitParams) (*RateLimit, *http.Response, error) { + rateLimit := new(RateLimit) + apiError := new(APIError) + resp, err := s.sling.New().Get("rate_limit_status.json").QueryStruct(params).Receive(rateLimit, apiError) + return rateLimit, resp, relevantError(err, *apiError) +} diff --git a/twitter/rate_limits_test.go b/twitter/rate_limits_test.go new file mode 100644 index 0000000..856a993 --- /dev/null +++ b/twitter/rate_limits_test.go @@ -0,0 +1,39 @@ +package twitter + +import ( + "fmt" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRateLimitService_Status(t *testing.T) { + httpClient, mux, server := testServer() + defer server.Close() + + mux.HandleFunc("/1.1/application/rate_limit_status.json", func(w http.ResponseWriter, r *http.Request) { + assertMethod(t, "GET", r) + assertQuery(t, map[string]string{"resources": "statuses,users"}, r) + w.Header().Set("Content-Type", "application/json") + fmt.Fprintf(w, `{"rate_limit_context":{"access_token":"a_fake_access_token"},"resources":{"statuses":{"/statuses/mentions_timeline":{"limit":75,"remaining":75,"reset":1403602426},"/statuses/lookup":{"limit":900,"remaining":900,"reset":1403602426}}}}`) + }) + + client := NewClient(httpClient) + rateLimits, _, err := client.RateLimits.Status(&RateLimitParams{Resources: []string{"statuses", "users"}}) + expected := &RateLimit{ + RateLimitContext: &RateLimitContext{AccessToken: "a_fake_access_token"}, + Resources: &RateLimitResources{ + Statuses: map[string]*RateLimitResource{ + "/statuses/mentions_timeline": &RateLimitResource{ + Limit: 75, + Remaining: 75, + Reset: 1403602426}, + "/statuses/lookup": &RateLimitResource{ + Limit: 900, + Remaining: 900, + Reset: 1403602426}}}} + + assert.Nil(t, err) + assert.Equal(t, expected, rateLimits) +} diff --git a/twitter/twitter.go b/twitter/twitter.go index 96fbf9f..8d394ee 100644 --- a/twitter/twitter.go +++ b/twitter/twitter.go @@ -18,6 +18,7 @@ type Client struct { Followers *FollowerService Friends *FriendService Friendships *FriendshipService + RateLimits *RateLimitService Search *SearchService Statuses *StatusService Streams *StreamService @@ -37,6 +38,7 @@ func NewClient(httpClient *http.Client) *Client { Followers: newFollowerService(base.New()), Friends: newFriendService(base.New()), Friendships: newFriendshipService(base.New()), + RateLimits: newRateLimitService(base.New()), Search: newSearchService(base.New()), Statuses: newStatusService(base.New()), Streams: newStreamService(httpClient, base.New()),