oauth_twitter 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YWRkMTExYThmN2UzMzI3NTQ1MTk3YTRmZTExNDA2ODRlZTE3MzkzNQ==
5
- data.tar.gz: !binary |-
6
- ODdmNDdlNzYyNWFjOWM2MDliYjUxMGQ0NzNmY2ZlYzExZTIxOWRhOQ==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- MWE1YmY5MWI1NjdjZjQ0NmExOTMxMGE0ZGI0N2ZkMWQxNmI2OWRmOTM0MGU0
10
- NzdlNDdhNDNkNGUyMzJmYzBmNDdhZDQ0YzI0NDY0MDJkYTYzZGZkNmE3OTA1
11
- YmFjMWE3NjFmNjVlZDNhYWMyZmFjMTI3ZWUxYzBhNTIzYTE3NDQ=
12
- data.tar.gz: !binary |-
13
- YjIxNWE4Zjc3ZTM2N2ViODRmYWE0MDIzODEwZjI2YTdlNGQ0Yjc5YzdmNWU3
14
- YzYyMDJhZDZiNDFjZDQ5ZTc0ODgxYTkyNDk1YWNkZjE5OTYyOTJmZDc2ZjYy
15
- MjVhYzdiYTNkYzY2OGZlZTljOWY2YzRiODk4MjFhYmEyMDljODg=
2
+ SHA1:
3
+ metadata.gz: b1b8c63a971cd6a4d61293f511956d2057300e45
4
+ data.tar.gz: 1cb8fb868660669faa0d3b8793bed7ed18d31fe5
5
+ SHA512:
6
+ metadata.gz: 939af0a3d243ba9afc19631e7f557c17a3a8b0ed13d535c0e8020d0daa55bc976aebce63c600705b97b0ecf8f73ff77a8d9c8a3e5055bc52c5eeb7766017d528
7
+ data.tar.gz: c82ef4319da355a0633bbef4abe4ae31aeb28467de35b5b233fa1cb2992e913fc8b9ddceb7976a59a423e75a007c1614397d3fcd23d74b6f80604358529129b6
@@ -6,10 +6,7 @@ module OauthTwitter
6
6
  }
7
7
 
8
8
  def rate_limit_status(params={}, options={})
9
- query = params.clone
10
- oauth = oauth_params(true)
11
- response = send_request(:GET, PATH[:rate_limit_status], query, oauth)
12
- return results_with_error_explained(response, options)
9
+ return send_request(:GET, PATH[:rate_limit_status], params, true, options)
13
10
  end
14
11
 
15
12
  end
@@ -17,87 +17,51 @@ module OauthTwitter
17
17
  }
18
18
 
19
19
  def friendships_no_retweets_ids(params={}, options={})
20
- query = params.clone
21
- oauth = oauth_params(true)
22
- response = send_request(:GET, PATH[:friendships_no_retweets_ids], query, oauth)
23
- return results_with_error_explained(response, options)
20
+ return send_request(:GET, PATH[:friendships_no_retweets_ids], params, true, options)
24
21
  end
25
22
 
26
23
  def friends_ids(params={}, options={})
27
- query = params.clone
28
- oauth = oauth_params(true)
29
- response = send_request(:GET, PATH[:friends_ids], query, oauth)
30
- return results_with_error_explained(response, options)
24
+ return send_request(:GET, PATH[:friends_ids], params, true, options)
31
25
  end
32
26
 
33
27
  def followers_ids(params={}, options={})
34
- query = params.clone
35
- oauth = oauth_params(true)
36
- response = send_request(:GET, PATH[:followers_ids], query, oauth)
37
- return results_with_error_explained(response, options)
28
+ return send_request(:GET, PATH[:followers_ids], params, true, options)
38
29
  end
39
30
 
40
31
  def friendships_lookup(params={}, options={})
