twitter 4.8.1 → 5.0.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.
Files changed (215) hide show
  1. data/CHANGELOG.md +36 -0
  2. data/CONTRIBUTING.md +13 -15
  3. data/LICENSE.md +1 -1
  4. data/README.md +401 -261
  5. data/Rakefile +6 -0
  6. data/lib/twitter/arguments.rb +14 -0
  7. data/lib/twitter/base.rb +109 -89
  8. data/lib/twitter/client.rb +38 -115
  9. data/lib/twitter/configuration.rb +5 -2
  10. data/lib/twitter/core_ext/kernel.rb +5 -1
  11. data/lib/twitter/creatable.rb +7 -4
  12. data/lib/twitter/cursor.rb +57 -45
  13. data/lib/twitter/direct_message.rb +2 -11
  14. data/lib/twitter/entity/uri.rb +14 -0
  15. data/lib/twitter/enumerable.rb +15 -0
  16. data/lib/twitter/error/already_favorited.rb +1 -1
  17. data/lib/twitter/error/already_posted.rb +10 -0
  18. data/lib/twitter/error/already_retweeted.rb +1 -1
  19. data/lib/twitter/error/bad_gateway.rb +2 -3
  20. data/lib/twitter/error/bad_request.rb +2 -2
  21. data/lib/twitter/error/forbidden.rb +2 -2
  22. data/lib/twitter/error/gateway_timeout.rb +2 -3
  23. data/lib/twitter/error/internal_server_error.rb +2 -3
  24. data/lib/twitter/error/not_acceptable.rb +2 -2
  25. data/lib/twitter/error/not_found.rb +2 -2
  26. data/lib/twitter/error/service_unavailable.rb +2 -3
  27. data/lib/twitter/error/too_many_requests.rb +2 -2
  28. data/lib/twitter/error/unauthorized.rb +2 -2
  29. data/lib/twitter/error/unprocessable_entity.rb +2 -2
  30. data/lib/twitter/error.rb +65 -14
  31. data/lib/twitter/factory.rb +13 -12
  32. data/lib/twitter/geo.rb +2 -7
  33. data/lib/twitter/geo_factory.rb +11 -7
  34. data/lib/twitter/geo_results.rb +40 -0
  35. data/lib/twitter/identity.rb +4 -34
  36. data/lib/twitter/list.rb +21 -4
  37. data/lib/twitter/media/photo.rb +6 -4
  38. data/lib/twitter/media_factory.rb +11 -7
  39. data/lib/twitter/null_object.rb +25 -0
  40. data/lib/twitter/oembed.rb +3 -2
  41. data/lib/twitter/place.rb +15 -15
  42. data/lib/twitter/profile_banner.rb +3 -2
  43. data/lib/twitter/rate_limit.rb +4 -17
  44. data/lib/twitter/relationship.rb +2 -19
  45. data/lib/twitter/rest/api/direct_messages.rb +138 -0
  46. data/lib/twitter/rest/api/favorites.rb +115 -0
  47. data/lib/twitter/rest/api/friends_and_followers.rb +287 -0
  48. data/lib/twitter/rest/api/help.rb +58 -0
  49. data/lib/twitter/rest/api/lists.rb +498 -0
  50. data/lib/twitter/rest/api/oauth.rb +62 -0
  51. data/lib/twitter/rest/api/places_and_geo.rb +86 -0
  52. data/lib/twitter/rest/api/saved_searches.rb +93 -0
  53. data/lib/twitter/rest/api/search.rb +37 -0
  54. data/lib/twitter/rest/api/spam_reporting.rb +29 -0
  55. data/lib/twitter/rest/api/suggested_users.rb +51 -0
  56. data/lib/twitter/rest/api/timelines.rb +202 -0
  57. data/lib/twitter/rest/api/trends.rb +58 -0
  58. data/lib/twitter/rest/api/tweets.rb +291 -0
  59. data/lib/twitter/rest/api/undocumented.rb +52 -0
  60. data/lib/twitter/rest/api/users.rb +383 -0
  61. data/lib/twitter/rest/api/utils.rb +246 -0
  62. data/lib/twitter/rest/client.rb +175 -0
  63. data/lib/twitter/rest/request/multipart_with_file.rb +36 -0
  64. data/lib/twitter/rest/response/parse_error_json.rb +15 -0
  65. data/lib/twitter/rest/response/parse_json.rb +31 -0
  66. data/lib/twitter/{response → rest/response}/raise_error.rb +8 -11
  67. data/lib/twitter/search_results.rb +37 -21
  68. data/lib/twitter/settings.rb +1 -6
  69. data/lib/twitter/size.rb +2 -15
  70. data/lib/twitter/streaming/client.rb +89 -0
  71. data/lib/twitter/streaming/connection.rb +22 -0
  72. data/lib/twitter/streaming/event.rb +35 -0
  73. data/lib/twitter/streaming/friend_list.rb +13 -0
  74. data/lib/twitter/streaming/message_parser.rb +18 -0
  75. data/lib/twitter/streaming/response.rb +34 -0
  76. data/lib/twitter/suggestion.rb +5 -8
  77. data/lib/twitter/token.rb +11 -1
  78. data/lib/twitter/trend.rb +4 -8
  79. data/lib/twitter/trend_results.rb +65 -0
  80. data/lib/twitter/tweet.rb +43 -92
  81. data/lib/twitter/user.rb +72 -47
  82. data/lib/twitter/version.rb +4 -4
  83. data/lib/twitter.rb +4 -39
  84. data/spec/fixtures/already_posted.json +1 -0
  85. data/spec/fixtures/ids_list.json +1 -1
  86. data/spec/fixtures/ids_list2.json +1 -1
  87. data/spec/fixtures/request_token.txt +6 -0
  88. data/spec/fixtures/search.json +1 -1
  89. data/spec/fixtures/search_malformed.json +1 -1
  90. data/spec/fixtures/track_streaming.json +3 -0
  91. data/spec/fixtures/track_streaming_user.json +5 -0
  92. data/spec/helper.rb +8 -13
  93. data/spec/twitter/base_spec.rb +13 -103
  94. data/spec/twitter/basic_user_spec.rb +3 -3
  95. data/spec/twitter/configuration_spec.rb +1 -1
  96. data/spec/twitter/cursor_spec.rb +17 -35
  97. data/spec/twitter/direct_message_spec.rb +44 -11
  98. data/spec/twitter/entity/uri_spec.rb +75 -0
  99. data/spec/twitter/error_spec.rb +59 -11
  100. data/spec/twitter/geo/point_spec.rb +6 -6
  101. data/spec/twitter/geo/polygon_spec.rb +5 -5
  102. data/spec/twitter/geo_factory_spec.rb +4 -4
  103. data/spec/twitter/geo_results_spec.rb +35 -0
  104. data/spec/twitter/geo_spec.rb +6 -6
  105. data/spec/twitter/identifiable_spec.rb +5 -26
  106. data/spec/twitter/list_spec.rb +54 -11
  107. data/spec/twitter/media/photo_spec.rb +122 -6
  108. data/spec/twitter/media_factory_spec.rb +3 -3
  109. data/spec/twitter/null_object_spec.rb +27 -0
  110. data/spec/twitter/oembed_spec.rb +69 -45
  111. data/spec/twitter/place_spec.rb +84 -28
  112. data/spec/twitter/profile_banner_spec.rb +1 -1
  113. data/spec/twitter/rate_limit_spec.rb +8 -25
  114. data/spec/twitter/relationship_spec.rb +26 -12
  115. data/spec/twitter/{api → rest/api}/direct_messages_spec.rb +28 -15
  116. data/spec/twitter/{api → rest/api}/favorites_spec.rb +80 -7
  117. data/spec/twitter/{api → rest/api}/friends_and_followers_spec.rb +121 -152
  118. data/spec/twitter/{api → rest/api}/geo_spec.rb +9 -23
  119. data/spec/twitter/{api → rest/api}/help_spec.rb +6 -6
  120. data/spec/twitter/{api → rest/api}/lists_spec.rb +116 -95
  121. data/spec/twitter/{api → rest/api}/oauth_spec.rb +21 -10
  122. data/spec/twitter/{api → rest/api}/saved_searches_spec.rb +13 -13
  123. data/spec/twitter/{api → rest/api}/search_spec.rb +8 -9
  124. data/spec/twitter/{api → rest/api}/spam_reporting_spec.rb +3 -3
  125. data/spec/twitter/{api → rest/api}/suggested_users_spec.rb +5 -5
  126. data/spec/twitter/{api → rest/api}/timelines_spec.rb +9 -9
  127. data/spec/twitter/{api → rest/api}/trends_spec.rb +6 -6
  128. data/spec/twitter/rest/api/tweets_spec.rb +503 -0
  129. data/spec/twitter/{api → rest/api}/undocumented_spec.rb +19 -45
  130. data/spec/twitter/{api → rest/api}/users_spec.rb +64 -39
  131. data/spec/twitter/rest/client_spec.rb +193 -0
  132. data/spec/twitter/saved_search_spec.rb +14 -3
  133. data/spec/twitter/search_results_spec.rb +32 -45
  134. data/spec/twitter/settings_spec.rb +17 -6
  135. data/spec/twitter/size_spec.rb +5 -15
  136. data/spec/twitter/source_user_spec.rb +3 -3
  137. data/spec/twitter/streaming/client_spec.rb +92 -0
  138. data/spec/twitter/streaming/event_spec.rb +45 -0
  139. data/spec/twitter/suggestion_spec.rb +5 -15
  140. data/spec/twitter/target_user_spec.rb +3 -3
  141. data/spec/twitter/token_spec.rb +16 -0
  142. data/spec/twitter/trend_results_spec.rb +89 -0
  143. data/spec/twitter/trend_spec.rb +26 -13
  144. data/spec/twitter/tweet_spec.rb +137 -124
  145. data/spec/twitter/user_spec.rb +139 -80
  146. data/spec/twitter_spec.rb +0 -119
  147. data/twitter.gemspec +12 -6
  148. data.tar.gz.sig +0 -0
  149. metadata +197 -138
  150. metadata.gz.sig +0 -0
  151. data/lib/twitter/action/favorite.rb +0 -19
  152. data/lib/twitter/action/follow.rb +0 -30
  153. data/lib/twitter/action/list_member_added.rb +0 -39
  154. data/lib/twitter/action/mention.rb +0 -46
  155. data/lib/twitter/action/reply.rb +0 -27
  156. data/lib/twitter/action/retweet.rb +0 -27
  157. data/lib/twitter/action/tweet.rb +0 -20
  158. data/lib/twitter/action_factory.rb +0 -22
  159. data/lib/twitter/api/arguments.rb +0 -13
  160. data/lib/twitter/api/direct_messages.rb +0 -148
  161. data/lib/twitter/api/favorites.rb +0 -126
  162. data/lib/twitter/api/friends_and_followers.rb +0 -334
  163. data/lib/twitter/api/help.rb +0 -64
  164. data/lib/twitter/api/lists.rb +0 -618
  165. data/lib/twitter/api/oauth.rb +0 -44
  166. data/lib/twitter/api/places_and_geo.rb +0 -121
  167. data/lib/twitter/api/saved_searches.rb +0 -99
  168. data/lib/twitter/api/search.rb +0 -37
  169. data/lib/twitter/api/spam_reporting.rb +0 -30
  170. data/lib/twitter/api/suggested_users.rb +0 -55
  171. data/lib/twitter/api/timelines.rb +0 -214
  172. data/lib/twitter/api/trends.rb +0 -63
  173. data/lib/twitter/api/tweets.rb +0 -304
  174. data/lib/twitter/api/undocumented.rb +0 -97
  175. data/lib/twitter/api/users.rb +0 -439
  176. data/lib/twitter/api/utils.rb +0 -187
  177. data/lib/twitter/configurable.rb +0 -96
  178. data/lib/twitter/default.rb +0 -102
  179. data/lib/twitter/entity/url.rb +0 -9
  180. data/lib/twitter/error/client_error.rb +0 -35
  181. data/lib/twitter/error/decode_error.rb +0 -9
  182. data/lib/twitter/error/identity_map_key_error.rb +0 -9
  183. data/lib/twitter/error/server_error.rb +0 -28
  184. data/lib/twitter/exceptable.rb +0 -36
  185. data/lib/twitter/identity_map.rb +0 -22
  186. data/lib/twitter/request/multipart_with_file.rb +0 -34
  187. data/lib/twitter/response/parse_json.rb +0 -25
  188. data/spec/fixtures/about_me.json +0 -1
  189. data/spec/fixtures/activity_summary.json +0 -1
  190. data/spec/fixtures/bad_gateway.json +0 -1
  191. data/spec/fixtures/bad_request.json +0 -1
  192. data/spec/fixtures/by_friends.json +0 -1
  193. data/spec/fixtures/end_session.json +0 -1
  194. data/spec/fixtures/forbidden.json +0 -1
  195. data/spec/fixtures/internal_server_error.json +0 -1
  196. data/spec/fixtures/not_acceptable.json +0 -1
  197. data/spec/fixtures/phoenix_search.phoenix +0 -1
  198. data/spec/fixtures/resolve.json +0 -1
  199. data/spec/fixtures/service_unavailable.json +0 -1
  200. data/spec/fixtures/totals.json +0 -1
  201. data/spec/fixtures/trends.json +0 -1
  202. data/spec/fixtures/unauthorized.json +0 -1
  203. data/spec/fixtures/video_facets.json +0 -1
  204. data/spec/twitter/action/favorite_spec.rb +0 -29
  205. data/spec/twitter/action/follow_spec.rb +0 -29
  206. data/spec/twitter/action/list_member_added_spec.rb +0 -41
  207. data/spec/twitter/action/mention_spec.rb +0 -52
  208. data/spec/twitter/action/reply_spec.rb +0 -41
  209. data/spec/twitter/action/retweet_spec.rb +0 -41
  210. data/spec/twitter/action_factory_spec.rb +0 -35
  211. data/spec/twitter/action_spec.rb +0 -16
  212. data/spec/twitter/api/tweets_spec.rb +0 -285
  213. data/spec/twitter/client_spec.rb +0 -223
  214. data/spec/twitter/error/client_error_spec.rb +0 -23
  215. data/spec/twitter/error/server_error_spec.rb +0 -20
