twitter 4.7.0 → 4.8.0

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
@@ -1,3 +1,10 @@
1
+ 4.8.0
2
+ -----
3
+ * [Add `Twitter::SearchResults#refresh_url`](https://github.com/sferik/twitter/commit/6bf08c008de139aad3ec173461e8633bfa5a3bd8) ([@mustafaturan](https://twitter.com/mustafaturan))
4
+ * [Fix issue with wrong signature being generated when multipart data is posted](https://github.com/sferik/twitter/commit/65ab90a6d51755e5901434a3568f8163ca3e262f) ([@mustafaturan](https://twitter.com/mustafaturan))
5
+ * [Restore compatibility with Ruby 1.8.7](https://github.com/sferik/twitter/commit/fb63970c1bd19792955d092a38b6adf53b558ec7)
6
+ * [Remove undocumented methods, retired in the APIpocalypse](https://github.com/sferik/twitter/commit/cf6a91f8df833dce5bffc7a0292402860e7d4da7)
7
+
1
8
  4.7.0
2
9
  -----
3
10
  * [Add support for application-only authentication](https://github.com/sferik/twitter/pull/387) ([@paracycle](https://twitter.com/paracycle))
@@ -260,7 +260,7 @@ module Twitter
260
260
  # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
261
261
  # @return [Twitter::Cursor]
262
262
  # @overload followers(options={})
263
- # Returns an array of numeric IDs for every user the authenticated user is following
263
+ # Returns a cursored collection of user objects for users following the authenticated user.
264
264
  #
265
265
  # @param options [Hash] A customizable set of options.
266
266
  # @option options [Integer] :cursor (-1) Breaks the results into pages. This is recommended for users who are following many users. Provide a value of -1 to begin paging. Provide values as returned in the response body's next_cursor and previous_cursor attributes to page back and forth in the list.
@@ -269,7 +269,7 @@ module Twitter
269
269
  # @example Return the authenticated user's friends' IDs
270
270
  # Twitter.followers
271
271
  # @overload followers(user, options={})
272
- # Returns an array of numeric IDs for every user the specified user is following
272
+ # Returns a cursored collection of user objects for users following the specified user.
273
273
  #
274
274
  # @param user [Integer, String, Twitter::User] A Twitter user ID, screen name, or object.
275
275
  # @param options [Hash] A customizable set of options.
@@ -291,7 +291,7 @@ module Twitter
291
291
  # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
292
292
  # @return [Twitter::Cursor]
293
293
  # @overload friends(options={})
294
- # Returns an array of numeric IDs for every user the authenticated user is following
294
+ # Returns a cursored collection of user objects for every user the authenticated user is following (otherwise known as their "friends").
295
295
  #
296
296
  # @param options [Hash] A customizable set of options.
297
297
  # @option options [Integer] :cursor (-1) Breaks the results into pages. This is recommended for users who are following many users. Provide a value of -1 to begin paging. Provide values as returned in the response body's next_cursor and previous_cursor attributes to page back and forth in the list.
@@ -300,7 +300,7 @@ module Twitter
300
300
  # @example Return the authenticated user's friends' IDs
301
301
  # Twitter.friends
302
302
  # @overload friends(user, options={})
303
- # Returns an array of numeric IDs for every user the specified user is following
303
+ # Returns a cursored collection of user objects for every user the specified user is following (otherwise known as their "friends").
304
304
  #
305
305
  # @param user [Integer, String, Twitter::User] A Twitter user ID, screen name, or object.
306
306
  # @param options [Hash] A customizable set of options.
@@ -69,7 +69,7 @@ module Twitter
69
69
  def list_timeline(*args)
70
70
  arguments = Twitter::API::Arguments.new(args)
71
71
  merge_list!(arguments.options, arguments.pop)
72
- merge_owner!(arguments.options, arguments.pop || screen_name) unless arguments.options[:owner_id] || arguments.options[:owner_screen_name]
72
+ merge_owner!(arguments.options, arguments.pop)
73
73
  objects_from_response(Twitter::Tweet, :get, "/1.1/lists/statuses.json", arguments.options)
74
74
  end
75
75
 
@@ -541,14 +541,14 @@ module Twitter
541
541
  def list_from_response(request_method, path, args)
542
542
  arguments = Twitter::API::Arguments.new(args)
543
543
  merge_list!(arguments.options, arguments.pop)
544
- merge_owner!(arguments.options, arguments.pop || screen_name) unless arguments.options[:owner_id] || arguments.options[:owner_screen_name]
544
+ merge_owner!(arguments.options, arguments.pop)
545
545
  object_from_response(Twitter::List, request_method, path, arguments.options)
546
546
  end
547
547
 
548
548
  def cursor_from_response_with_list(request_method, path, args, calling_method)
549
549
  arguments = Twitter::API::Arguments.new(args)
550
550
  merge_list!(arguments.options, arguments.pop)
551
- merge_owner!(arguments.options, arguments.pop || screen_name) unless arguments.options[:owner_id] || arguments.options[:owner_screen_name]
551
+ merge_owner!(arguments.options, arguments.pop)
552
552
  cursor_from_response(:users, Twitter::User, request_method, path, arguments.options, calling_method)
553
553
  end
554
554
 
@@ -556,7 +556,7 @@ module Twitter
556
556
  arguments = Twitter::API::Arguments.new(args)
557
557
  merge_user!(arguments.options, arguments.pop)
558
558
  merge_list!(arguments.options, arguments.pop)
559
- merge_owner!(arguments.options, arguments.pop || screen_name) unless arguments.options[:owner_id] || arguments.options[:owner_screen_name]
559
+ merge_owner!(arguments.options, arguments.pop)
560
560
  send(request_method.to_sym, path, arguments.options)
561
561
  true
562
562
  rescue Twitter::Error::NotFound, Twitter::Error::Forbidden
@@ -567,7 +567,7 @@ module Twitter
567
567
  arguments = Twitter::API::Arguments.new(args)
568
568
  merge_user!(arguments.options, arguments.pop)
569
569
  merge_list!(arguments.options, arguments.pop)
570
- merge_owner!(arguments.options, arguments.pop || screen_name) unless arguments.options[:owner_id] || arguments.options[:owner_screen_name]
570
+ merge_owner!(arguments.options, arguments.pop)
571
571
  object_from_response(Twitter::List, request_method, path, arguments.options)
572
572
  end
573
573
 
@@ -575,7 +575,7 @@ module Twitter
575
575
  arguments = Twitter::API::Arguments.new(args)
576
576
  members = arguments.pop
577
577
  merge_list!(arguments.options, arguments.pop)
578
- merge_owner!(arguments.options, arguments.pop || screen_name) unless arguments.options[:owner_id] || arguments.options[:owner_screen_name]
578
+ merge_owner!(arguments.options, arguments.pop)
579
579
  members.flatten.each_slice(MAX_USERS_PER_REQUEST).threaded_map do |users|
580
580
  object_from_response(Twitter::List, request_method, path, merge_users(arguments.options, users))
581
581
  end.last
@@ -605,8 +605,11 @@ module Twitter
605
605
  # @param user[Integer, String, Twitter::User] A Twitter user ID, screen_name, or object.
606
606
  # @return [Hash]
607
607
  def merge_owner!(hash, user)
608
- merge_user!(hash, user, "owner")
609
- hash[:owner_id] = hash.delete(:owner_user_id) unless hash[:owner_user_id].nil?
608
+ unless hash[:owner_id] || hash[:owner_screen_name]
609
+ user ||= screen_name
610
+ merge_user!(hash, user, "owner")
611
+ hash[:owner_id] = hash.delete(:owner_user_id) unless hash[:owner_user_id].nil?
612
+ end
610
613
  hash
611
614
  end
612
615
 
@@ -10,38 +10,6 @@ module Twitter
10
10
  module Undocumented
11
11
  include Twitter::API::Utils
12
12
 
13
- # Returns activity about me
14
- #
15
- # @note Undocumented
16
- # @rate_limited Yes
17
- # @authentication Requires user context
18
- # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
19
- # @return [Array] An array of actions
20
- # @param options [Hash] A customizable set of options.
21
- # @option options [Integer] :count Specifies the number of records to retrieve. Must be less than or equal to 100.
22
- # @option options [Integer] :since_id Returns results with an ID greater than (that is, more recent than) the specified ID.
23
- # @example Return activity about me
24
- # Twitter.activity_about_me
25
- def activity_about_me(options={})
26
- objects_from_response(Twitter::ActionFactory, :get, "/i/activity/about_me.json", options)
27
- end
28
-
29
- # Returns activity by friends
30
- #
31
- # @note Undocumented
32
- # @rate_limited Yes
33
- # @authentication Requires user context
34
- # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid./
35
- # @return [Array] An array of actions
36
- # @param options [Hash] A customizable set of options.
37
- # @option options [Integer] :count Specifies the number of records to retrieve. Must be less than or equal to 100.
38
- # @option options [Integer] :since_id Returns results with an ID greater than (that is, more recent than) the specified ID.
39
- # @example Return activity by friends
40
- # Twitter.activity_by_friends
41
- def activity_by_friends(options={})
42
- objects_from_response(Twitter::ActionFactory, :get, "/i/activity/by_friends.json", options)
43
- end
44
-
45
13
  # @note Undocumented
46
14
  # @rate_limited Yes
47
15
  # @authentication Requires user context
@@ -20,7 +20,6 @@ require 'twitter/configurable'
20
20
  require 'twitter/error/client_error'
21
21
  require 'twitter/error/decode_error'
22
22
  require 'simple_oauth'
23
- require 'base64'
24
23
  require 'uri'
25
24
 
26
25
  module Twitter
@@ -86,7 +85,7 @@ module Twitter
86
85
  # @param path [String]
87
86
  # @param params [Hash]
88
87
  # @return [Proc]
89
- def request_setup(method, path, params)
88
+ def request_setup(method, path, params, signature_params)
90
89
  Proc.new do |request|
91
90
  if params.delete(:bearer_token_request)
92
91
  request.headers[:authorization] = bearer_token_credentials_auth_header
@@ -99,13 +98,13 @@ module Twitter
99
98
  end
100
99
  request.headers[:authorization] = bearer_auth_header
101
100
  else
102
- request.headers[:authorization] = oauth_auth_header(method, path, params).to_s
101
+ request.headers[:authorization] = oauth_auth_header(method, path, signature_params).to_s
103
102
  end
104
103
  end
105
104
  end
106
105
 
107
106
  def request(method, path, params={}, signature_params=params)
108
- request_setup = request_setup(method, path, params)
107
+ request_setup = request_setup(method, path, params, signature_params)
109
108
  connection.send(method.to_sym, path, params, &request_setup).env
110
109
  rescue Faraday::Error::ClientError
111
110
  raise Twitter::Error::ClientError
@@ -124,10 +123,14 @@ module Twitter
124
123
  #
125
124
  # @return [String]
126
125
  def bearer_token_credentials_auth_header
127
- basic_auth_token = Base64.strict_encode64("#{@consumer_key}:#{@consumer_secret}")
126
+ basic_auth_token = encode_value("#{@consumer_key}:#{@consumer_secret}")
128
127
  "Basic #{basic_auth_token}"
129
128
  end
130
129
 
130
+ def encode_value(value)
131
+ [value].pack("m0").gsub("\n", '')
132
+ end
133
+
131
134
  def bearer_auth_header
132
135
  "Bearer #{@bearer_token}"
133
136
  end
@@ -2,7 +2,7 @@ require 'twitter/error/client_error'
2
2
 
3
3
  module Twitter
4
4
  class Error
5
- # Raised when Twitter returns the HTTP status code 404
5
+ # Raised when Twitter returns the HTTP status code 422
6
6
  class UnprocessableEntity < Twitter::Error::ClientError
7
7
  HTTP_STATUS_CODE = 422
8
8
  end
@@ -63,5 +63,16 @@ module Twitter
63
63
  Faraday::Utils.parse_nested_query(@attrs[:search_metadata][:next_results][1..-1]).inject({}) { |memo, (k,v)| memo[k.to_sym] = v; memo} if next_results?
64
64
  end
65
65
  alias next_page next_results
66
+
67
+ # Returns a Hash of query parameters for the refresh URL in the search
68
+ #
69
+ # Returned Hash can be merged into the previous search options list
70
+ # to easily access the refresh page
71
+ #
72
+ # @return [Hash]
73
+ def refresh_url
74
+ Faraday::Utils.parse_nested_query(@attrs[:search_metadata][:refresh_url][1..-1]).inject({}) { |memo, (k,v)| memo[k.to_sym] = v; memo}
75
+ end
76
+ alias refresh_page refresh_url
66
77
  end
67
78
  end
@@ -1,7 +1,7 @@
1
1
  module Twitter
2
2
  class Version
3
3
  MAJOR = 4 unless defined? Twitter::Version::MAJOR
4
- MINOR = 7 unless defined? Twitter::Version::MINOR
4
+ MINOR = 8 unless defined? Twitter::Version::MINOR
5
5
  PATCH = 0 unless defined? Twitter::Version::PATCH
6
6
  PRE = nil unless defined? Twitter::Version::PRE
7
7
 
@@ -8,7 +8,7 @@ describe Twitter::API::OAuth do
8
8
 
9
9
  describe "#token" do
10
10
  before do
11
- # WebMock treats Basic Auth differently so we have to chack against the full url with credentials.
11
+ # WebMock treats Basic Auth differently so we have to chack against the full URL with credentials.
12
12
  @oauth2_token_url = "https://CK:CS@api.twitter.com/oauth2/token"
13
13
  stub_request(:post, @oauth2_token_url).with(:body => "grant_type=client_credentials").to_return(:body => fixture("bearer_token.json"), :headers => {:content_type => "application/json; charset=utf-8"})
14
14
  end
@@ -6,34 +6,6 @@ describe Twitter::API::Undocumented do
6
6
  @client = Twitter::Client.new
7
7
  end
8
8
 
9
- describe "#activity_about_me" do
10
- before do
11
- stub_get("/i/activity/about_me.json").to_return(:body => fixture("about_me.json"), :headers => {:content_type => "application/json; charset=utf-8"})
12
- end
13
- it "requests the correct resource" do
14
- @client.activity_about_me
15
- expect(a_get("/i/activity/about_me.json")).to have_been_made
16
- end
17
- it "returns activity about me" do
18
- activity_about_me = @client.activity_about_me
19
- expect(activity_about_me.first).to be_a Twitter::Action::Mention
20
- end
21
- end
22
-
23
- describe "#activity_by_friends" do
24
- before do
25
- stub_get("/i/activity/by_friends.json").to_return(:body => fixture("by_friends.json"), :headers => {:content_type => "application/json; charset=utf-8"})
26
- end
27
- it "requests the correct resource" do
28
- @client.activity_by_friends
29
- expect(a_get("/i/activity/by_friends.json")).to have_been_made
30
- end
31
- it "returns activity by friends" do
32
- activity_by_friends = @client.activity_by_friends
33
- expect(activity_by_friends.first).to be_a Twitter::Action::Favorite
34
- end
35
- end
36
-
37
9
  describe "#following_followers_of" do
38
10
  context "with a screen_name passed" do
39
11
  before do
@@ -173,6 +173,32 @@ describe Twitter::Client do
173
173
  expect(authorization.options[:token]).to eq "OT"
174
174
  expect(authorization.options[:token_secret]).to eq "OS"
175
175
  end
176
+ it "submits the correct auth header when no media is present" do
177
+ # We use static values for nounce and timestamp to get a stable signature
178
+ secret = {:consumer_key => 'CK', :consumer_secret => 'CS',
179
+ :token => 'OT', :token_secret => 'OS',
180
+ :nonce => 'b6ebe4c2a11af493f8a2290fe1296965', :timestamp => '1370968658'}
181
+ header = {"Authorization" => /oauth_signature="FbthwmgGq02iQw%2FuXGEWaL6V6eM%3D"/}
182
+
183
+ subject.stub(:credentials).and_return(secret)
184
+ stub_post("/1.1/statuses/update.json")
185
+ subject.update("Just a test")
186
+ expect(a_post("/1.1/statuses/update.json").
187
+ with(:headers => header)).to have_been_made
188
+ end
189
+ it "submits the correct auth header when media is present" do
190
+ # We use static values for nounce and timestamp to get a stable signature
191
+ secret = {:consumer_key => 'CK', :consumer_secret => 'CS',
192
+ :token => 'OT', :token_secret => 'OS',
193
+ :nonce => 'e08201ad0dab4897c99445056feefd95', :timestamp => '1370967652'}
194
+ header = {"Authorization" => /oauth_signature="9ziouUPwZT9IWWRbJL8r0BerKYA%3D"/}
195
+
196
+ subject.stub(:credentials).and_return(secret)
197
+ stub_post("/1.1/statuses/update_with_media.json")
198
+ subject.update_with_media("Just a test", fixture("pbjt.gif"))
199
+ expect(a_post("/1.1/statuses/update_with_media.json").
200
+ with(:headers => header)).to have_been_made
201
+ end
176
202
  end
177
203
 
178
204
  describe "#bearer_auth_header" do
@@ -191,7 +217,7 @@ describe Twitter::Client do
191
217
  it "creates the correct auth header with supplied consumer_key and consumer_secret" do
192
218
  uri = "/1.1/direct_messages.json"
193
219
  authorization = subject.send(:bearer_token_credentials_auth_header)
194
- expect(authorization).to eq "Basic #{Base64.strict_encode64("CK:CS")}"
220
+ expect(authorization).to eq "Basic Q0s6Q1M="
195
221
  end
196
222
  end
197
223
  end
@@ -113,10 +113,7 @@ describe Twitter::SearchResults do
113
113
  end
114
114
 
115
115
  describe "#next_results" do
116
- let(:next_results) {Twitter::SearchResults.new(:search_metadata =>
117
- {:next_results => "?max_id=249279667666817023&q=%23freebandnames&count=4&include_entities=1&result_type=mixed"
118
- }).next_results
119
- }
116
+ let(:next_results) {Twitter::SearchResults.new(:search_metadata => {:next_results => "?max_id=249279667666817023&q=%23freebandnames&count=4&include_entities=1&result_type=mixed"}).next_results}
120
117
 
121
118
  it "returns a hash of query parameters" do
122
119
  expect(next_results).to be_a Hash
@@ -127,4 +124,16 @@ describe Twitter::SearchResults do
127
124
  end
128
125
  end
129
126
 
127
+ describe "#refresh_url" do
128
+ let(:refresh_url) {Twitter::SearchResults.new(:search_metadata => {:refresh_url => "?since_id=249279667666817023&q=%23freebandnames&count=4&include_entities=1&result_type=recent"}).refresh_url}
129
+
130
+ it "returns a hash of query parameters" do
131
+ expect(refresh_url).to be_a Hash
132
+ end
133
+
134
+ it "returns a since_id" do
135
+ expect(refresh_url[:since_id]).to eq "249279667666817023"
136
+ end
137
+ end
138
+
130
139
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twitter
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.7.0
4
+ version: 4.8.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -40,7 +40,7 @@ cert_chain:
40
40
  U0xxV3ZRUnNCbHlwSGZoczZKSnVMbHlaUEdoVTNSL3YKU2YzbFZLcEJDV2dS
41
41
  cEdUdnk0NVhWcEIrNTl5MzNQSm1FdVExUFRFT1l2UXlhbzlVS01BQWFBTi83
42
42
  cVdRdGpsMApobHc9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
43
- date: 2013-05-30 00:00:00.000000000 Z
43
+ date: 2013-06-12 00:00:00.000000000 Z
44
44
  dependencies:
45
45
  - !ruby/object:Gem::Dependency
46
46
  name: faraday
metadata.gz.sig CHANGED
@@ -1 +1,2 @@
1
- O(�ӓa݌�i[fb��M�h��ĉ�eƆ��5�؄�$oWg�2Vf�:��� ���u�O���T>ܺ�����1
1
+ �x����N
2
+ c�ڴ��۝1������P?���Kݐnzx�A��փ@48ڏD�"S� �1d�T��ꍫ��䦐�T�2Y�Dm?�ͷ������?1~2X��L������� &���������[2[�s+n5�ӱ=7��x�Ƞ��w��"و�p�3м���>�=�� �R� ���Q�]p(`�P��?ö߀�j$���)�.��L�fM�0�HcD�ѽ�=�R�uȀzR2֓���ꔢ!hzb`uy�B