41
- query = params.clone
42
- oauth = oauth_params(true)
43
- response = send_request(:GET, PATH[:friendships_lookup], query, oauth)
44
- return results_with_error_explained(response, options)
32
+ return send_request(:GET, PATH[:friendships_lookup], params, true, options)
45
33
  end
46
34
 
47
35
  def friendships_incoming(params={}, options={})
48
- query = params.clone
49
- oauth = oauth_params(true)
50
- response = send_request(:GET, PATH[:friendships_incoming], query, oauth)
51
- return results_with_error_explained(response, options)
36
+ return send_request(:GET, PATH[:friendships_incoming], params, true, options)
52
37
  end
53
38
 
54
39
  def friendships_outgoing(params={}, options={})
55
- query = params.clone
56
- oauth = oauth_params(true)
57
- response = send_request(:GET, PATH[:friendships_outgoing], query, oauth)
58
- return results_with_error_explained(response, options)
40
+ return send_request(:GET, PATH[:friendships_outgoing], params, true, options)
59
41
  end
60
42
 
61
43
  def friendships_create(params={}, options={})
62
- query = params.clone
63
- oauth = oauth_params(true)
64
- response = send_request(:POST, PATH[:friendships_create], query, oauth)
65
- return results_with_error_explained(response, options)
44
+ return send_request(:GET, PATH[:friendships_create], params, true, options)
66
45
  end
67
46
 
68
47
  def friendships_destroy(params={}, options={})
69
- query = params.clone
70
- oauth = oauth_params(true)
71
- response = send_request(:POST, PATH[:friendships_destroy], query, oauth)
72
- return results_with_error_explained(response, options)
48
+ return send_request(:GET, PATH[:friendships_destroy], params, true, options)
73
49
  end
74
50
 
75
51
  def friendships_update(params={}, options={})
76
- query = params.clone
77
- oauth = oauth_params(true)
78
- response = send_request(:POST, PATH[:friendships_update], query, oauth)
79
- return results_with_error_explained(response, options)
52
+ return send_request(:GET, PATH[:friendships_update], params, true, options)
80
53
  end
81
54
 
82
55
  def friendships_show(params={}, options={})
83
- query = params.clone
84
- oauth = oauth_params(true)
85
- response = send_request(:GET, PATH[:friendships_show], query, oauth)
86
- return results_with_error_explained(response, options)
56
+ return send_request(:GET, PATH[:friendships_show], params, true, options)
87
57
  end
88
58
 
89
59
  def friends_list(params={}, options={})
90
- query = params.clone
91
- oauth = oauth_params(true)
92
- response = send_request(:GET, PATH[:friends_list], query, oauth)
93
- return results_with_error_explained(response, options)
60
+ return send_request(:GET, PATH[:friends_list], params, true, options)
94
61
  end
95
62
 
96
63
  def followers_list(params={}, options={})
97
- query = params.clone
98
- oauth = oauth_params(true)
99
- response = send_request(:GET, PATH[:followers_list], query, oauth)
100
- return results_with_error_explained(response, options)
64
+ return send_request(:GET, PATH[:followers_list], params, true, options)
101
65
  end
102
66
 
103
67
  end
@@ -9,31 +9,20 @@ module OauthTwitter
9
9
  }
10
10
 
11
11
  def oauth_authenticate(params={}, options={})
12
- query = params.clone
13
- oauth = oauth_params(true)
14
- response = send_request(:GET, PATH[:oauth_authenticate], query, oauth)
15
- return results_with_error_explained(response, options)
12
+ return send_request(:GET, PATH[:oauth_authenticate], params, true, options)
16
13
  end
17
14
 
18
15
  def oauth_authorize(params={}, options={})
19
- query = params.clone
20
- oauth = oauth_params(true)
21
- response = send_request(:GET, PATH[:oauth_authorize], query, oauth)
22
- return results_with_error_explained(response, options)
16
+ return send_request(:GET, PATH[:oauth_authorize], params, true, options)
23
17
  end
24
18
 
25
19
  def oauth_access_token(params={}, options={})