data/Rakefile CHANGED
@@ -7,5 +7,11 @@ RSpec::Core::RakeTask.new(:spec)
7
7
  task :test => :spec
8
8
  task :default => :spec
9
9
 
10
+ task :erd do
11
+ `bundle exec ruby ./etc/erd.rb > ./etc/erd.dot`
12
+ `dot -Tpng ./etc/erd.dot -o ./etc/erd.png`
13
+ `open ./etc/erd.png`
14
+ end
15
+
10
16
  require 'yard'
11
17
  YARD::Rake::YardocTask.new
@@ -0,0 +1,14 @@
1
+ module Twitter
2
+ class Arguments < Array
3
+ attr_reader :options
4
+
5
+ # Initializes a new Arguments object
6
+ #
7
+ # @return [Twitter::Arguments]
8
+ def initialize(args)
9
+ @options = args.last.is_a?(::Hash) ? args.pop : {}
10
+ super(args)
11
+ end
12
+
13
+ end
14
+ end
data/lib/twitter/base.rb CHANGED
@@ -1,75 +1,116 @@
1
- require 'twitter/error/identity_map_key_error'
1
+ require 'forwardable'
2
+ require 'memoizable'
3
+ require 'twitter/null_object'
4
+ require 'uri'
2
5
 
3
6
  module Twitter
