twitter 4.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 (210) hide show
  1. data/CHANGELOG.md +673 -0
  2. data/LICENSE.md +20 -0
  3. data/README.md +415 -0
  4. data/Rakefile +11 -0
  5. data/lib/twitter.rb +29 -0
  6. data/lib/twitter/action/favorite.rb +19 -0
  7. data/lib/twitter/action/follow.rb +31 -0
  8. data/lib/twitter/action/list_member_added.rb +41 -0
  9. data/lib/twitter/action/mention.rb +48 -0
  10. data/lib/twitter/action/reply.rb +27 -0
  11. data/lib/twitter/action/retweet.rb +27 -0
  12. data/lib/twitter/action/tweet.rb +22 -0
  13. data/lib/twitter/action_factory.rb +22 -0
  14. data/lib/twitter/api.rb +2442 -0
  15. data/lib/twitter/base.rb +119 -0
  16. data/lib/twitter/basic_user.rb +8 -0
  17. data/lib/twitter/client.rb +96 -0
  18. data/lib/twitter/configurable.rb +67 -0
  19. data/lib/twitter/configuration.rb +20 -0
  20. data/lib/twitter/core_ext/array.rb +7 -0
  21. data/lib/twitter/core_ext/enumerable.rb +11 -0
  22. data/lib/twitter/core_ext/hash.rb +100 -0
  23. data/lib/twitter/core_ext/kernel.rb +15 -0
  24. data/lib/twitter/core_ext/string.rb +10 -0
  25. data/lib/twitter/creatable.rb +20 -0
  26. data/lib/twitter/cursor.rb +87 -0
  27. data/lib/twitter/default.rb +101 -0
  28. data/lib/twitter/direct_message.rb +21 -0
  29. data/lib/twitter/entity.rb +7 -0
  30. data/lib/twitter/entity/hashtag.rb +9 -0
  31. data/lib/twitter/entity/url.rb +9 -0
  32. data/lib/twitter/entity/user_mention.rb +9 -0
  33. data/lib/twitter/error.rb +34 -0
  34. data/lib/twitter/error/bad_gateway.rb +11 -0
  35. data/lib/twitter/error/bad_request.rb +10 -0
  36. data/lib/twitter/error/client_error.rb +35 -0
  37. data/lib/twitter/error/decode_error.rb +9 -0
  38. data/lib/twitter/error/forbidden.rb +10 -0
  39. data/lib/twitter/error/gateway_timeout.rb +11 -0
  40. data/lib/twitter/error/identity_map_key_error.rb +9 -0
  41. data/lib/twitter/error/internal_server_error.rb +11 -0
  42. data/lib/twitter/error/not_acceptable.rb +10 -0
  43. data/lib/twitter/error/not_found.rb +10 -0
  44. data/lib/twitter/error/rate_limited.rb +11 -0
  45. data/lib/twitter/error/server_error.rb +28 -0
  46. data/lib/twitter/error/service_unavailable.rb +11 -0
  47. data/lib/twitter/error/unauthorized.rb +10 -0
  48. data/lib/twitter/factory.rb +21 -0
  49. data/lib/twitter/geo.rb +15 -0
  50. data/lib/twitter/geo/point.rb +22 -0
  51. data/lib/twitter/geo/polygon.rb +8 -0
  52. data/lib/twitter/geo_factory.rb +18 -0
  53. data/lib/twitter/identity.rb +50 -0
  54. data/lib/twitter/identity_map.rb +22 -0
  55. data/lib/twitter/language.rb +7 -0
  56. data/lib/twitter/list.rb +18 -0
  57. data/lib/twitter/media/photo.rb +22 -0
  58. data/lib/twitter/media_factory.rb +17 -0
  59. data/lib/twitter/metadata.rb +7 -0
  60. data/lib/twitter/oembed.rb +8 -0
  61. data/lib/twitter/place.rb +34 -0
  62. data/lib/twitter/rate_limit.rb +45 -0
  63. data/lib/twitter/relationship.rb +36 -0
  64. data/lib/twitter/request/multipart_with_file.rb +41 -0
  65. data/lib/twitter/response/parse_json.rb +25 -0
  66. data/lib/twitter/response/raise_error.rb +30 -0
  67. data/lib/twitter/saved_search.rb +9 -0
  68. data/lib/twitter/search_results.rb +48 -0
  69. data/lib/twitter/settings.rb +17 -0
  70. data/lib/twitter/size.rb +24 -0
  71. data/lib/twitter/source_user.rb +15 -0
  72. data/lib/twitter/suggestion.rb +22 -0
  73. data/lib/twitter/target_user.rb +8 -0
  74. data/lib/twitter/trend.rb +14 -0
  75. data/lib/twitter/tweet.rb +145 -0
  76. data/lib/twitter/user.rb +97 -0
  77. data/lib/twitter/version.rb +18 -0
  78. data/spec/fixtures/about_me.json +1 -0
  79. data/spec/fixtures/activity_summary.json +1 -0
  80. data/spec/fixtures/all.json +1 -0
  81. data/spec/fixtures/bad_gateway.json +1 -0
  82. data/spec/fixtures/bad_request.json +1 -0
  83. data/spec/fixtures/by_friends.json +1 -0
  84. data/spec/fixtures/category.json +1 -0
  85. data/spec/fixtures/configuration.json +1 -0
  86. data/spec/fixtures/contributees.json +1 -0
  87. data/spec/fixtures/contributors.json +1 -0
  88. data/spec/fixtures/direct_message.json +1 -0
  89. data/spec/fixtures/direct_messages.json +1 -0
  90. data/spec/fixtures/end_session.json +1 -0
  91. data/spec/fixtures/enhance_your_calm.text +11 -0
  92. data/spec/fixtures/favorites.json +1 -0
  93. data/spec/fixtures/following.json +1 -0
  94. data/spec/fixtures/forbidden.json +1 -0
  95. data/spec/fixtures/friendships.json +1 -0
  96. data/spec/fixtures/ids.json +1 -0
  97. data/spec/fixtures/ids_list.json +1 -0
  98. data/spec/fixtures/ids_list2.json +1 -0
  99. data/spec/fixtures/image_facets.json +1 -0
  100. data/spec/fixtures/internal_server_error.json +1 -0
  101. data/spec/fixtures/languages.json +1 -0
  102. data/spec/fixtures/list.json +1 -0
  103. data/spec/fixtures/lists.json +1 -0
  104. data/spec/fixtures/locations.json +1 -0
  105. data/spec/fixtures/matching_trends.json +1 -0
  106. data/spec/fixtures/me.jpeg +0 -0
  107. data/spec/fixtures/media_timeline.json +1 -0
  108. data/spec/fixtures/members.json +1 -0
  109. data/spec/fixtures/no_user_matches.json +1 -0
  110. data/spec/fixtures/not_acceptable.json +1 -0
  111. data/spec/fixtures/not_following.json +1 -0
  112. data/spec/fixtures/not_found.json +1 -0
  113. data/spec/fixtures/oembed.json +1 -0
  114. data/spec/fixtures/pbjt.gif +0 -0
  115. data/spec/fixtures/pengwynn.json +1 -0
  116. data/spec/fixtures/phoenix_search.phoenix +1 -0
  117. data/spec/fixtures/place.json +1 -0
  118. data/spec/fixtures/places.json +1 -0
  119. data/spec/fixtures/privacy.json +1 -0
  120. data/spec/fixtures/profile_image.text +24 -0
  121. data/spec/fixtures/rate_limit_status.json +1 -0
  122. data/spec/fixtures/recommendations.json +1 -0
  123. data/spec/fixtures/related_results.json +1 -0
  124. data/spec/fixtures/resolve.json +1 -0
  125. data/spec/fixtures/retweet.json +1 -0
  126. data/spec/fixtures/retweeted_status.json +1 -0
  127. data/spec/fixtures/retweeters_of.json +1 -0
  128. data/spec/fixtures/retweets.json +1 -0
  129. data/spec/fixtures/saved_search.json +1 -0
  130. data/spec/fixtures/saved_searches.json +1 -0
  131. data/spec/fixtures/search.json +1 -0
  132. data/spec/fixtures/search_malformed.json +1 -0
  133. data/spec/fixtures/service_unavailable.json +1 -0
  134. data/spec/fixtures/settings.json +1 -0
  135. data/spec/fixtures/sferik.json +1 -0
  136. data/spec/fixtures/status.json +1 -0
  137. data/spec/fixtures/status_with_media.json +104 -0
  138. data/spec/fixtures/statuses.json +1 -0
  139. data/spec/fixtures/suggestions.json +1 -0
  140. data/spec/fixtures/tos.json +1 -0
  141. data/spec/fixtures/totals.json +1 -0
  142. data/spec/fixtures/trends.json +1 -0
  143. data/spec/fixtures/trends_current.json +1 -0
  144. data/spec/fixtures/trends_daily.json +1 -0
  145. data/spec/fixtures/trends_weekly.json +1 -0
  146. data/spec/fixtures/unauthorized.json +1 -0
  147. data/spec/fixtures/user_search.json +1 -0
  148. data/spec/fixtures/user_timeline.json +1 -0
  149. data/spec/fixtures/users.json +1 -0
  150. data/spec/fixtures/users_list.json +1 -0
  151. data/spec/fixtures/video_facets.json +1 -0
  152. data/spec/fixtures/we_concept_bg2.png +0 -0
  153. data/spec/fixtures/wildcomet2.jpe +0 -0
  154. data/spec/helper.rb +53 -0
  155. data/spec/twitter/action/favorite_spec.rb +29 -0
  156. data/spec/twitter/action/follow_spec.rb +29 -0
  157. data/spec/twitter/action/list_member_added_spec.rb +41 -0
  158. data/spec/twitter/action/mention_spec.rb +52 -0
  159. data/spec/twitter/action/reply_spec.rb +41 -0
  160. data/spec/twitter/action/retweet_spec.rb +41 -0
  161. data/spec/twitter/action_factory_spec.rb +37 -0
  162. data/spec/twitter/action_spec.rb +16 -0
  163. data/spec/twitter/api/account_spec.rb +148 -0
  164. data/spec/twitter/api/activity_spec.rb +41 -0
  165. data/spec/twitter/api/blocks_spec.rb +167 -0
  166. data/spec/twitter/api/direct_messages_spec.rb +142 -0
  167. data/spec/twitter/api/friendships_spec.rb +567 -0
  168. data/spec/twitter/api/geo_spec.rb +100 -0
  169. data/spec/twitter/api/help_spec.rb +76 -0
  170. data/spec/twitter/api/lists_spec.rb +900 -0
  171. data/spec/twitter/api/report_spam_spec.rb +29 -0
  172. data/spec/twitter/api/saved_searches_spec.rb +100 -0
  173. data/spec/twitter/api/search_spec.rb +68 -0
  174. data/spec/twitter/api/statuses_spec.rb +559 -0
  175. data/spec/twitter/api/trends_spec.rb +80 -0
  176. data/spec/twitter/api/users_spec.rb +419 -0
  177. data/spec/twitter/base_spec.rb +113 -0
  178. data/spec/twitter/basic_user_spec.rb +23 -0
  179. data/spec/twitter/client_spec.rb +175 -0
  180. data/spec/twitter/configuration_spec.rb +17 -0
  181. data/spec/twitter/cursor_spec.rb +102 -0
  182. data/spec/twitter/direct_message_spec.rb +56 -0
  183. data/spec/twitter/error/client_error_spec.rb +40 -0
  184. data/spec/twitter/error/server_error_spec.rb +24 -0
  185. data/spec/twitter/error_spec.rb +20 -0
  186. data/spec/twitter/geo/point_spec.rb +41 -0
  187. data/spec/twitter/geo/polygon_spec.rb +29 -0
  188. data/spec/twitter/geo_factory_spec.rb +21 -0
  189. data/spec/twitter/geo_spec.rb +29 -0
  190. data/spec/twitter/identifiable_spec.rb +54 -0
  191. data/spec/twitter/list_spec.rb +45 -0
  192. data/spec/twitter/media/photo_spec.rb +35 -0
  193. data/spec/twitter/media_factory_spec.rb +17 -0
  194. data/spec/twitter/oembed_spec.rb +146 -0
  195. data/spec/twitter/place_spec.rb +75 -0
  196. data/spec/twitter/rate_limit_spec.rb +76 -0
  197. data/spec/twitter/relationship_spec.rb +35 -0
  198. data/spec/twitter/saved_search_spec.rb +34 -0
  199. data/spec/twitter/search_results_spec.rb +89 -0
  200. data/spec/twitter/settings_spec.rb +16 -0
  201. data/spec/twitter/size_spec.rb +38 -0
  202. data/spec/twitter/source_user_spec.rb +23 -0
  203. data/spec/twitter/suggestion_spec.rb +50 -0
  204. data/spec/twitter/target_user_spec.rb +23 -0
  205. data/spec/twitter/trend_spec.rb +38 -0
  206. data/spec/twitter/tweet_spec.rb +307 -0
  207. data/spec/twitter/user_spec.rb +127 -0
  208. data/spec/twitter_spec.rb +93 -0
  209. data/twitter.gemspec +30 -0
  210. metadata +584 -0