26
- query = params.clone
27
- oauth = oauth_params(true)
28
- response = send_request(:POST, PATH[:oauth_access_token], query, oauth)
29
- return results_with_error_explained(response, options)
20
+ return send_request(:POST, PATH[:oauth_access_token], params, true, options)
30
21
  end
31
22
 
32
23
  def oauth_request_token(params={}, options={})
33
24
  callback_url = params[:oauth_callback] || Config.oauth_callback
34
- oauth = oauth_params(false, {oauth_callback: callback_url})
35
- response = send_request(:POST, PATH[:oauth_request_token], nil, oauth)
36
- return results_with_error_explained(response, options)
25
+ return send_request(:POST, PATH[:oauth_request_token], {}, [false, {:oauth_callback => callback_url}], options)
37
26
  end
38
27
 
39
28
  end
@@ -43,13 +43,9 @@ module OauthTwitter
43
43
  # if count = 5, pages = 3, then it will return 5 * 3 = 15 tweets
44
44
  # from the user's timeline. Cursor stops if response no more reponse.
45
45
  #
46
- # :explain_error => [Bool] if true, will return a HTTP Code indicate
47
- # the error
46
+ # :detailed => [Bool] if false, will return just the data
48
47
  #
49
48
  # @return [Array] hash structured the same as Twitter's JSON response.
50
- #
51
- # if :explain_error => true, will return array like:
52
- # [json, response.body, response.code]
53
49
  def home_timeline(params={}, options={})
54
50
  query = params.clone
55
51
  return send_status_request(:home_timeline, query, options)
@@ -70,14 +66,13 @@ module OauthTwitter
70
66
  response = nil
71
67
  options[:pages] ||= 1
72
68
  options[:pages].times do |page_num|
73
- oauth = oauth_params(true)
74
- response = send_request(:GET, PATH[api_symbol], query, oauth)
75
- break unless response[0]
76
- break if response[1].empty?
77
- full_response += response[1]
78
- query[:max_id] = response[1].last['id'] - 1
69
+ response = send_request(:GET, PATH[api_symbol], query, true, options)
70
+ break unless response[:valid]
71
+ break if response[:data].empty?
72
+ full_response += response[:data]
73
+ query[:max_id] = response[:data].last['id'] - 1
79
74
  end
80
- return results_with_error_explained(response, options, full_response)
75
+ return assemble_multi_page_response(full_response, response, options)
81
76
  end
82
77
 
83
78
  end
@@ -17,62 +17,48 @@ module OauthTwitter
17
17
  query = params.clone
18
18
  users_array = query[:screen_name] || query[:user_id]
19
19
  users_array_type = (query[:screen_name]) ? :screen_name : :user_id
20
+
20
21
  # slice id_array for multiple request
21
22
  num_of_set = users_array.size / 100
22
23
  num_of_set += 1 if users_array.size % 100 > 0
23
24
  id_sets = num_of_set.times.map {|i| users_array.slice(i*100, (i+1)*100)}
25
+
24
26
  # send request
25
27
  full_response = []
26
28
  response = nil
27
29
  id_sets.each do |set|
28
- oauth = oauth_params(true)
29
30
  query[users_array_type] = set.join(',')
30
31
  method = set.size <= 10 ? :GET : :POST
31
- response = send_request(method, PATH[:users_lookup], query, oauth)
32
- if response[0]
33
- full_response += response[1]
32
+ response = send_request(method, PATH[:users_lookup], query, true)
33
+ if response[:valid]
34
+ full_response += response[:data]
34
35
  else
35
36
  break
36
37
  end
37
38
  end
38
- return results_with_error_explained(response, options, full_response)
39
+
40
+ # return
41
+ return assemble_multi_page_response(full_response, response, options)
39
42
  end
40
43
 
41
44
  def users_show(params, options={})
42
- query = params.clone
43
- oauth = oauth_params(true)
44
- response = send_request(:GET, PATH[:users_show], query, oauth)
45
- return results_with_error_explained(response, options)
45
+ return send_request(:GET, PATH[:users_show], params, true, options)
46
46
  end