4
7
  class Base
5
- # Define methods that retrieve the value from an initialized instance variable Hash, using the attribute as a key
6
- #
7
- # @param attrs [Array, Set, Symbol]
8
- def self.attr_reader(*attrs)
9
- mod = Module.new do
10
- attrs.each do |attribute|
11
- define_method attribute do
12
- @attrs[attribute.to_sym]
13
- end
14
- define_method "#{attribute}?" do
15
- !!@attrs[attribute.to_sym]
16
- end
8
+ extend Forwardable
9
+ include Memoizable
10
+ attr_reader :attrs
11
+ alias to_h attrs
12
+ alias to_hash attrs
13
+ alias to_hsh attrs
14
+
15
+ class << self
16
+
17
+ # Construct an object from a response hash
18
+ #
19
+ # @param response [Hash]
20
+ # @return [Twitter::Base]
21
+ def from_response(response={})
22
+ new(response[:body])
23
+ end
24
+
25
+ # Define methods that retrieve the value from attributes
26
+ #
27
+ # @param attrs [Array, Symbol]
28
+ def attr_reader(*attrs)
29
+ attrs.each do |attr|
30
+ define_attribute_method(attr)
31
+ define_predicate_method(attr)
17
32
  end
18
33
  end
19
- const_set(:Attributes, mod)
20
- include mod
21
- end
22
34
 
