twitter_labs_api 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b280e642f8468d372684da3c0a04ce2effffd652b244e53a50e1925ade66d3fc
4
- data.tar.gz: e1f1513a92468bc7fdb3e538bbc70b44ab15be2251f203485258f701b8c6b629
3
+ metadata.gz: f948545c92cea7e99843267178e59de531a72c6ae552b83d3e75e9166c15ef1a
4
+ data.tar.gz: 11a1eff22ea020997cfaa2242e2d53c3734d49d5bcf52ae6a505db5ed16d106a
5
5
  SHA512:
6
- metadata.gz: 7166032d4689b43fd696fc5f627dfe00af89eec532b3f36a652d6b22d3c74732c75b60e36be3a18caa9683b68c3b4629abad0d9319985ad56ef01ee19264ad94
7
- data.tar.gz: 259cb764a4c6f15ed5efb335bc46da7117fa447da3c19fd7754e931e40616bd2464847b547a9a17a7d5094f43195f717f196da6733ec47bfbf7d9c8470aa3e19
6
+ metadata.gz: b1ef6ca4d36e6c1fc0bbbeaa88a0ab764b66997b2ac8c1da2c546a8208f8368f9da6376341cdcc69a4d840a411ace4e5c38a30d71f6fa1463d1c24385a0164b2
7
+ data.tar.gz: 971f0fb5b2fe9d242ea98e1d7a51ee227f586580a04f14bf3c5af4e56541167c2e2f2d3e78977f7c3b78712a08ebf7af97e722ac7363da82cfe8e77e0ae8d387
@@ -0,0 +1 @@
1
+ pkg/
@@ -1,3 +1,9 @@
1
+ # 0.2.0 - 5 March 2020
2
+
3
+ - Fix: Handle 'successful' API errors (i.e., HTTP 200 response, but API error such as User Not Found)
4
+ - Documented expansion fields
5
+ - Documented methods
6
+
1
7
  # 0.1.0 - 5 March 2020
2
8
 