47
47
 
48
48
  def users_search(params, options={})
49
- query = params.clone
50
- oauth = oauth_params(true)
51
- response = send_request(:GET, PATH[:users_search], query, oauth)
52
- return results_with_error_explained(response, options)
49
+ return send_request(:GET, PATH[:users_search], params, true, options)
53
50
  end
54
51
 
55
52
  def users_contributees(params, options={})
56
- query = params.clone
57
- oauth = oauth_params(true)
58
- response = send_request(:GET, PATH[:users_contributees], query, oauth)
59
- return results_with_error_explained(response, options)
53
+ return send_request(:GET, PATH[:users_contributees], params, true, options)
60
54
  end
61
55
 
62
56
  def users_contributors(params, options={})
63
- query = params.clone
64
- oauth = oauth_params(true)
65
- response = send_request(:GET, PATH[:users_contributors], query, oauth)
66
- return results_with_error_explained(response, options)
57
+ return send_request(:GET, PATH[:users_contributors], params, true, options)
67
58
  end
68
59
 
69
- ##
70
- #
71
60
  def users_profile_banner(params={}, options={})
72
- query = params.clone
73
- oauth = oauth_params(true)
74
- response = send_request(:GET, PATH[:users_profile_banner], query, oauth)
75
- return results_with_error_explained(response, options)
61
+ return send_request(:GET, PATH[:users_profile_banner], params, true, options)
76
62
  end
77
63
 
78
64
  end
@@ -7,10 +7,69 @@ require "multi_json"
7
7
 
8
8
  module OauthTwitter
9
9
  module Helper
10
+ ##
11
+ # Twitter API root url
12
+ HOST = "https://api.twitter.com"
13
+
14
+ ##
15
+ # Package data and send oauth request
16
+ #
17
+ # oauth = true : true - include oauth token
18
+ # false - do not include oauth token
19
+ # [false, {hash}] - include additional params
20
+ #
21
+ # options = {} : :detailed => fasle - return false if request failed,
22
+ # otherwise return just data
23
+ # --------------------------------------------------
24
+ def send_request(method, path, original_query, oauth=true, options={})
25
+ # generate signing key
26
+ signing_key_array = [ Config.consumer_secret ]
27
+
28
+ # generate oauth params
29
+ if !!oauth === oauth # boolean
30
+ oauth_params = generate_oauth_params(oauth)
31
+ signing_key_array.push((oauth ? self.oauth_token_secret : '' ))
32
+ else
33
+ oauth_params = generate_oauth_params(oauth[0], oauth[1])
34
+ signing_key_array.push((oauth[0] ? self.oauth_token_secret : '' ))
35
+ end
36
+
37
+ # filter out value == nil
38
+ query = original_query.select {|key, value| !value.nil?}
39
+
40
+ # generate base string
41
+ base_array = [ method.to_s.upcase, URI.encode_www_form_component(HOST + path), URI.encode_www_form_component(URI.encode_www_form((query ? oauth_params.merge(query) : oauth_params).sort)) ]
42
+
43
+ # generate signature
44
+ oauth_params[:oauth_signature] = sign(base_array, signing_key_array)
45
+
46
+ # generate HTTP request
47
+ uri = URI.parse(HOST + path)
48
+ https = Net::HTTP.new(uri.host, uri.port)
49
+ https.use_ssl = true
50
+ if method.to_s.upcase === 'GET'
51
+ uri.query = URI.encode_www_form(query) if query
52
+ request = Net::HTTP::Get.new(uri.request_uri)
53
+ elsif method.to_s.upcase === 'POST'
54
+ request = Net::HTTP::Post.new(uri.request_uri)
55
+ request.set_form_data(query) if query
56
+ end
57
+ request["Authorization"] = generate_oauth_header(oauth_params)
58
+
59
+ # retrive response
60
+ return parse_response(https.request(request), options)
61
+ end
62
+
63
+
64
+ # Protected
65
+ # ==================================================
66
+ protected
10
67
 