23
- # return [Twitter::IdentityMap]
24
- def self.identity_map
25
- return unless Twitter.identity_map
26
- @identity_map = Twitter.identity_map.new unless defined?(@identity_map) && @identity_map.class == Twitter.identity_map
27
- @identity_map
28
- end
35
+ # Define object methods from attributes
36
+ #
37
+ # @param klass [Symbol]
38
+ # @param key1 [Symbol]
39
+ # @param key2 [Symbol]
40
+ def object_attr_reader(klass, key1, key2=nil)
41
+ define_attribute_method(key1, klass, key2)
42
+ define_predicate_method(key1)
43
+ end
29
44
 
30
- # Retrieves an object from the identity map.
31
- #
32
- # @param attrs [Hash]
33
- # @return [Twitter::Base]
34
- def self.fetch(attrs)
35
- return unless identity_map
36
- if object = identity_map.fetch(Marshal.dump(attrs))
37
- return object
45
+ # Define URI methods from attributes
46
+ #
47
+ # @param attrs [Array, Symbol]
48
+ def uri_attr_reader(*attrs)
49
+ attrs.each do |uri_key|
50
+ array = uri_key.to_s.split("_")
51
+ index = array.index("uri")
52
+ array[index] = "url"
53
+ url_key = array.join("_").to_sym
54
+ define_uri_method(uri_key, url_key)
55
+ alias_method(url_key, uri_key)
56
+ define_predicate_method(uri_key, url_key)
57
+ alias_method(:"#{url_key}?", :"#{uri_key}?")
58
+ end
38
59
  end
39
- return yield if block_given?
40
- raise Twitter::Error::IdentityMapKeyError, "key not found"
41
- end
42
60
 
43
- # Stores an object in the identity map.
44
- #
45
- # @param object [Object]
46
- # @return [Twitter::Base]
47
- def self.store(object)
48
- return object unless identity_map
49
- identity_map.store(Marshal.dump(object.attrs), object)
50
- end
61
+ # Define display_uri attribute methods
62
+ def display_uri_attr_reader
63
+ define_attribute_method(:display_url)
64
+ alias_method(:display_uri, :display_url)
65
+ define_predicate_method(:display_uri, :display_url)
66
+ alias_method(:display_url?, :display_uri?)
67
+ end
51
68
 
