twitter 4.7.0 → 4.8.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.
- 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�
|