11
68
  ##
12
69
  # Generate oauth params
13
- def oauth_params(include_oauth_token=true, addional_oauth_params={})
70
+ #
71
+ # --------------------------------------------------
72
+ def generate_oauth_params(include_oauth_token=true, addional_oauth_params={})
14
73
  oauth = {
15
74
  :oauth_consumer_key => Config.consumer_key,
16
75
  :oauth_nonce => SecureRandom.hex(21),
@@ -18,101 +77,71 @@ module OauthTwitter
18
77
  :oauth_timestamp => Time.now.to_i,
19
78
  :oauth_version => "1.0"
20
79
  }
21
- oauth[:oauth_token] = self.oauth_token if include_oauth_token == true
80
+ oauth[:oauth_token] = self.oauth_token if include_oauth_token === true
22
81
  return oauth.merge(addional_oauth_params)
23
82
  end
24
83
 
25
84
  ##
26
- # percent_encode disallowed char
27
- RESERVED_CHARS = /[^a-zA-Z0-9\-\.\_\~]/
28
-
29
- ##
30
- # percent_encode strigns
31
- def self.percent_encode(raw)
32
- return URI.escape(raw.to_s, RESERVED_CHARS)
85
+ # Sign oauth params
86
+ #
87
+ # --------------------------------------------------
88
+ def sign(base_array, signing_key_array)
89
+ hex_str = OpenSSL::HMAC.hexdigest( OpenSSL::Digest::Digest.new('sha1'), signing_key_array.join('&'), base_array.join('&') )
90
+ binary_str = Base64.encode64( [hex_str].pack("H*") ).gsub(/\n/, "")
91
+ return URI.encode_www_form_component(binary_str)
33
92
  end
34
93
 
35
94
  ##
36
- # Twitter API root url
37
- HOST = "https://api.twitter.com"
95
+ # Generate header message for HTTP request
96
+ #
97
+ # --------------------------------------------------
98
+ def generate_oauth_header(signed_oauth)
99
+ return "OAuth " << signed_oauth.map {|key, val| "#{key}=\"#{val}\""}.join(",")
100
+ end
38
101
 
39
102
  ##
40
- # Helper method to send request to Twitter API
41
- # @param method [Symbol] HTTP method, support :GET or :POST
42
- # @param path [String] request url path
43
- # @param query [Hash] request parameters
44
- # @param oauth [Hash] oauth request header
103
+ # Parse response for cleaner outputs
45
104
  #
46
- # @return [Array] 0: indicate successful or not, 1: response content,
47
- # 2: error messages if any
48
- def send_request(method, path, query, oauth)
49
- # Make base_str and signing_key
50
- base_str = method.to_s.upcase << "&"
51
- base_str << Helper.percent_encode(HOST + path) << "&"
52
- hash = query ? oauth.merge(query) : oauth
53
- array = hash.sort.map {|key, val| Helper.percent_encode(key) + "=" + Helper.percent_encode(val)}
54
- base_str << Helper.percent_encode(array.join("&"))
55
- # Sign
56
- signing_key = String.new(Config.consumer_secret) << "&"
57
- signing_key << self.oauth_token_secret if hash[:oauth_token]
58
- signature = Helper.sign(base_str, signing_key)
59
- signed_oauth = oauth.merge(:oauth_signature => signature)
60
- # Header
61
- auth_header = Helper.auth_header(signed_oauth)
62
- # HTTP request
63
- uri = URI.parse(HOST + path)
64
- https = Net::HTTP.new(uri.host, uri.port)
65
- https.use_ssl = true
66
- case
67
- when method.to_s.upcase == "POST"
68
- request = Net::HTTP::Post.new(uri.request_uri)
69
- request.set_form_data(query) if query
70
- when method.to_s.upcase == "GET"
71
- uri.query = URI.encode_www_form(query) if query
72
- request = Net::HTTP::Get.new(uri.request_uri)
73
- end
74
- request["Authorization"] = auth_header
75
- ##
76
- # Might raise SocketError if no internet connection
77
- response = https.request(request)
78
- case response.code
79
- when "200"
105
+ # --------------------------------------------------
106
+ def parse_response(response, options={})
107
+ result = {}
108
+ begin
109
+ result[:data] = MultiJson.load(response.body)
110
+ rescue MultiJson::LoadError
80
111
  begin