52
- # Returns a new object based on the response hash
53
- #
54
- # @param response [Hash]
55
- # @return [Twitter::Base]
56
- def self.from_response(response={})
57
- fetch_or_new(response[:body])
58
- end
69
+ private
59
70
 
60
- # Retrieves an object from the identity map, or stores it in the
61
- # identity map if it doesn't already exist.
62
- #
63
- # @param attrs [Hash]
64
- # @return [Twitter::Base]
65
- def self.fetch_or_new(attrs={})
66
- return unless attrs
67
- return new(attrs) unless identity_map
71
+ # Dynamically define a method for a URI
72
+ #
73
+ # @param key1 [Symbol]
74
+ # @param key2 [Symbol]
75
+ def define_uri_method(key1, key2)
76
+ define_method(key1) do ||
77
+ URI.parse(@attrs[key2]) if @attrs[key2]
78
+ end
79
+ memoize(key1)
80
+ end
81
+
82
+ # Dynamically define a method for an attribute
83
+ #
84
+ # @param key1 [Symbol]
85
+ # @param klass [Symbol]
86
+ # @param key2 [Symbol]
87
+ def define_attribute_method(key1, klass=nil, key2=nil)
88
+ define_method(key1) do ||
89
+ if klass.nil?
90
+ @attrs[key1]
91
+ else
92
+ if @attrs[key1]
93
+ attrs = attrs_for_object(key1, key2)
94
+ Twitter.const_get(klass).new(attrs)
95
+ else
96
+ NullObject.new
97
+ end
98
+ end
99
+ end
100
+ memoize(key1)
101
+ end
68
102
 
69
- fetch(attrs) do
70
- object = new(attrs)
71
- store(object)
103
+ # Dynamically define a predicate method for an attribute
104
+ #
105
+ # @param key1 [Symbol]
106
+ # @param key2 [Symbol]
107
+ def define_predicate_method(key1, key2=key1)
108
+ define_method(:"#{key1}?") do ||
109
+ !!@attrs[key2]
110
+ end
111
+ memoize(:"#{key1}?")
72
112
  end
113
+
73
114
  end
74
115
 
75
116
  # Initializes a new object
@@ -77,7 +118,7 @@ module Twitter
77
118
  # @param attrs [Hash]
78
119
  # @return [Twitter::Base]
79
120
  def initialize(attrs={})
80
- @attrs = attrs
121
+ @attrs = attrs || {}
81
122
  end
82
123
 
83
124
  # Fetches an attribute of an object using hash notation
@@ -89,36 +130,15 @@ module Twitter
89
130
  nil
90
131
  end
91
132
 
92
- # Retrieve the attributes of an object
93
- #
94
- # @return [Hash]
95
- def attrs
96
- @attrs
97
- end
98
- alias to_hash attrs
133
+ private
99
134
 
100
- # Update the attributes of an object
101
- #
102
- # @param attrs [Hash]
103
- # @return [Twitter::Base]
104
- def update(attrs)
105
- @attrs.update(attrs)
106
- self
107
- end
108
-
109
- protected
110
-
111
- # @param attr [Symbol]
112
- # @param other [Twitter::Base]
113
- # @return [Boolean]
114
- def attr_equal(attr, other)
115
- self.class == other.class && !other.send(attr).nil? && send(attr) == other.send(attr)
116
- end
117
-
118
- # @param other [Twitter::Base]
119
- # @return [Boolean]
120
- def attrs_equal(other)
121
- self.class == other.class && !other.attrs.empty? && attrs == other.attrs
135
+ def attrs_for_object(key1, key2=nil)
136
+ if key2.nil?
137
+ @attrs[key1]
138
+ else
139
+ attrs = @attrs.dup
140
+ attrs.delete(key1).merge(key2 => attrs)
141
+ end
122
142
  end
123
143
 
124
144
  end
@@ -1,147 +1,70 @@
1
- require 'faraday'
2
- require 'multi_json'
3
- require 'twitter/api/direct_messages'
4
- require 'twitter/api/favorites'
5
- require 'twitter/api/friends_and_followers'
6
- require 'twitter/api/help'
7
- require 'twitter/api/lists'
8
- require 'twitter/api/oauth'
9
- require 'twitter/api/places_and_geo'
10
- require 'twitter/api/saved_searches'
11
- require 'twitter/api/search'
12
- require 'twitter/api/spam_reporting'
13
- require 'twitter/api/suggested_users'
14
- require 'twitter/api/timelines'
15
- require 'twitter/api/trends'
16
- require 'twitter/api/tweets'
17
- require 'twitter/api/undocumented'
18
- require 'twitter/api/users'
19
- require 'twitter/configurable'
20
- require 'twitter/error/client_error'
21
- require 'twitter/error/decode_error'
22
1
  require 'simple_oauth'
2
+ require 'twitter/version'
23
3
  require 'uri'