3
9
  Initial gem commit
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- twitter_labs_api (0.1.0)
4
+ twitter_labs_api (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -21,7 +21,7 @@ GEM
21
21
  minitest (5.14.0)
22
22
  rack (2.2.2)
23
23
  rainbow (3.0.0)
24
- rake (10.5.0)
24
+ rake (13.0.1)
25
25
  thread_safe (0.3.6)
26
26
  tzinfo (1.2.6)
27
27
  thread_safe (~> 0.1)
@@ -34,7 +34,7 @@ DEPENDENCIES
34
34
  activesupport
35
35
  bundler (~> 2.0)
36
36
  httplog
37
- rake (~> 10.0)
37
+ rake (~> 13.0)
38
38
  twitter_labs_api!
39
39
 
40
40
  BUNDLED WITH
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # twitter-labs-api
2
2
 
3
- A basic implementation of a Twitter Labs API client in Ruby. This project uses the v2 endpoints announced [here](https://twittercommunity.com/t/releasing-a-new-version-of-labs-endpoints/134219/3).
3
+ A basic implementation of a Twitter Labs API client as a handy Ruby [gem](https://rubygems.org/gems/twitter_labs_api). This project uses the v2 endpoints announced [here](https://twittercommunity.com/t/releasing-a-new-version-of-labs-endpoints/134219/3).
4
4
 
5
5
  ## Usage
6
6
 
@@ -9,10 +9,17 @@ All one needs is a Twitter [bearer token](https://developer.twitter.com/en/docs/
9
9
 
10
10
  One easy way to get a bearer token is to use [this method](https://www.rubydoc.info/gems/twitter/Twitter/REST/Client#bearer_token%3F-instance_method) from https://github.com/sferik/twitter.
11
11
 
12
+ ### Setup
13
+
14
+ ```shell
15
+ gem install twitter_labs_api
16
+ ```
17
+
12
18
  ### Example
13
19
 
20
+ #### Getting a Tweet by ID
14
21
  ```ruby
15
- requre `labs_api`
22
+ requre `twitter_labs_api`
16
23
 
17
24
  api = TwitterLabsAPI.new(bearer_token: 'YOUR-BEARER-TOKEN')
18
25
 
@@ -21,6 +28,18 @@ api.get_tweet(id: '1234671272602193920')
21
28
  >> {"data"=>{"author_id"=>"44196397", "created_at"=>"2020-03-03T02:45:45.000Z", "id"=>"1234671272602193920", "lang"=>"und", "public_metrics"=>{"retweet_count"=>4534, "reply_count"=>1036, "like_count"=>43489, "quote_count"=>224}, "text"=>"✌️ bro https://t.co/nJ7CUyhr2j"}}
22
29
  ```
23
30
 
31
+ #### Specifying which fields to include in the response
32
+
33
+ By default, the gem requests the 'default' fields for each entity. See the [API Reference](https://developer.twitter.com/en/docs/labs/tweets-and-users/api-reference) for available fields. One can customize the response payload like so:
34
+
35
+ ```ruby
36
+ my_fields = %w[id author_id created_at text]
37
+
38
+ api.get_tweet(id: '1235508591232090112', tweet_fields: my_fields)
39
+
40
+ >> {"author_id"=>"229708614", "created_at"=>"2020-03-05T10:12:57.000Z", "id"=>"1235508591232090112", "text"=>"Hot take: coronavirus will not boost remote work in the long run because spur-of-the-moment work-from-home for in-person companies is likely to be a shitshow."}
41
+ ```
42
+
24
43
  ### Status
25
44
  Currently, the following endpoints are implemented:
26
45
 
@@ -3,13 +3,14 @@ require 'net/http'
3
3
  require 'uri'
4
4
  require 'active_support/core_ext/hash/indifferent_access'
5
5
 
6
- DEFAULT_TWEET_FIELDS = %w[id author_id created_at lang public_metrics].join(',').freeze
7
- DEFAULT_USER_FIELDS = %w[name username].join(',').freeze
6
+ DEFAULT_TWEET_FIELDS = %w[id author_id created_at lang public_metrics].freeze
7
+ DEFAULT_USER_FIELDS = %w[name username].freeze
8
8
 
9
9
  class TwitterLabsAPIError < StandardError; end
10
10
 
11
+ # A basic implementation of a Twitter Labs API client.
11
12
  class TwitterLabsAPI
12
- attr_accessor :bearer_token, :debug
13
+ attr_accessor :bearer_token, :debug, :api_response, :parsed_response
13
14
 
14
15
  def initialize(bearer_token:, debug: false)
15
16
  @bearer_token = bearer_token
@@ -17,39 +18,47 @@ class TwitterLabsAPI
17
18
  require 'httplog' if debug
18
19
  end
19
20
 
21
+ # @param [String] :id the ID of the requested Tweet
22
+ # @param [Array<String>] :tweet_fields (["id", "author_id", "created_at", "lang", "public_metrics"]) the list of fields to retrieve for the given tweet
20
23
  def get_tweet(id:, tweet_fields: DEFAULT_TWEET_FIELDS)
21
24
  url = "https://api.twitter.com/labs/2/tweets/#{id}"
22
25
  params = {
23
- 'tweet.fields' => tweet_fields
26
+ 'tweet.fields' => tweet_fields.join(',')
24
27
  }.compact
25
28
 
26
29
  make_request(url: url, params: params)
27
30
  end
28
31
 
32
+ # @param [Array<String>] :ids the collection of requested Tweet IDs
33
+ # @param [Array<String>] :tweet_fields (["id", "author_id", "created_at", "lang", "public_metrics"]) the list of fields to retrieve for the given tweet
29
34
  def get_tweets(ids:, tweet_fields: DEFAULT_TWEET_FIELDS)
30
35
  url = 'https://api.twitter.com/labs/2/tweets'
31
36
  params = {
32
37
  'ids' => ids.join(','),
33
- 'tweet.fields' => tweet_fields
38
+ 'tweet.fields' => tweet_fields.join(',')
34
39
  }.compact
35
40
 
36
41
  make_request(url: url, params: params, is_collection: true)
37
42
  end
38
43
 
44
+ # @param [String] :id the ID of the requested User
45
+ # @param [Array<String>] :user_fields (["name", "username"]) the list of fields to retrieve for the given User
39
46
  def get_user(id:, user_fields: DEFAULT_USER_FIELDS)
40
47
  url = "https://api.twitter.com/labs/2/users/#{id}"
41
48
  params = {
42
- 'user.fields' => user_fields
49
+ 'user.fields' => user_fields.join(',')
43
50
  }.compact
44
51
 
45
52
  make_request(url: url, params: params)
46
53
  end
47
54
 
55
+ # @param [Array<String>] :ids the collection of requested User IDs
56
+ # @param [Array<String>] :user_fields (["name", "username"]) the list of fields to retrieve for the given User
48
57
  def get_users(ids:, user_fields: DEFAULT_USER_FIELDS)
49
58
  url = 'https://api.twitter.com/labs/2/users'
50
59
  params = {
51
60
  'ids' => ids.join(','),
52
- 'user.fields' => user_fields
61
+ 'user.fields' => user_fields.join(',')
53
62
  }.compact
54
63
 
55
64
  make_request(url: url, params: params, is_collection: true)
@@ -64,28 +73,33 @@ class TwitterLabsAPI
64
73
  request['Authorization'] = "Bearer #{bearer_token}"
65
74
  req_options = { use_ssl: uri.scheme == 'https' }
66
75
 
67
- response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
76
+ self.api_response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
68
77
  http.request(request)
69
78
  end
70
79
 
71
- is_collection ? handle_collection(response) : handle_single(response)
72
- end
80
+ raise TwitterLabsAPIError("#{api_response.code} #{api_response.msg}") unless api_response.is_a?(Net::HTTPSuccess)
81
+
82
+ self.parsed_response = JSON.parse(api_response.body)
73
83
 
74
- # TODO: handle non-api errs (e.g., timeouts)
75
- def handle_single(response)
76
- return JSON.parse(response.body)['data'].with_indifferent_access if response.is_a?(Net::HTTPSuccess)
84
+ handle_api_error if error_response?
77
85
 
78
- handle_api_error(response)
86
+ is_collection ? handle_collection : handle_single
79
87
  end
80
88
 
81
- def handle_collection(response)
82
- return JSON.parse(response.body)['data'].map(&:with_indifferent_access) if response.is_a?(Net::HTTPSuccess)
89
+ def error_response?
90
+ parsed_response.key?('errors')
91
+ end
92
+
93
+ def handle_single
94
+ parsed_response['data'].with_indifferent_access
95
+ end
83
96
 
84
- handle_api_error(response)
97
+ def handle_collection
98
+ parsed_response['data'].map(&:with_indifferent_access)
85
99
  end
86
100
 
87
- def handle_api_error(response)
88
- error = JSON.parse(response.body)
101
+ def handle_api_error
102
+ error = parsed_response['errors'].first
89
103
 
90
104
  raise TwitterLabsAPIError, "#{error['title']}: #{error['detail']} #{error['type']}"
91
105
  end
@@ -1,3 +1,3 @@
1
1
  class TwitterLabsAPI
2
- VERSION = '0.1.0'.freeze
2
+ VERSION = '0.2.0'.freeze
3
3
  end
@@ -26,5 +26,5 @@ Gem::Specification.new do |spec|
26
26
  spec.require_paths = ['lib']
27
27
 
28
28
  spec.add_development_dependency 'bundler', '~> 2.0'
29
- spec.add_development_dependency 'rake', '~> 10.0'
29
+ spec.add_development_dependency 'rake', '~> 13.0'
30
30
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twitter_labs_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tomholford
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '13.0'
41
41
  description:
42
42
  email:
43
43
  - tomholford@users.noreply.github.com
@@ -45,6 +45,7 @@ executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
+ - ".gitignore"
48
49
  - CHANGELOG.md
49
50
  - Gemfile
50
51
  - Gemfile.lock