81
- return true, MultiJson.load(response.body)
82
- rescue MultiJson::LoadError
83
- return true, Rack::Utils.parse_nested_query(response.body)
112
+ result[:data] = Hash[URI.decode_www_form(response.body)]
113
+ rescue ArgumentError
114
+ result[:data] = response.body
84
115
  end
116
+ end
117
+
118
+ if options[:detailed] === false
119
+ return result[:data] if response.code === '200'
120
+ return nil
85
121
  else
86
- return false, MultiJson.load(response.body), response.code
122
+ result[:valid] = response.code === '200' ? true : false
123
+ result[:code] = response.code.to_i
124
+ return result
87
125
  end
88
126
  end
89
127
 
90
128
  ##
91
- # Sign oauth params
92
- def self.sign(base_str, signing_key)
93
- hex_str = OpenSSL::HMAC.hexdigest(
94
- OpenSSL::Digest::Digest.new('sha1'),
95
- signing_key,
96
- base_str)
97
- binary_str = Base64.encode64( [hex_str].pack("H*") ).gsub(/\n/, "")
98
- return Helper.percent_encode( binary_str )
99
- end
100
-
101
- def self.auth_header(signed_oauth)
102
- params = signed_oauth.map { |key, val| "#{key}=\"#{val}\"" }
103
- return "OAuth " << params.join(",")
104
- end
105
-
106
- def results_with_error_explained(response, options, full_response=nil)
107
- if full_response && options[:explain_error] == true
108
- return response[0] ? [response[0], full_response] : (response + [full_response])
109
- elsif full_response
110
- return full_response
111
- elsif options[:explain_error] == true
112
- return response
129
+ # Asseble multi page response
130
+ #
131
+ # --------------------------------------------------
132
+ def assemble_multi_page_response(full_response, last_response, options={})
133
+ if options[:detailed] === false
134
+ result = last_response[:valid] ? full_response : last_response[:data]
113
135
  else
114
- return response[0] ? response[1] : false
136
+ result = {
137
+ :valid => last_response[:valid],
138
+ :code => last_response[:code],
139
+ :data => full_response
140
+ }
141
+ result[:message] = last_response[:data] unless last_response[:valid]
115
142
  end
143
+
144
+ return result
116
145
  end
117
146
 
118
147
  end
@@ -1,3 +1,3 @@
1
1
  module OauthTwitter
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oauth_twitter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daiwei Lu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-01 00:00:00.000000000 Z
11
+ date: 2013-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -28,28 +28,28 @@ dependencies:
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ! '>='
31
+ - - '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: '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
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rack
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ! '>='
45
+ - - '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: 1.4.5
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ! '>='
52
+ - - '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: 1.4.5
55
55
  - !ruby/object:Gem::Dependency
@@ -99,12 +99,12 @@ require_paths:
99
99
  - lib
100
100
  required_ruby_version: !ruby/object:Gem::Requirement
101
101
  requirements:
102
- - - ! '>='
102
+ - - '>='
103
103
  - !ruby/object:Gem::Version
104
104
  version: '0'
105
105
  required_rubygems_version: !ruby/object:Gem::Requirement
106
106
  requirements:
107
- - - ! '>='
107
+ - - '>='
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
110
  requirements: []
@@ -114,4 +114,3 @@ signing_key:
114
114
  specification_version: 4
115
115
  summary: Load data from Twitter API
116
116
  test_files: []
117
- has_rdoc: