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 +0 -0
- data/CHANGELOG.md +7 -0
- data/lib/twitter/api/friends_and_followers.rb +4 -4
- data/lib/twitter/api/lists.rb +11 -8
- data/lib/twitter/api/undocumented.rb +0 -32
- data/lib/twitter/client.rb +8 -5
- data/lib/twitter/error/unprocessable_entity.rb +1 -1
- data/lib/twitter/search_results.rb +11 -0
- data/lib/twitter/version.rb +1 -1
- data/spec/twitter/api/oauth_spec.rb +1 -1
- data/spec/twitter/api/undocumented_spec.rb +0 -28
- data/spec/twitter/client_spec.rb +27 -1
- data/spec/twitter/search_results_spec.rb +13 -4
- metadata +2 -2
- metadata.gz.sig +2 -1
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGELOG.md
CHANGED
@@ -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
|
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
|
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
|
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
|
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.
|
data/lib/twitter/api/lists.rb
CHANGED
@@ -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
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
609
|
-
|
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
|
data/lib/twitter/client.rb
CHANGED
@@ -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,
|
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 =
|
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
|
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
|
data/lib/twitter/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Twitter
|
2
2
|
class Version
|
3
3
|
MAJOR = 4 unless defined? Twitter::Version::MAJOR
|
4
|
-
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
|
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
|
data/spec/twitter/client_spec.rb
CHANGED
@@ -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
|
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.
|
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-
|
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
|
-
|
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�
|