24
4
 
25
5
  module Twitter
26
- # Wrapper for the Twitter REST API
27
- #
28
- # @note All methods have been separated into modules and follow the same grouping used in {http://dev.twitter.com/doc the Twitter API Documentation}.
29
- # @see http://dev.twitter.com/pages/every_developer
30
6
  class Client
31
- include Twitter::API::DirectMessages
32
- include Twitter::API::Favorites
33
- include Twitter::API::FriendsAndFollowers
34
- include Twitter::API::Help
35
- include Twitter::API::Lists
36
- include Twitter::API::OAuth
37
- include Twitter::API::PlacesAndGeo
38
- include Twitter::API::SavedSearches
39
- include Twitter::API::Search
40
- include Twitter::API::SpamReporting
41
- include Twitter::API::SuggestedUsers
42
- include Twitter::API::Timelines
43
- include Twitter::API::Trends
44
- include Twitter::API::Tweets
45
- include Twitter::API::Undocumented
46
- include Twitter::API::Users
47
- include Twitter::Configurable
7
+ attr_accessor :access_token, :access_token_secret, :consumer_key, :consumer_secret
8
+ alias oauth_token access_token
9
+ alias oauth_token= access_token=
10
+ alias oauth_token_secret access_token_secret
11
+ alias oauth_token_secret= access_token_secret=
48
12
 
49
13
  # Initializes a new Client object
50
14
  #
51
15
  # @param options [Hash]
52
16
  # @return [Twitter::Client]
53
17
  def initialize(options={})
54
- Twitter::Configurable.keys.each do |key|
55
- instance_variable_set(:"@#{key}", options[key] || Twitter.instance_variable_get(:"@#{key}"))
18
+ options.each do |key, value|
19
+ send(:"#{key}=", value)
56
20
  end
21
+ yield self if block_given?
22
+ validate_credential_type!
57
23
  end
58
24
 
59
- # Perform an HTTP DELETE request
60
- def delete(path, params={})
61
- request(:delete, path, params)
25
+ # @return [Boolean]
26
+ def user_token?
27
+ !!(access_token && access_token_secret)
62
28
  end
63
29
 
64
- # Perform an HTTP GET request
65
- def get(path, params={})
66
- request(:get, path, params)
30
+ # @return [String]
31
+ def user_agent
32
+ @user_agent ||= "Twitter Ruby Gem #{Twitter::Version}"
67
33
  end
68
34
 
69
- # Perform an HTTP POST request
70
- def post(path, params={})
71
- signature_params = params.values.any?{|value| value.respond_to?(:to_io)} ? {} : params
72
- request(:post, path, params, signature_params)
35
+ # @return [Hash]
36
+ def credentials
37
+ {
38
+ :consumer_key => consumer_key,
39
+ :consumer_secret => consumer_secret,
40
+ :token => access_token,
41
+ :token_secret => access_token_secret,
42
+ }
73
43
  end
74
44
 
75
- # Perform an HTTP PUT request
76
- def put(path, params={})
77
- request(:put, path, params)
45
+ # @return [Boolean]
46
+ def credentials?
47
+ credentials.values.all?
78
48
  end
79
49
 
80
50
  private
81
51
 
82
- # Returns a proc that can be used to setup the Faraday::Request headers
83
- #
84
- # @param method [Symbol]
85
- # @param path [String]
86
- # @param params [Hash]
87
- # @return [Proc]
88
- def request_setup(method, path, params, signature_params)
89
- Proc.new do |request|
90
- if params.delete(:bearer_token_request)
91
- request.headers[:authorization] = bearer_token_credentials_auth_header
92
- request.headers[:content_type] = 'application/x-www-form-urlencoded; charset=UTF-8'
93
- request.headers[:accept] = '*/*' # It is important we set this, otherwise we get an error.
94
- elsif params.delete(:app_auth) || !user_token?
95
- unless bearer_token?
96
- @bearer_token = token
97
- Twitter.client.bearer_token = @bearer_token if Twitter.client?
98
- end
99
- request.headers[:authorization] = bearer_auth_header
100
- else
101
- request.headers[:authorization] = oauth_auth_header(method, path, signature_params).to_s
102
- end
103
- end
104
- end
105
-
106
- def request(method, path, params={}, signature_params=params)
107
- request_setup = request_setup(method, path, params, signature_params)
108
- connection.send(method.to_sym, path, params, &request_setup).env
109
- rescue Faraday::Error::ClientError
110
- raise Twitter::Error::ClientError
111
- rescue MultiJson::DecodeError
112
- raise Twitter::Error::DecodeError
113
- end
114
-
115
- # Returns a Faraday::Connection object
116
- #
117
- # @return [Faraday::Connection]
118
- def connection
119
- @connection ||= Faraday.new(@endpoint, @connection_options.merge(:builder => @middleware))
120
- end
121
-
122
- # Generates authentication header for a bearer token request
52
+ # Ensures that all credentials set during configuration are of a
53
+ # valid type. Valid types are String and Symbol.
123
54
  #