@@ -0,0 +1,119 @@
1
+ require 'twitter/core_ext/kernel'
2
+ require 'twitter/error/identity_map_key_error'
3
+
4
+ module Twitter
5
+ class Base
6
+ attr_reader :attrs
7
+ alias to_hash attrs
8
+
9
+ # Define methods that retrieve the value from an initialized instance variable Hash, using the attribute as a key
10
+ #
11
+ # @overload self.attr_reader(attr)
12
+ # @param attr [Symbol]
13
+ # @overload self.attr_reader(attrs)
14
+ # @param attrs [Array<Symbol>]
15
+ def self.attr_reader(*attrs)
16
+ attrs.each do |attribute|
17
+ class_eval do
18
+ define_method attribute do
19
+ @attrs[attribute.to_sym]
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ # return [Twitter::IdentityMap]
26
+ def self.identity_map
27
+ return unless Twitter.identity_map
28
+ @identity_map = Twitter.identity_map.new unless defined?(@identity_map) && @identity_map.class == Twitter.identity_map
29
+ @identity_map
30
+ end
31
+
32
+ # Retrieves an object from the identity map.
33
+ #
34
+ # @param attrs [Hash]
35
+ # @return [Twitter::Base]
36
+ def self.fetch(attrs)
37
+ return unless identity_map
38
+ if object = identity_map.fetch(Marshal.dump(attrs))
39
+ return object
40
+ end
41
+ return yield if block_given?
42
+ raise Twitter::Error::IdentityMapKeyError, "key not found"
43
+ end
44
+
45
+ # Stores an object in the identity map.
46
+ #
47
+ # @param object [Object]
48
+ # @return [Twitter::Base]
49
+ def self.store(object)
50
+ return object unless identity_map
51
+ identity_map.store(Marshal.dump(object.attrs), object)
52
+ end
53
+
54
+ # Returns a new object based on the response hash
55
+ #
56
+ # @param response [Hash]
57
+ # @return [Twitter::Base]
58
+ def self.from_response(response={})
59
+ fetch_or_new(response[:body])
60
+ end
61
+
62
+ # Retrieves an object from the identity map, or stores it in the
63
+ # identity map if it doesn't already exist.
64
+ #
65
+ # @param attrs [Hash]
66
+ # @return [Twitter::Base]
67
+ def self.fetch_or_new(attrs={})
68
+ return unless attrs
69
+ return new(attrs) unless identity_map
70
+
71
+ fetch(attrs) do
72
+ object = new(attrs)
73
+ store(object)
74
+ end
75
+ end
76
+
77
+ # Initializes a new object
78
+ #
79
+ # @param attrs [Hash]
80
+ # @return [Twitter::Base]
81
+ def initialize(attrs={})
82
+ @attrs = attrs
83
+ end
84
+
85
+ # Fetches an attribute of an object using hash notation
86
+ #
87
+ # @param method [String, Symbol] Message to send to the object
88
+ def [](method)
89
+ send(method.to_sym)
90
+ rescue NoMethodError
91
+ nil
92
+ end
93
+
94
+ # Update the attributes of an object
95
+ #
96
+ # @param attrs [Hash]
97
+ # @return [Twitter::Base]
98
+ def update(attrs)
99
+ @attrs.update(attrs)
100
+ self
101
+ end
102
+
103
+ protected
104
+
105
+ # @param attr [Symbol]
106
+ # @param other [Twitter::Base]
107
+ # @return [Boolean]
108
+ def attr_equal(attr, other)
109
+ self.class == other.class && !other.send(attr).nil? && send(attr) == other.send(attr)
110
+ end
111
+
112
+ # @param other [Twitter::Base]
113
+ # @return [Boolean]
114
+ def attrs_equal(other)
115
+ self.class == other.class && !other.attrs.empty? && attrs == other.attrs
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,8 @@
1
+ require 'twitter/identity'
2
+
3
+ module Twitter
4
+ class BasicUser < Twitter::Identity
5
+ attr_reader :following, :screen_name
6
+ alias following? following
7
+ end
8
+ end
@@ -0,0 +1,96 @@
1
+ require 'faraday'
2
+ require 'multi_json'
3
+ require 'twitter/api'
4
+ require 'twitter/configurable'
5
+ require 'twitter/error/client_error'
6
+ require 'twitter/error/decode_error'
7
+ require 'simple_oauth'
8
+ require 'uri'
9
+
10
+ module Twitter
11
+ # Wrapper for the Twitter REST API
12
+ #
13
+ # @note All methods have been separated into modules and follow the same grouping used in {http://dev.twitter.com/doc the Twitter API Documentation}.
14
+ # @see http://dev.twitter.com/pages/every_developer
15
+ class Client
16
+ include Twitter::API
17
+ include Twitter::Configurable
18
+
19
+ # Initializes a new Client object
20
+ #
21
+ # @param options [Hash]
22
+ # @return [Twitter::Client]
23
+ def initialize(options={})
24
+ Twitter::Configurable.keys.each do |key|
25
+ instance_variable_set(:"@#{key}", options[key] || Twitter.instance_variable_get(:"@#{key}"))
26
+ end
27
+ end
28
+
29
+ # Perform an HTTP DELETE request
30
+ def delete(path, params={}, options={})
31
+ request(:delete, path, params, options)
32
+ end
33
+
34
+ # Perform an HTTP GET request
35
+ def get(path, params={}, options={})
36
+ request(:get, path, params, options)
37
+ end
38
+
39
+ # Perform an HTTP POST request
40
+ def post(path, params={}, options={})
41
+ request(:post, path, params, options)
42
+ end
43
+
44
+ # Perform an HTTP UPDATE request
45
+ def put(path, params={}, options={})
46
+ request(:put, path, params, options)
47
+ end
48
+
49
+ private
50
+
51
+ # Returns a Faraday::Connection object
52
+ #
53
+ # @return [Faraday::Connection]
54
+ def connection
55
+ @connection ||= Faraday.new(@endpoint, @connection_options.merge(:builder => @middleware))
56
+ end
57
+
58
+ # Perform an HTTP request
59
+ #
60
+ # @raise [Twitter::Error::ClientError, Twitter::Error::DecodeError]
61
+ def request(method, path, params={}, options={})
62
+ uri = options[:endpoint] || @endpoint
63
+ uri = URI(uri) unless uri.respond_to?(:host)
64
+ uri += path
65
+ request_headers = {}
66
+ if credentials?
67
+ authorization = auth_header(method, uri, params)
68
+ request_headers[:authorization] = authorization.to_s
69
+ end
70
+ connection.url_prefix = options[:endpoint] || @endpoint
71
+ response = connection.run_request(method.to_sym, path, nil, request_headers) do |request|
72
+ unless params.empty?
73
+ case request.method
74
+ when :post, :put
75
+ request.body = params
76
+ else
77
+ request.params.update(params)
78
+ end
79
+ end
80
+ yield request if block_given?
81
+ end.env
82
+ response
83
+ rescue Faraday::Error::ClientError
84
+ raise Twitter::Error::ClientError
85
+ rescue MultiJson::DecodeError
86
+ raise Twitter::Error::DecodeError
87
+ end
88
+
89
+ def auth_header(method, uri, params={})
90
+ # When posting a file, don't sign any params
91
+ signature_params = [:post, :put].include?(method.to_sym) && params.values.any?{|value| value.respond_to?(:to_io)} ? {} : params
92
+ SimpleOAuth::Header.new(method, uri, signature_params, credentials)
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,67 @@
1
+ require 'twitter/default'
2
+
3
+ module Twitter
4
+ module Configurable
5
+ attr_writer :consumer_key, :consumer_secret, :oauth_token, :oauth_token_secret
6
+ attr_accessor :endpoint, :connection_options, :identity_map, :middleware
7
+
8
+ class << self
9
+
10
+ def keys
11
+ @keys ||= [
12
+ :consumer_key,
13
+ :consumer_secret,
14
+ :oauth_token,
15
+ :oauth_token_secret,
16
+ :endpoint,
17
+ :connection_options,
18
+ :identity_map,
19
+ :middleware,
20
+ ]
21
+ end
22
+
23
+ end
24
+
25
+ # Convenience method to allow configuration options to be set in a block
26
+ def configure
27
+ yield self
28
+ self
29
+ end
30
+
31
+ # @return [Boolean]
32
+ def credentials?
33
+ credentials.values.all?
34
+ end
35
+
36
+ # @return [Fixnum]
37
+ def cache_key
38
+ options.hash
39
+ end
40
+
41
+ def reset!
42
+ Twitter::Configurable.keys.each do |key|
43
+ instance_variable_set(:"@#{key}", Twitter::Default.options[key])
44
+ end
45
+ self
46
+ end
47
+ alias setup reset!
48
+
49
+ private
50
+
51
+ # @return [Hash]
52
+ def credentials
53
+ {
54
+ :consumer_key => @consumer_key,
55
+ :consumer_secret => @consumer_secret,
56
+ :token => @oauth_token,
57
+ :token_secret => @oauth_token_secret,
58
+ }
59
+ end
60
+
61
+ # @return [Hash]
62
+ def options
63
+ Hash[Twitter::Configurable.keys.map{|key| [key, instance_variable_get(:"@#{key}")]}]
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,20 @@
1
+ require 'twitter/base'
2
+ require 'twitter/size'
3
+
4
+ module Twitter
5
+ class Configuration < Twitter::Base
6
+ attr_reader :characters_reserved_per_media, :max_media_per_upload,
7
+ :non_username_paths, :photo_size_limit, :short_url_length, :short_url_length_https
8
+
9
+ # Returns an array of photo sizes
10
+ #
11
+ # @return [Array<Twitter::Size>]
12
+ def photo_sizes
13
+ @photo_sizes ||= Array(@attrs[:photo_sizes]).inject({}) do |object, (key, value)|
14
+ object[key] = Twitter::Size.fetch_or_new(value)
15
+ object
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ class Array
2
+
3
+ def extract_options!
4
+ last.is_a?(::Hash) ? pop : {}
5
+ end unless method_defined?(:extract_options!)
6
+
7
+ end
@@ -0,0 +1,11 @@
1
+ module Enumerable
2
+
3
+ def threaded_map
4
+ threads = []
5
+ each do |object|
6
+ threads << Thread.new{yield object}
7
+ end
8
+ threads.map(&:value)
9
+ end
10
+
11
+ end
@@ -0,0 +1,100 @@
1
+ class Hash
2
+
3
+ # Return a hash that includes everything but the given keys.
4
+ #
5
+ # @param keys [Array, Set]
6
+ # @return [Hash]
7
+ def except(*keys)
8
+ self.dup.except!(*keys)
9
+ end unless method_defined?(:except)
10
+
11
+ # Replaces the hash without the given keys.
12
+ #
13
+ # @param keys [Array, Set]
14
+ # @return [Hash]
15
+ def except!(*keys)
16
+ keys.each{|key| delete(key)}
17
+ self
18
+ end unless method_defined?(:except!)
19
+
20
+ # Take a list and merge it into the hash with the correct key
21
+ #
22
+ # @param list [Integer, String, Twitter::List] A Twitter list ID, slug, or object.
23
+ # @return [Hash]
24
+ def merge_list!(list)
25
+ case list
26
+ when Integer
27
+ self[:list_id] = list
28
+ when String
29
+ self[:slug] = list
30
+ when Twitter::List
31
+ self[:list_id] = list.id
32
+ self.merge_owner!(list.user)
33
+ end
34
+ self
35
+ end
36
+
37
+ # Take an owner and merge it into the hash with the correct key
38
+ #
39
+ # @param user[Integer, String, Twitter::User] A Twitter user ID, screen_name, or object.
40
+ # @return [Hash]
41
+ def merge_owner!(user)
42
+ self.merge_user!(user, "owner")
43
+ self[:owner_id] = self.delete(:owner_user_id) unless self[:owner_user_id].nil?
44
+ self
45
+ end
46
+
47
+ # Take a user and merge it into the hash with the correct key
48
+ #
49
+ # @param user[Integer, String, Twitter::User] A Twitter user ID, screen_name, or object.
50
+ # @return [Hash]
51
+ def merge_user(user, prefix=nil)
52
+ self.dup.merge_user!(user, prefix)
53
+ end
54
+
55
+ # Take a user and merge it into the hash with the correct key
56
+ #
57
+ # @param user[Integer, String, Twitter::User] A Twitter user ID, screen_name, or object.
58
+ # @return [Hash]
59
+ def merge_user!(user, prefix=nil)
60
+ case user
61
+ when Integer
62
+ self[[prefix, "user_id"].compact.join("_").to_sym] = user
63
+ when String
64
+ self[[prefix, "screen_name"].compact.join("_").to_sym] = user
65
+ when Twitter::User
66
+ self[[prefix, "user_id"].compact.join("_").to_sym] = user.id
67
+ end
68
+ self
69
+ end
70
+
71
+ # Take a multiple users and merge them into the hash with the correct keys
72
+ #
73
+ # @param users [Array<Integer, String, Twitter::User>, Set<Integer, String, Twitter::User>] An array of Twitter user IDs, screen_names, or objects.
74
+ # @return [Hash]
75
+ def merge_users(*users)
76
+ self.dup.merge_users!(*users)
77
+ end
78
+
79
+ # Take a multiple users and merge them into the hash with the correct keys
80
+ #
81
+ # @param users [Array<Integer, String, Twitter::User>, Set<Integer, String, Twitter::User>] An array of Twitter user IDs, screen_names, or objects.
82
+ # @return [Hash]
83
+ def merge_users!(*users)
84
+ user_ids, screen_names = [], []
85
+ users.flatten.each do |user|
86
+ case user
87
+ when Integer
88
+ user_ids << user
89
+ when String
90
+ screen_names << user
91
+ when Twitter::User
92
+ user_ids << user.id
93
+ end
94
+ end
95
+ self[:user_id] = user_ids.join(',') unless user_ids.empty?
96
+ self[:screen_name] = screen_names.join(',') unless screen_names.empty?
97
+ self
98
+ end
99
+
100
+ end
@@ -0,0 +1,15 @@
1
+ module Kernel
2
+
3
+ def calling_method
4
+ caller[1][/`([^']*)'/, 1].to_sym
5
+ end
6
+
7
+ # Returns the object's singleton class (exists in Ruby 1.9.2)
8
+ def singleton_class; class << self; self; end; end unless method_defined?(:singleton_class)
9
+
10
+ # class_eval on an object acts like singleton_class.class_eval.
11
+ def class_eval(*args, &block)
12
+ singleton_class.class_eval(*args, &block)
13
+ end
14
+
15
+ end