twitter 4.3.0 → 4.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +10 -0
- data/CHANGELOG.md +123 -110
- data/CONTRIBUTING.md +51 -0
- data/README.md +17 -2
- data/lib/twitter/api/direct_messages.rb +3 -6
- data/lib/twitter/api/favorites.rb +6 -13
- data/lib/twitter/api/friends_and_followers.rb +76 -8
- data/lib/twitter/api/lists.rb +65 -36
- data/lib/twitter/api/places_and_geo.rb +3 -3
- data/lib/twitter/api/saved_searches.rb +2 -2
- data/lib/twitter/api/spam_reporting.rb +2 -2
- data/lib/twitter/api/suggested_users.rb +1 -1
- data/lib/twitter/api/timelines.rb +12 -8
- data/lib/twitter/api/tweets.rb +8 -12
- data/lib/twitter/api/undocumented.rb +3 -3
- data/lib/twitter/api/users.rb +16 -10
- data/lib/twitter/api/utils.rb +109 -30
- data/lib/twitter/base.rb +15 -5
- data/lib/twitter/basic_user.rb +0 -1
- data/lib/twitter/client.rb +16 -37
- data/lib/twitter/core_ext/enumerable.rb +2 -2
- data/lib/twitter/default.rb +5 -8
- data/lib/twitter/exceptable.rb +36 -0
- data/lib/twitter/factory.rb +4 -4
- data/lib/twitter/list.rb +0 -1
- data/lib/twitter/request/multipart_with_file.rb +5 -7
- data/lib/twitter/search_results.rb +10 -6
- data/lib/twitter/settings.rb +0 -1
- data/lib/twitter/source_user.rb +0 -7
- data/lib/twitter/target_user.rb +0 -1
- data/lib/twitter/tweet.rb +15 -17
- data/lib/twitter/user.rb +4 -14
- data/lib/twitter/version.rb +4 -4
- data/spec/fixtures/followers_list.json +1 -0
- data/spec/fixtures/friends_list.json +1 -0
- data/spec/fixtures/ids_list.json +1 -1
- data/spec/fixtures/ids_list2.json +1 -1
- data/spec/helper.rb +9 -8
- data/spec/twitter/action_factory_spec.rb +1 -1
- data/spec/twitter/api/favorites_spec.rb +2 -2
- data/spec/twitter/api/friends_and_followers_spec.rb +102 -2
- data/spec/twitter/api/spam_reporting_spec.rb +2 -2
- data/spec/twitter/api/tweets_spec.rb +2 -2
- data/spec/twitter/api/users_spec.rb +107 -49
- data/spec/twitter/base_spec.rb +1 -1
- data/spec/twitter/client_spec.rb +4 -4
- data/spec/twitter/cursor_spec.rb +2 -2
- data/spec/twitter/error/client_error_spec.rb +16 -5
- data/spec/twitter/error/server_error_spec.rb +1 -1
- data/spec/twitter/error_spec.rb +2 -2
- data/spec/twitter/geo_factory_spec.rb +1 -1
- data/spec/twitter/identifiable_spec.rb +2 -2
- data/spec/twitter/media_factory_spec.rb +1 -1
- data/spec/twitter/search_results_spec.rb +11 -0
- data/spec/twitter/tweet_spec.rb +11 -0
- data/twitter.gemspec +3 -2
- metadata +190 -173
- data/lib/twitter/core_ext/array.rb +0 -7
- data/lib/twitter/core_ext/hash.rb +0 -100
- data/lib/twitter/core_ext/string.rb +0 -10
data/lib/twitter/basic_user.rb
CHANGED
data/lib/twitter/client.rb
CHANGED
@@ -27,7 +27,6 @@ module Twitter
|
|
27
27
|
# @note All methods have been separated into modules and follow the same grouping used in {http://dev.twitter.com/doc the Twitter API Documentation}.
|
28
28
|
# @see http://dev.twitter.com/pages/every_developer
|
29
29
|
class Client
|
30
|
-
include Twitter::API
|
31
30
|
include Twitter::API::DirectMessages
|
32
31
|
include Twitter::API::Favorites
|
33
32
|
include Twitter::API::FriendsAndFollowers
|
@@ -67,57 +66,37 @@ module Twitter
|
|
67
66
|
|
68
67
|
# Perform an HTTP POST request
|
69
68
|
def post(path, params={})
|
70
|
-
|
69
|
+
signature_params = params.values.any?{|value| value.respond_to?(:to_io)} ? {} : params
|
70
|
+
request(:post, path, params, signature_params)
|
71
71
|
end
|
72
72
|
|
73
|
-
# Perform an HTTP
|
73
|
+
# Perform an HTTP PUT request
|
74
74
|
def put(path, params={})
|
75
75
|
request(:put, path, params)
|
76
76
|
end
|
77
77
|
|
78
78
|
private
|
79
79
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
def connection
|
84
|
-
@connection ||= Faraday.new(@endpoint, @connection_options.merge(:builder => @middleware))
|
85
|
-
end
|
86
|
-
|
87
|
-
# Perform an HTTP request
|
88
|
-
#
|
89
|
-
# @raise [Twitter::Error::ClientError, Twitter::Error::DecodeError]
|
90
|
-
def request(method, path, params={})
|
91
|
-
uri = URI(@endpoint) unless uri.respond_to?(:host)
|
92
|
-
uri += path
|
93
|
-
request_headers = {}
|
94
|
-
if credentials?
|
95
|
-
authorization = auth_header(method, uri, params)
|
96
|
-
request_headers[:authorization] = authorization.to_s
|
97
|
-
end
|
98
|
-
connection.url_prefix = @endpoint
|
99
|
-
response = connection.run_request(method.to_sym, path, nil, request_headers) do |request|
|
100
|
-
unless params.empty?
|
101
|
-
case request.method
|
102
|
-
when :post, :put
|
103
|
-
request.body = params
|
104
|
-
else
|
105
|
-
request.params.update(params)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
yield request if block_given?
|
80
|
+
def request(method, path, params={}, signature_params=params)
|
81
|
+
connection.send(method.to_sym, path, params) do |request|
|
82
|
+
request.headers[:authorization] = auth_header(method.to_sym, path, signature_params).to_s
|
109
83
|
end.env
|
110
|
-
response
|
111
84
|
rescue Faraday::Error::ClientError
|
112
85
|
raise Twitter::Error::ClientError
|
113
86
|
rescue MultiJson::DecodeError
|
114
87
|
raise Twitter::Error::DecodeError
|
115
88
|
end
|
116
89
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
90
|
+
# Returns a Faraday::Connection object
|
91
|
+
#
|
92
|
+
# @return [Faraday::Connection]
|
93
|
+
def connection
|
94
|
+
@connection ||= Faraday.new(@endpoint, @connection_options.merge(:builder => @middleware))
|
95
|
+
end
|
96
|
+
|
97
|
+
def auth_header(method, path, params={})
|
98
|
+
uri = URI(@endpoint + path)
|
99
|
+
SimpleOAuth::Header.new(method, uri, params, credentials)
|
121
100
|
end
|
122
101
|
|
123
102
|
end
|
data/lib/twitter/default.rb
CHANGED
@@ -2,7 +2,6 @@ require 'faraday'
|
|
2
2
|
require 'twitter/configurable'
|
3
3
|
require 'twitter/error/client_error'
|
4
4
|
require 'twitter/error/server_error'
|
5
|
-
require 'twitter/identity_map'
|
6
5
|
require 'twitter/request/multipart_with_file'
|
7
6
|
require 'twitter/response/parse_json'
|
8
7
|
require 'twitter/response/raise_error'
|
@@ -10,7 +9,7 @@ require 'twitter/version'
|
|
10
9
|
|
11
10
|
module Twitter
|
12
11
|
module Default
|
13
|
-
ENDPOINT = 'https://api.twitter.com' unless defined? ENDPOINT
|
12
|
+
ENDPOINT = 'https://api.twitter.com' unless defined? Twitter::Default::ENDPOINT
|
14
13
|
CONNECTION_OPTIONS = {
|
15
14
|
:headers => {
|
16
15
|
:accept => 'application/json',
|
@@ -20,8 +19,8 @@ module Twitter
|
|
20
19
|
:raw => true,
|
21
20
|
:ssl => {:verify => false},
|
22
21
|
:timeout => 10,
|
23
|
-
} unless defined? CONNECTION_OPTIONS
|
24
|
-
IDENTITY_MAP = false unless defined? IDENTITY_MAP
|
22
|
+
} unless defined? Twitter::Default::CONNECTION_OPTIONS
|
23
|
+
IDENTITY_MAP = false unless defined? Twitter::Default::IDENTITY_MAP
|
25
24
|
MIDDLEWARE = Faraday::Builder.new do |builder|
|
26
25
|
# Convert file uploads to Faraday::UploadIO objects
|
27
26
|
builder.use Twitter::Request::MultipartWithFile
|
@@ -37,7 +36,7 @@ module Twitter
|
|
37
36
|
builder.use Twitter::Response::RaiseError, Twitter::Error::ServerError
|
38
37
|
# Set Faraday's HTTP adapter
|
39
38
|
builder.adapter Faraday.default_adapter
|
40
|
-
end
|
39
|
+
end unless defined? Twitter::Default::MIDDLEWARE
|
41
40
|
|
42
41
|
class << self
|
43
42
|
|
@@ -66,7 +65,7 @@ module Twitter
|
|
66
65
|
ENV['TWITTER_OAUTH_TOKEN_SECRET']
|
67
66
|
end
|
68
67
|
|
69
|
-
# @note This is configurable in case you want to use
|
68
|
+
# @note This is configurable in case you want to use a Twitter-compatible endpoint.
|
70
69
|
# @see http://status.net/wiki/Twitter-compatible_API
|
71
70
|
# @see http://en.blog.wordpress.com/2009/12/12/twitter-api/
|
72
71
|
# @see http://staff.tumblr.com/post/287703110/api
|
@@ -76,12 +75,10 @@ module Twitter
|
|
76
75
|
ENDPOINT
|
77
76
|
end
|
78
77
|
|
79
|
-
# @return [Hash]
|
80
78
|
def connection_options
|
81
79
|
CONNECTION_OPTIONS
|
82
80
|
end
|
83
81
|
|
84
|
-
# @return [Twitter::IdentityMap]
|
85
82
|
def identity_map
|
86
83
|
IDENTITY_MAP
|
87
84
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Twitter
|
2
|
+
module Exceptable
|
3
|
+
|
4
|
+
private
|
5
|
+
|
6
|
+
# Return a hash that includes everything but the given keys.
|
7
|
+
#
|
8
|
+
# @param klass [Class]
|
9
|
+
# @param hash [Hash]
|
10
|
+
# @param key1 [Symbol]
|
11
|
+
# @param key2 [Symbol]
|
12
|
+
def fetch_or_new_without_self(klass, hash, key1, key2)
|
13
|
+
klass.fetch_or_new(hash.dup[key1].merge(key2 => except(hash, key1))) unless hash[key1].nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
# Return a hash that includes everything but the given keys.
|
17
|
+
#
|
18
|
+
# @param hash [Hash]
|
19
|
+
# @param key [Symbol]
|
20
|
+
# @return [Hash]
|
21
|
+
def except(hash, key)
|
22
|
+
except!(hash.dup, key)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Replaces the hash without the given keys.
|
26
|
+
#
|
27
|
+
# @param hash [Hash]
|
28
|
+
# @param key [Symbol]
|
29
|
+
# @return [Hash]
|
30
|
+
def except!(hash, key)
|
31
|
+
hash.delete(key)
|
32
|
+
hash
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
data/lib/twitter/factory.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'twitter/core_ext/string'
|
2
|
-
|
3
1
|
module Twitter
|
4
2
|
class Factory
|
5
3
|
|
@@ -10,8 +8,10 @@ module Twitter
|
|
10
8
|
# @return [Twitter::Action::Favorite, Twitter::Action::Follow, Twitter::Action::ListMemberAdded, Twitter::Action::Mention, Twitter::Action::Reply, Twitter::Action::Retweet]
|
11
9
|
def self.fetch_or_new(method, klass, attrs={})
|
12
10
|
return unless attrs
|
13
|
-
|
14
|
-
|
11
|
+
type = attrs.delete(method.to_sym)
|
12
|
+
if type
|
13
|
+
const_name = type.gsub(/\/(.?)/){"::#{$1.upcase}"}.gsub(/(?:^|_)(.)/){$1.upcase}
|
14
|
+
klass.const_get(const_name.to_sym).fetch_or_new(attrs)
|
15
15
|
else
|
16
16
|
raise ArgumentError, "argument must have :#{method} key"
|
17
17
|
end
|
data/lib/twitter/list.rb
CHANGED
@@ -10,14 +10,12 @@ module Twitter
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def call(env)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
env[:request_headers][CONTENT_TYPE] = self.class.mime_type
|
18
|
-
end
|
13
|
+
env[:body].each do |key, value|
|
14
|
+
if value.respond_to?(:to_io)
|
15
|
+
env[:body][key] = Faraday::UploadIO.new(value, mime_type(value.path), value.path)
|
16
|
+
env[:request_headers][CONTENT_TYPE] = self.class.mime_type
|
19
17
|
end
|
20
|
-
end
|
18
|
+
end if env[:body].is_a?(::Hash)
|
21
19
|
@app.call(env)
|
22
20
|
end
|
23
21
|
|
@@ -15,33 +15,37 @@ module Twitter
|
|
15
15
|
|
16
16
|
# @return [Float]
|
17
17
|
def completed_in
|
18
|
-
@attrs[:search_metadata][:completed_in]
|
18
|
+
@attrs[:search_metadata][:completed_in] if search_metadata?
|
19
19
|
end
|
20
20
|
|
21
21
|
# @return [Integer]
|
22
22
|
def max_id
|
23
|
-
@attrs[:search_metadata][:max_id]
|
23
|
+
@attrs[:search_metadata][:max_id] if search_metadata?
|
24
24
|
end
|
25
25
|
|
26
26
|
# @return [Integer]
|
27
27
|
def page
|
28
|
-
@attrs[:search_metadata][:page]
|
28
|
+
@attrs[:search_metadata][:page] if search_metadata?
|
29
29
|
end
|
30
30
|
|
31
31
|
# @return [String]
|
32
32
|
def query
|
33
|
-
@attrs[:search_metadata][:query]
|
33
|
+
@attrs[:search_metadata][:query] if search_metadata?
|
34
34
|
end
|
35
35
|
|
36
36
|
# @return [Integer]
|
37
37
|
def results_per_page
|
38
|
-
@attrs[:search_metadata][:results_per_page]
|
38
|
+
@attrs[:search_metadata][:results_per_page] if search_metadata?
|
39
39
|
end
|
40
40
|
alias rpp results_per_page
|
41
41
|
|
42
|
+
def search_metadata?
|
43
|
+
!@attrs[:search_metadata].nil?
|
44
|
+
end
|
45
|
+
|
42
46
|
# @return [Integer]
|
43
47
|
def since_id
|
44
|
-
@attrs[:search_metadata][:since_id]
|
48
|
+
@attrs[:search_metadata][:since_id] if search_metadata?
|
45
49
|
end
|
46
50
|
|
47
51
|
end
|
data/lib/twitter/settings.rb
CHANGED
data/lib/twitter/source_user.rb
CHANGED
@@ -4,12 +4,5 @@ module Twitter
|
|
4
4
|
class SourceUser < Twitter::BasicUser
|
5
5
|
attr_reader :all_replies, :blocking, :can_dm, :followed_by, :marked_spam,
|
6
6
|
:notifications_enabled, :want_retweets
|
7
|
-
alias all_replies? all_replies
|
8
|
-
alias blocking? blocking
|
9
|
-
alias can_dm? can_dm
|
10
|
-
alias followed_by? followed_by
|
11
|
-
alias marked_spam? marked_spam
|
12
|
-
alias notifications_enabled? notifications_enabled
|
13
|
-
alias want_retweets? want_retweets
|
14
7
|
end
|
15
8
|
end
|
data/lib/twitter/target_user.rb
CHANGED
data/lib/twitter/tweet.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require 'twitter/core_ext/hash'
|
2
1
|
require 'twitter/creatable'
|
3
2
|
require 'twitter/entity/hashtag'
|
4
3
|
require 'twitter/entity/url'
|
5
4
|
require 'twitter/entity/user_mention'
|
5
|
+
require 'twitter/exceptable'
|
6
6
|
require 'twitter/geo_factory'
|
7
7
|
require 'twitter/identity'
|
8
8
|
require 'twitter/media_factory'
|
@@ -13,18 +13,21 @@ require 'twitter/user'
|
|
13
13
|
module Twitter
|
14
14
|
class Tweet < Twitter::Identity
|
15
15
|
include Twitter::Creatable
|
16
|
+
include Twitter::Exceptable
|
16
17
|
attr_reader :favorited, :favoriters, :from_user_id, :from_user_name,
|
17
18
|
:in_reply_to_screen_name, :in_reply_to_attrs_id, :in_reply_to_status_id,
|
18
19
|
:in_reply_to_user_id, :iso_language_code, :profile_image_url,
|
19
20
|
:profile_image_url_https, :repliers, :retweeted, :retweeters, :source,
|
20
21
|
:text, :to_user, :to_user_id, :to_user_name, :truncated
|
21
22
|
alias in_reply_to_tweet_id in_reply_to_status_id
|
22
|
-
alias favorited? favorited
|
23
23
|
alias favourited favorited
|
24
|
-
alias favourited? favorited
|
24
|
+
alias favourited? favorited?
|
25
25
|
alias favouriters favoriters
|
26
|
-
|
27
|
-
|
26
|
+
|
27
|
+
# @return [Boolean]
|
28
|
+
def entities?
|
29
|
+
!@attrs[:entities].nil?
|
30
|
+
end
|
28
31
|
|
29
32
|
# @return [Integer]
|
30
33
|
def favoriters_count
|
@@ -121,7 +124,7 @@ module Twitter
|
|
121
124
|
|
122
125
|
# @return [Twitter::User]
|
123
126
|
def user
|
124
|
-
@user ||= Twitter::User
|
127
|
+
@user ||= fetch_or_new_without_self(Twitter::User, @attrs, :user, :status)
|
125
128
|
end
|
126
129
|
|
127
130
|
# @note Must include entities in your request for this method to work
|
@@ -130,30 +133,25 @@ module Twitter
|
|
130
133
|
@user_mentions ||= entities(Twitter::Entity::UserMention, :user_mentions)
|
131
134
|
end
|
132
135
|
|
133
|
-
|
134
|
-
|
135
|
-
!@attrs[:entities].nil?
|
136
|
+
def user?
|
137
|
+
!@attrs[:user].nil?
|
136
138
|
end
|
137
139
|
|
138
140
|
private
|
139
141
|
|
140
142
|
# @param klass [Class]
|
141
|
-
# @param
|
142
|
-
def entities(klass,
|
143
|
+
# @param key [Symbol]
|
144
|
+
def entities(klass, key)
|
143
145
|
if entities?
|
144
|
-
Array(@attrs[:entities][
|
146
|
+
Array(@attrs[:entities][key.to_sym]).map do |user_mention|
|
145
147
|
klass.fetch_or_new(user_mention)
|
146
148
|
end
|
147
149
|
else
|
148
|
-
warn "#{Kernel.caller.first}: To get #{
|
150
|
+
warn "#{Kernel.caller.first}: To get #{key.to_s.tr('_', ' ')}, you must pass `:include_entities => true` when requesting the #{self.class.name}."
|
149
151
|
[]
|
150
152
|
end
|
151
153
|
end
|
152
154
|
|
153
|
-
def user?
|
154
|
-
!@attrs[:user].nil?
|
155
|
-
end
|
156
|
-
|
157
155
|
end
|
158
156
|
|
159
157
|
Status = Tweet
|
data/lib/twitter/user.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
require 'twitter/basic_user'
|
2
|
-
require 'twitter/core_ext/hash'
|
3
2
|
require 'twitter/creatable'
|
3
|
+
require 'twitter/exceptable'
|
4
4
|
require 'twitter/tweet'
|
5
5
|
|
6
6
|
module Twitter
|
7
7
|
class User < Twitter::BasicUser
|
8
8
|
PROFILE_IMAGE_SUFFIX_REGEX = /_normal(\.gif|\.jpe?g|\.png)$/
|
9
9
|
include Twitter::Creatable
|
10
|
+
include Twitter::Exceptable
|
10
11
|
attr_reader :connections, :contributors_enabled, :default_profile,
|
11
12
|
:default_profile_image, :description, :favourites_count,
|
12
13
|
:follow_request_sent, :followers_count, :friends_count, :geo_enabled,
|
@@ -17,10 +18,6 @@ module Twitter
|
|
17
18
|
:profile_sidebar_fill_color, :profile_text_color,
|
18
19
|
:profile_use_background_image, :protected, :statuses_count, :time_zone,
|
19
20
|
:url, :utc_offset, :verified
|
20
|
-
alias contributors_enabled? contributors_enabled
|
21
|
-
alias default_profile? default_profile
|
22
|
-
alias default_profile_image? default_profile_image
|
23
|
-
alias follow_request_sent? follow_request_sent
|
24
21
|
alias favorite_count favourites_count
|
25
22
|
alias favoriters_count favourites_count
|
26
23
|
alias favorites_count favourites_count
|
@@ -28,20 +25,13 @@ module Twitter
|
|
28
25
|
alias favouriters_count favourites_count
|
29
26
|
alias follower_count followers_count
|
30
27
|
alias friend_count friends_count
|
31
|
-
alias geo_enabled? geo_enabled
|
32
|
-
alias is_translator? is_translator
|
33
|
-
alias notifications? notifications
|
34
|
-
alias profile_background_tile? profile_background_tile
|
35
|
-
alias profile_use_background_image? profile_use_background_image
|
36
|
-
alias protected? protected
|
37
28
|
alias status_count statuses_count
|
38
29
|
alias translator is_translator
|
39
|
-
alias translator? is_translator
|
30
|
+
alias translator? is_translator?
|
40
31
|
alias tweet_count statuses_count
|
41
32
|
alias tweets_count statuses_count
|
42
33
|
alias update_count statuses_count
|
43
34
|
alias updates_count statuses_count
|
44
|
-
alias verified? verified
|
45
35
|
|
46
36
|
# Return the URL to the user's profile banner image
|
47
37
|
#
|
@@ -93,7 +83,7 @@ module Twitter
|
|
93
83
|
|
94
84
|
# @return [Twitter::Tweet]
|
95
85
|
def status
|
96
|
-
@status ||= Twitter::Tweet
|
86
|
+
@status ||= fetch_or_new_without_self(Twitter::Tweet, @attrs, :status, :user)
|
97
87
|
end
|
98
88
|
|
99
89
|
def status?
|