124
- # @return [String]
125
- def bearer_token_credentials_auth_header
126
- basic_auth_token = encode_value("#{@consumer_key}:#{@consumer_secret}")
127
- "Basic #{basic_auth_token}"
128
- end
129
-
130
- def encode_value(value)
131
- [value].pack("m0").gsub("\n", '')
132
- end
133
-
134
- def bearer_auth_header
135
- if @bearer_token.is_a?(Twitter::Token) && @bearer_token.token_type == "bearer"
136
- "Bearer #{@bearer_token.access_token}"
137
- else
138
- "Bearer #{@bearer_token}"
55
+ # @raise [Twitter::Error::ConfigurationError] Error is raised when
56
+ # supplied twitter credentials are not a String or Symbol.
57
+ def validate_credential_type!
58
+ credentials.each do |credential, value|
59
+ next if value.nil?
60
+ raise(Error::ConfigurationError, "Invalid #{credential} specified: #{value.inspect} must be a string or symbol.") unless value.is_a?(String) || value.is_a?(Symbol)
139
61
  end
140
62
  end
141
63
 
142
- def oauth_auth_header(method, path, params={})
143
- uri = URI(@endpoint + path)
64
+ def oauth_auth_header(method, uri, params={})
65
+ uri = URI.parse(uri)
144
66
  SimpleOAuth::Header.new(method, uri, params, credentials)
145
67
  end
68
+
146
69
  end
147
70
  end
@@ -4,16 +4,19 @@ module Twitter
4
4
  class Configuration < Twitter::Base
5
5
  attr_reader :characters_reserved_per_media, :max_media_per_upload,
6
6
  :non_username_paths, :photo_size_limit, :short_url_length, :short_url_length_https
7
+ alias short_uri_length short_url_length
8
+ alias short_uri_length_https short_url_length_https
7
9
 
8
10
  # Returns an array of photo sizes
9
11
  #
10
12
  # @return [Array<Twitter::Size>]
11
13
  def photo_sizes
12
- @photo_sizes ||= Array(@attrs[:photo_sizes]).inject({}) do |object, (key, value)|
13
- object[key] = Twitter::Size.fetch_or_new(value)
14
+ Array(@attrs[:photo_sizes]).inject({}) do |object, (key, value)|
15
+ object[key] = Size.new(value)
14
16
  object
15
17
  end
16
18
  end
19
+ memoize :photo_sizes
17
20
 
18
21
  end
19
22
  end
@@ -1,6 +1,10 @@
1
1
  module Kernel
2
2
 
3
3
  # Returns the object's singleton class (exists in Ruby 1.9.2)
4
- def singleton_class; class << self; self; end; end unless method_defined?(:singleton_class)
4
+ def singleton_class
5
+ class << self
6
+ self
7
+ end
8
+ end unless method_defined?(:singleton_class)
5
9
 
6
10
  end
@@ -1,20 +1,23 @@
1
1
  require 'time'
2
+ require 'memoizable'
2
3
 
3
4
  module Twitter
4
5
  module Creatable
6
+ include Memoizable
5
7
 
6
8
  # Time when the object was created on Twitter
7
9
  #
8
10
  # @return [Time]
9
11
  def created_at
10
- @created_at ||= Time.parse(@attrs[:created_at]) if created?
12
+ Time.parse(@attrs[:created_at]) if @attrs[:created_at]
11
13
  end
14
+ memoize :created_at
12
15
 
13
- private
14
-
16
+ # @return [Boolean]
15
17
  def created?
16
- !@attrs[:created_at].nil?
18
+ !!@attrs[:created_at]
17
19
  end
20
+ memoize :created?
18
21
 
19
22
  end
20
23
  end
@@ -3,62 +3,62 @@ require 'twitter/core_ext/kernel'
3
3
  module Twitter
4
4
  class Cursor
5
5
  include Enumerable
6
- attr_reader :attrs, :collection
6
+ attr_reader :attrs
7
+ alias to_h attrs
7
8
  alias to_hash attrs
9
+ alias to_hsh attrs
10
+
11
+ class << self
12
+
13
+ # Construct a new Cursor object from a response hash
14
+ #
15
+ # @param response [Hash]
16
+ # @param key [String, Symbol] The key to fetch the data from the response
17
+ # @param klass [Class] The class to instantiate objects in the response
18
+ # @param client [Twitter::REST::Client]
19
+ # @param request_method [String, Symbol]
20
+ # @param path [String]
21
+ # @param options [Hash]
22
+ # @return [Twitter::Cursor]
23
+ def from_response(response, key, klass, client, request_method, path, options)
24
+ new(response[:body], key, klass, client, request_method, path, options)
25
+ end
8
26
 
9
- # Initializes a new Cursor object
10
- #
11
- # @param response [Hash]
12
- # @param collection_name [String, Symbol] The name of the method to return the collection
13
- # @param klass [Class] The class to instantiate object in the collection
14
- # @param client [Twitter::Client]
15
- # @param method_name [String, Symbol]
16
- # @param method_options [Hash]
17
- # @return [Twitter::Cursor]
18
- def self.from_response(response, collection_name, klass, client, method_name, method_options)
19
- new(response[:body], collection_name, klass, client, method_name, method_options)
20
27
  end
21
28
 
22
29
  # Initializes a new Cursor
23
30
  #
24
31
  # @param attrs [Hash]
25
- # @param collection_name [String, Symbol] The name of the method to return the collection
26
- # @param klass [Class] The class to instantiate object in the collection
27
- # @param client [Twitter::Client]
28
- # @param method_name [String, Symbol]
29
- # @param method_options [Hash]
32
+ # @param key [String, Symbol] The key to fetch the data from the response
33
+ # @param klass [Class] The class to instantiate objects in the response
34
+ # @param client [Twitter::REST::Client]
35
+ # @param request_method [String, Symbol]
36
+ # @param path [String]
37
+ # @param options [Hash]
30
38
  # @return [Twitter::Cursor]
31
- def initialize(attrs, collection_name, klass, client, method_name, method_options)
32
- @attrs = attrs
39
+ def initialize(attrs, key, klass, client, request_method, path, options)
40
+ @key = key.to_sym
41
+ @klass = klass
33
42
  @client = client
34
- @method_name = method_name
35
- @method_options = method_options
36
- @collection = Array(attrs[collection_name.to_sym]).map do |item|
37
- if klass
38
- klass.fetch_or_new(item)
39
- else
40
- item
41
- end
42
- end
43
- singleton_class.class_eval do
44
- alias_method(collection_name.to_sym, :collection)
45
- end
46
- end
47
-
48
- # @param collection [Array]
49
- # @param cursor [Integer]
50
- # @return [Array]
51
- def all(collection=collection, cursor=next_cursor)
52
- cursor = @client.send(@method_name.to_sym, @method_options.merge(:cursor => cursor))
53
- collection += cursor.collection
54
- cursor.last? ? collection.flatten : all(collection, cursor.next_cursor)
43
+ @request_method = request_method.to_sym
44
+ @path = path
45
+ @options = options
46
+ @collection = []
47
+ set_attrs(attrs)
55
48
  end
56
49
 
57
- # @return [Enumerable]
58
- def each
59
- all(collection, next_cursor).each do |element|
50
+ # @return [Enumerator]
51
+ def each(start = 0, &block)
52
+ return to_enum(:each) unless block_given?
53
+ Array(@collection[start..-1]).each do |element|
60
54
  yield element
61
55
  end
56
+ unless last?
57
+ start = [@collection.size, start].max
58
+ fetch_next_page
59
+ each(start, &block)
60
+ end
61
+ self
62
62
  end
63
63
 
64
64
  def next_cursor
@@ -75,13 +75,25 @@ module Twitter
75
75
  def first?
76
76
  previous_cursor.zero?
77
77
  end
78
- alias first first?
79
78
 
80
79
  # @return [Boolean]
81
80
  def last?
82
81
  next_cursor.zero?
83
82
  end
84
- alias last last?
83
+
84
+ private
85
+
86
+ def fetch_next_page
87
+ response = @client.send(@request_method, @path, @options.merge(:cursor => next_cursor))
88
+ set_attrs(response[:body])
89
+ end
90
+
91
+ def set_attrs(attrs)
92
+ @attrs = attrs
93
+ Array(attrs[@key]).each do |element|
94
+ @collection << (@klass ? @klass.new(element) : element)
95
+ end
96
+ end
85
97
 
86
98
  end
87
99
  end
@@ -6,16 +6,7 @@ module Twitter
6
6
  include Twitter::Creatable
7
7
  attr_reader :text
8
8
  alias full_text text
9
-
10
- # @return [Twitter::User]
11
- def recipient
12
- @recipient ||= Twitter::User.fetch_or_new(@attrs[:recipient])
13
- end
14
-
15
- # @return [Twitter::User]
16
- def sender
17
- @sender ||= Twitter::User.fetch_or_new(@attrs[:sender])
18
- end
19
-
9
+ object_attr_reader :User, :recipient
10
+ object_attr_reader :User, :sender
20
11
  end
21
12
  end
@@ -0,0 +1,14 @@
1
+ require 'twitter/entity'
2
+
3
+ module Twitter
4
+ class Entity
5
+ class URI < Twitter::Entity
6
+ display_uri_attr_reader
7
+ uri_attr_reader :expanded_uri, :uri
8
+ end
9
+
10
+ Uri = URI
11
+ URL = URI
12
+ Url = URI
13
+ end
14
+ end