twitter 5.4.1 → 5.5.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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +5 -0
- data/CONTRIBUTING.md +6 -8
- data/README.md +8 -0
- data/Rakefile +1 -2
- data/lib/twitter/base.rb +4 -4
- data/lib/twitter/creatable.rb +1 -1
- data/lib/twitter/cursor.rb +3 -3
- data/lib/twitter/direct_message.rb +2 -0
- data/lib/twitter/entities.rb +69 -0
- data/lib/twitter/enumerable.rb +2 -0
- data/lib/twitter/error.rb +4 -3
- data/lib/twitter/null_object.rb +7 -4
- data/lib/twitter/profile.rb +94 -0
- data/lib/twitter/rest/api/direct_messages.rb +1 -1
- data/lib/twitter/rest/api/favorites.rb +1 -1
- data/lib/twitter/rest/api/friends_and_followers.rb +1 -1
- data/lib/twitter/rest/api/spam_reporting.rb +1 -1
- data/lib/twitter/rest/api/tweets.rb +3 -3
- data/lib/twitter/rest/api/users.rb +9 -9
- data/lib/twitter/rest/api/utils.rb +2 -2
- data/lib/twitter/rest/client.rb +2 -2
- data/lib/twitter/search_results.rb +3 -3
- data/lib/twitter/streaming/client.rb +1 -0
- data/lib/twitter/trend_results.rb +1 -1
- data/lib/twitter/tweet.rb +11 -75
- data/lib/twitter/user.rb +8 -87
- data/lib/twitter/utils.rb +7 -8
- data/lib/twitter/version.rb +2 -2
- data/spec/fixtures/direct_message.json +1 -1
- data/spec/twitter/direct_message_spec.rb +142 -0
- data/spec/twitter/null_object_spec.rb +70 -7
- data/spec/twitter/rest/api/direct_messages_spec.rb +12 -12
- data/spec/twitter/tweet_spec.rb +2 -26
- data/twitter.gemspec +9 -9
- metadata +32 -63
- metadata.gz.sig +5 -2
@@ -49,7 +49,7 @@ module Twitter
|
|
49
49
|
# @param path [String]
|
50
50
|
# @param args [Array]
|
51
51
|
# @return [Array<Twitter::User>]
|
52
|
-
def
|
52
|
+
def parallel_user_objects_from_response(request_method, path, args)
|
53
53
|
arguments = Twitter::Arguments.new(args)
|
54
54
|
Twitter::Utils.parallel_map(arguments) do |user|
|
55
55
|
object_from_response(Twitter::User, request_method, path, merge_user(arguments.options, user))
|
@@ -101,7 +101,7 @@ module Twitter
|
|
101
101
|
# @param path [String]
|
102
102
|
# @param args [Array]
|
103
103
|
# @return [Array]
|
104
|
-
def
|
104
|
+
def parallel_objects_from_response(klass, request_method, path, args) # rubocop:disable ParameterLists
|
105
105
|
arguments = Twitter::Arguments.new(args)
|
106
106
|
Twitter::Utils.parallel_map(arguments) do |object|
|
107
107
|
id = extract_id(object)
|
data/lib/twitter/rest/client.rb
CHANGED
@@ -139,8 +139,8 @@ module Twitter
|
|
139
139
|
end
|
140
140
|
end
|
141
141
|
response.env
|
142
|
-
rescue Faraday::Error::ClientError, JSON::ParserError
|
143
|
-
raise Twitter::Error
|
142
|
+
rescue Faraday::Error::ClientError, JSON::ParserError => error
|
143
|
+
raise Twitter::Error.new(error) # rubocop:disable RaiseArgs
|
144
144
|
end
|
145
145
|
|
146
146
|
def auth_token(method, path, params = {}, signature_params = params) # rubocop:disable ParameterLists
|
@@ -34,7 +34,7 @@ module Twitter
|
|
34
34
|
@path = path
|
35
35
|
@options = options
|
36
36
|
@collection = []
|
37
|
-
|
37
|
+
self.attrs = attrs
|
38
38
|
end
|
39
39
|
|
40
40
|
private
|
@@ -66,10 +66,10 @@ module Twitter
|
|
66
66
|
|
67
67
|
def fetch_next_page
|
68
68
|
response = @client.send(@request_method, @path, next_page)
|
69
|
-
|
69
|
+
self.attrs = response[:body]
|
70
70
|
end
|
71
71
|
|
72
|
-
def
|
72
|
+
def attrs=(attrs)
|
73
73
|
@attrs = attrs
|
74
74
|
Array(@attrs[:statuses]).map do |tweet|
|
75
75
|
@collection << Tweet.new(tweet)
|
@@ -58,6 +58,7 @@ module Twitter
|
|
58
58
|
# @see https://dev.twitter.com/docs/api/1.1/get/site
|
59
59
|
# @see https://dev.twitter.com/docs/streaming-apis/streams/site
|
60
60
|
# @see https://dev.twitter.com/docs/streaming-apis/parameters
|
61
|
+
# @note Site Streams is currently in a limited beta. Access is restricted to whitelisted accounts.
|
61
62
|
# @param follow [Enumerable<Integer, String, Twitter::User>] A list of user IDs, indicating the users to return statuses for in the stream.
|
62
63
|
# @param options [Hash] A customizable set of options.
|
63
64
|
# @option options [String] :with Specifies whether to return information for just the users specified in the follow parameter, or include messages from accounts they follow.
|
data/lib/twitter/tweet.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
require 'twitter/creatable'
|
2
|
+
require 'twitter/entities'
|
3
|
+
require 'twitter/identity'
|
2
4
|
|
3
5
|
module Twitter
|
4
6
|
class Tweet < Twitter::Identity
|
5
7
|
include Twitter::Creatable
|
6
|
-
|
7
|
-
|
8
|
-
:
|
9
|
-
:
|
8
|
+
include Twitter::Entities
|
9
|
+
attr_reader :favorite_count, :favorited, :filter_level,
|
10
|
+
:in_reply_to_screen_name, :in_reply_to_attrs_id,
|
11
|
+
:in_reply_to_status_id, :in_reply_to_user_id, :lang,
|
12
|
+
:retweet_count, :retweeted, :source, :text, :truncated
|
10
13
|
alias_method :favorites_count, :favorite_count
|
11
14
|
alias_method :favoriters_count, :favorite_count
|
12
15
|
alias_method :in_reply_to_tweet_id, :in_reply_to_status_id
|
16
|
+
alias_method :reply?, :in_reply_to_status_id?
|
13
17
|
alias_method :retweeters_count, :retweet_count
|
14
18
|
object_attr_reader :GeoFactory, :geo
|
15
19
|
object_attr_reader :Metadata, :metadata
|
@@ -21,21 +25,10 @@ module Twitter
|
|
21
25
|
alias_method :retweeted_tweet?, :retweeted_status?
|
22
26
|
object_attr_reader :User, :user, :status
|
23
27
|
|
24
|
-
# @return [Boolean]
|
25
|
-
def entities?
|
26
|
-
!@attrs[:entities].nil? && @attrs[:entities].any? { |_, array| !array.empty? }
|
27
|
-
end
|
28
|
-
memoize :entities?
|
29
|
-
|
30
|
-
def filter_level
|
31
|
-
@attrs[:filter_level] || 'none'
|
32
|
-
end
|
33
|
-
memoize :filter_level
|
34
|
-
|
35
|
-
# @return [String]
|
36
28
|
# @note May be > 140 characters.
|
29
|
+
# @return [String]
|
37
30
|
def full_text
|
38
|
-
if
|
31
|
+
if retweet?
|
39
32
|
prefix = text[/\A(RT @[a-z0-9_]{1,20}: )/i, 1]
|
40
33
|
[prefix, retweeted_status.text].compact.join
|
41
34
|
else
|
@@ -44,69 +37,12 @@ module Twitter
|
|
44
37
|
end
|
45
38
|
memoize :full_text
|
46
39
|
|
47
|
-
# @note Must include entities in your request for this method to work
|
48
|
-
# @return [Array<Twitter::Entity::Hashtag>]
|
49
|
-
def hashtags
|
50
|
-
entities(Entity::Hashtag, :hashtags)
|
51
|
-
end
|
52
|
-
memoize :hashtags
|
53
|
-
|
54
|
-
# @note Must include entities in your request for this method to work
|
55
|
-
# @return [Array<Twitter::Media>]
|
56
|
-
def media
|
57
|
-
entities(MediaFactory, :media)
|
58
|
-
end
|
59
|
-
memoize :media
|
60
|
-
|
61
|
-
# @return [Boolean]
|
62
|
-
def reply?
|
63
|
-
!!@attrs[:in_reply_to_status_id]
|
64
|
-
end
|
65
|
-
memoize :reply?
|
66
|
-
|
67
|
-
# @note Must include entities in your request for this method to work
|
68
|
-
# @return [Array<Twitter::Entity::Symbol>]
|
69
|
-
def symbols
|
70
|
-
entities(Entity::Symbol, :symbols)
|
71
|
-
end
|
72
|
-
memoize :symbols
|
73
|
-
|
74
40
|
# @return [String] The URL to the tweet.
|
75
41
|
def uri
|
76
|
-
Addressable::URI.parse("https://twitter.com/#{user.screen_name}/status/#{id}")
|
42
|
+
Addressable::URI.parse("https://twitter.com/#{user.screen_name}/status/#{id}") unless user.nil?
|
77
43
|
end
|
78
44
|
memoize :uri
|
79
45
|
alias_method :url, :uri
|
80
|
-
|
81
|
-
# @note Must include entities in your request for this method to work
|
82
|
-
# @return [Array<Twitter::Entity::URI>]
|
83
|
-
def uris
|
84
|
-
entities(Entity::URI, :urls)
|
85
|
-
end
|
86
|
-
memoize :uris
|
87
|
-
alias_method :urls, :uris
|
88
|
-
|
89
|
-
# @note Must include entities in your request for this method to work
|
90
|
-
# @return [Array<Twitter::Entity::UserMention>]
|
91
|
-
def user_mentions
|
92
|
-
entities(Entity::UserMention, :user_mentions)
|
93
|
-
end
|
94
|
-
memoize :user_mentions
|
95
|
-
|
96
|
-
private
|
97
|
-
|
98
|
-
# @param klass [Class]
|
99
|
-
# @param key [Symbol]
|
100
|
-
def entities(klass, key)
|
101
|
-
if entities?
|
102
|
-
Array(@attrs[:entities][key.to_sym]).map do |entity|
|
103
|
-
klass.new(entity)
|
104
|
-
end
|
105
|
-
else
|
106
|
-
warn "#{Kernel.caller.first}: To get #{key.to_s.tr('_', ' ')}, you must pass `:include_entities => true` when requesting the #{self.class}."
|
107
|
-
[]
|
108
|
-
end
|
109
|
-
end
|
110
46
|
end
|
111
47
|
Status = Tweet # rubocop:disable ConstantName
|
112
48
|
end
|
data/lib/twitter/user.rb
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
+
require 'addressable/uri'
|
2
|
+
require 'memoizable'
|
1
3
|
require 'twitter/basic_user'
|
2
4
|
require 'twitter/creatable'
|
5
|
+
require 'twitter/entity/uri'
|
6
|
+
require 'twitter/profile'
|
3
7
|
|
4
8
|
module Twitter
|
5
9
|
class User < Twitter::BasicUser
|
6
|
-
PROFILE_IMAGE_SUFFIX_REGEX = /_normal(\.gif|\.jpe?g|\.png)$/i
|
7
|
-
PREDICATE_URI_METHOD_REGEX = /_uri\?$/
|
8
10
|
include Twitter::Creatable
|
11
|
+
include Twitter::Profile
|
12
|
+
include Memoizable
|
9
13
|
attr_reader :connections, :contributors_enabled, :default_profile,
|
10
14
|
:default_profile_image, :description, :favourites_count,
|
11
15
|
:follow_request_sent, :followers_count, :friends_count,
|
@@ -28,20 +32,6 @@ module Twitter
|
|
28
32
|
alias_method :tweet?, :status?
|
29
33
|
alias_method :tweeted?, :status?
|
30
34
|
|
31
|
-
class << self
|
32
|
-
private
|
33
|
-
|
34
|
-
def alias_predicate_uri_methods(method)
|
35
|
-
%w(_url? _uri_https? _url_https?).each do |replacement|
|
36
|
-
alias_method_sub(method, PREDICATE_URI_METHOD_REGEX, replacement)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def alias_method_sub(method, pattern, replacement)
|
41
|
-
alias_method(method.to_s.sub(pattern, replacement).to_sym, method)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
35
|
# @return [Array<Twitter::Entity::URI>]
|
46
36
|
def description_uris
|
47
37
|
Array(@attrs[:entities][:description][:urls]).map do |entity|
|
@@ -51,71 +41,16 @@ module Twitter
|
|
51
41
|
memoize :description_uris
|
52
42
|
alias_method :description_urls, :description_uris
|
53
43
|
|
54
|
-
# Return the URL to the user's profile banner image
|
55
|
-
#
|
56
|
-
# @param size [String, Symbol] The size of the image. Must be one of: 'mobile', 'mobile_retina', 'web', 'web_retina', 'ipad', or 'ipad_retina'
|
57
|
-
# @return [String]
|
58
|
-
def profile_banner_uri(size = :web)
|
59
|
-
parse_encoded_uri(insecure_uri([@attrs[:profile_banner_url], size].join('/'))) if @attrs[:profile_banner_url]
|
60
|
-
end
|
61
|
-
alias_method :profile_banner_url, :profile_banner_uri
|
62
|
-
|
63
|
-
# Return the secure URL to the user's profile banner image
|
64
|
-
#
|
65
|
-
# @param size [String, Symbol] The size of the image. Must be one of: 'mobile', 'mobile_retina', 'web', 'web_retina', 'ipad', or 'ipad_retina'
|
66
|
-
# @return [String]
|
67
|
-
def profile_banner_uri_https(size = :web)
|
68
|
-
parse_encoded_uri([@attrs[:profile_banner_url], size].join('/')) if @attrs[:profile_banner_url]
|
69
|
-
end
|
70
|
-
alias_method :profile_banner_url_https, :profile_banner_uri_https
|
71
|
-
|
72
|
-
# @return [Boolean]
|
73
|
-
def profile_banner_uri?
|
74
|
-
!!@attrs[:profile_banner_url]
|
75
|
-
end
|
76
|
-
memoize :profile_banner_uri?
|
77
|
-
alias_predicate_uri_methods :profile_banner_uri?
|
78
|
-
|
79
|
-
# Return the URL to the user's profile image
|
80
|
-
#
|
81
|
-
# @param size [String, Symbol] The size of the image. Must be one of: 'mini', 'normal', 'bigger' or 'original'
|
82
|
-
# @return [String]
|
83
|
-
def profile_image_uri(size = :normal)
|
84
|
-
parse_encoded_uri(insecure_uri(profile_image_uri_https(size))) if @attrs[:profile_image_url_https]
|
85
|
-
end
|
86
|
-
alias_method :profile_image_url, :profile_image_uri
|
87
|
-
|
88
|
-
# Return the secure URL to the user's profile image
|
89
|
-
#
|
90
|
-
# @param size [String, Symbol] The size of the image. Must be one of: 'mini', 'normal', 'bigger' or 'original'
|
91
|
-
# @return [String]
|
92
|
-
def profile_image_uri_https(size = :normal)
|
93
|
-
# The profile image URL comes in looking like like this:
|
94
|
-
# https://a0.twimg.com/profile_images/1759857427/image1326743606_normal.png
|
95
|
-
# It can be converted to any of the following sizes:
|
96
|
-
# https://a0.twimg.com/profile_images/1759857427/image1326743606.png
|
97
|
-
# https://a0.twimg.com/profile_images/1759857427/image1326743606_mini.png
|
98
|
-
# https://a0.twimg.com/profile_images/1759857427/image1326743606_bigger.png
|
99
|
-
parse_encoded_uri(@attrs[:profile_image_url_https].sub(PROFILE_IMAGE_SUFFIX_REGEX, profile_image_suffix(size))) if @attrs[:profile_image_url_https]
|
100
|
-
end
|
101
|
-
alias_method :profile_image_url_https, :profile_image_uri_https
|
102
|
-
|
103
|
-
def profile_image_uri?
|
104
|
-
!!@attrs[:profile_image_url_https]
|
105
|
-
end
|
106
|
-
memoize :profile_image_uri?
|
107
|
-
alias_predicate_uri_methods :profile_image_uri?
|
108
|
-
|
109
44
|
# @return [String] The URL to the user.
|
110
45
|
def uri
|
111
|
-
Addressable::URI.parse("https://twitter.com/#{screen_name}")
|
46
|
+
Addressable::URI.parse("https://twitter.com/#{screen_name}") unless screen_name.nil?
|
112
47
|
end
|
113
48
|
memoize :uri
|
114
49
|
alias_method :url, :uri
|
115
50
|
|
116
51
|
# @return [String] The URL to the user's website.
|
117
52
|
def website
|
118
|
-
Addressable::URI.parse(@attrs[:url])
|
53
|
+
Addressable::URI.parse(@attrs[:url]) unless @attrs[:url].nil?
|
119
54
|
end
|
120
55
|
memoize :website
|
121
56
|
|
@@ -123,19 +58,5 @@ module Twitter
|
|
123
58
|
!!@attrs[:url]
|
124
59
|
end
|
125
60
|
memoize :website?
|
126
|
-
|
127
|
-
private
|
128
|
-
|
129
|
-
def parse_encoded_uri(uri)
|
130
|
-
Addressable::URI.parse(URI.encode(uri))
|
131
|
-
end
|
132
|
-
|
133
|
-
def insecure_uri(uri)
|
134
|
-
uri.to_s.sub(/^https/i, 'http')
|
135
|
-
end
|
136
|
-
|
137
|
-
def profile_image_suffix(size)
|
138
|
-
:original == size.to_sym ? '\\1' : "_#{size}\\1"
|
139
|
-
end
|
140
61
|
end
|
141
62
|
end
|
data/lib/twitter/utils.rb
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
module Twitter
|
2
2
|
module Utils
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
3
|
+
module_function
|
4
|
+
def parallel_map(enumerable)
|
5
|
+
# Don't bother spawning a new thread if there's only one item
|
6
|
+
if enumerable.count == 1
|
7
|
+
enumerable.map { |object| yield object }
|
8
|
+
else
|
9
|
+
enumerable.map { |object| Thread.new { yield object } }.map(&:value)
|
11
10
|
end
|
12
11
|
end
|
13
12
|
end
|
data/lib/twitter/version.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"
|
1
|
+
{"id":418030038152642560,"id_str":"418030038152642560","text":"My #newride from @PUBLICBikes. Don't you want one? https:\/\/t.co\/7HIwCl68Y8 https:\/\/t.co\/JSSxDPr4Sf","sender":{"id":14471007,"id_str":"14471007","name":"Diana Kimball","screen_name":"dianakimball","location":"Berlin","description":"Community at @SoundCloud. Every now and then, I write a longer letter that I\u2019d love to send to you: http:\/\/t.co\/AZEzTiBwRS","url":"http:\/\/t.co\/tUTbLPD7Yc","entities":{"url":{"urls":[{"url":"http:\/\/t.co\/tUTbLPD7Yc","expanded_url":"http:\/\/blog.dianakimball.com","display_url":"blog.dianakimball.com","indices":[0,22]}]},"description":{"urls":[{"url":"http:\/\/t.co\/AZEzTiBwRS","expanded_url":"http:\/\/expertnovice.com","display_url":"expertnovice.com","indices":[100,122]}]}},"protected":false,"followers_count":4283,"friends_count":684,"listed_count":176,"created_at":"Tue Apr 22 05:14:47 +0000 2008","favourites_count":6773,"utc_offset":-18000,"time_zone":"Quito","geo_enabled":true,"verified":false,"statuses_count":5527,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"F4FFFF","profile_background_image_url":"http:\/\/abs.twimg.com\/images\/themes\/theme15\/bg.png","profile_background_image_url_https":"https:\/\/abs.twimg.com\/images\/themes\/theme15\/bg.png","profile_background_tile":false,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/3333204267\/51006fd104a17604e0398359ff5937ba_normal.jpeg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/3333204267\/51006fd104a17604e0398359ff5937ba_normal.jpeg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/14471007\/1359310744","profile_link_color":"8F1864","profile_sidebar_border_color":"FFFFFF","profile_sidebar_fill_color":"C0DFEC","profile_text_color":"333333","profile_use_background_image":false,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":false,"notifications":false},"sender_id":14471007,"sender_id_str":"14471007","sender_screen_name":"dianakimball","recipient":{"id":7505382,"id_str":"7505382","name":"Erik Michaels-Ober","screen_name":"sferik","location":"","description":"Prolonging the inevitable.","url":"https:\/\/t.co\/L2xIBaQPRf","entities":{"url":{"urls":[{"url":"https:\/\/t.co\/L2xIBaQPRf","expanded_url":"https:\/\/github.com\/sferik","display_url":"github.com\/sferik","indices":[0,23]}]},"description":{"urls":[]}},"protected":false,"followers_count":3946,"friends_count":345,"listed_count":205,"created_at":"Mon Jul 16 12:59:01 +0000 2007","favourites_count":8018,"utc_offset":3600,"time_zone":"Berlin","geo_enabled":true,"verified":false,"statuses_count":13011,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"000000","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/677717672\/bb0b3653dcf0644e344823e0a2eb3382.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/677717672\/bb0b3653dcf0644e344823e0a2eb3382.png","profile_background_tile":false,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/378800000757402331\/d8dfba561e2e94112a737f17e7d138ca_normal.jpeg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/378800000757402331\/d8dfba561e2e94112a737f17e7d138ca_normal.jpeg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/7505382\/1385736840","profile_link_color":"0084B4","profile_sidebar_border_color":"000000","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false},"recipient_id":7505382,"recipient_id_str":"7505382","recipient_screen_name":"sferik","created_at":"Tue Dec 31 14:45:02 +0000 2013","entities":{"hashtags":[{"text":"newride","indices":[3,11]}],"symbols":[],"urls":[{"url":"https:\/\/t.co\/7HIwCl68Y8","expanded_url":"https:\/\/twitter.com\/PUBLICBikes\/status\/350315569708412929","display_url":"twitter.com\/PUBLICBikes\/st\u2026","indices":[51,74]},{"url":"https:\/\/t.co\/JSSxDPr4Sf","expanded_url":"https:\/\/ton.twitter.com\/1.1\/ton\/data\/dm\/418030038152642560\/418030038161047552\/0cnHqrKV.jpg","display_url":"pic.twitter.com\/JSSxDPr4Sf","indices":[75,98]}],"user_mentions":[{"screen_name":"PUBLICBikes","name":"PUBLIC Bikes","id":30035888,"id_str":"30035888","indices":[17,29]}],"media":[{"id":418030038161047552,"id_str":"418030038161047552","indices":[75,98],"media_url":"https:\/\/ton.twitter.com\/1.1\/ton\/data\/dm\/418030038152642560\/418030038161047552\/0cnHqrKV.jpg","media_url_https":"https:\/\/ton.twitter.com\/1.1\/ton\/data\/dm\/418030038152642560\/418030038161047552\/0cnHqrKV.jpg","url":"https:\/\/t.co\/JSSxDPr4Sf","display_url":"pic.twitter.com\/JSSxDPr4Sf","expanded_url":"https:\/\/ton.twitter.com\/1.1\/ton\/data\/dm\/418030038152642560\/418030038161047552\/0cnHqrKV.jpg","type":"photo","sizes":{"medium":{"w":600,"h":600,"resize":"fit"},"large":{"w":640,"h":640,"resize":"fit"},"thumb":{"w":150,"h":150,"resize":"crop"},"small":{"w":340,"h":340,"resize":"fit"}}}]}}
|
@@ -1,7 +1,17 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
require 'helper'
|
2
3
|
|
3
4
|
describe Twitter::DirectMessage do
|
4
5
|
|
6
|
+
before do
|
7
|
+
@old_stderr = $stderr
|
8
|
+
$stderr = StringIO.new
|
9
|
+
end
|
10
|
+
|
11
|
+
after do
|
12
|
+
$stderr = @old_stderr
|
13
|
+
end
|
14
|
+
|
5
15
|
describe '#==' do
|
6
16
|
it 'returns true when objects IDs are the same' do
|
7
17
|
direct_message = Twitter::DirectMessage.new(:id => 1, :text => 'foo')
|
@@ -86,4 +96,136 @@ describe Twitter::DirectMessage do
|
|
86
96
|
end
|
87
97
|
end
|
88
98
|
|
99
|
+
describe '#hashtags' do
|
100
|
+
it 'returns an array of Entity::Hashtag when entities are set' do
|
101
|
+
hashtags_array = [
|
102
|
+
{
|
103
|
+
:text => 'twitter',
|
104
|
+
:indices => [10, 33],
|
105
|
+
}
|
106
|
+
]
|
107
|
+
hashtags = Twitter::DirectMessage.new(:id => 28_669_546_014, :entities => {:hashtags => hashtags_array}).hashtags
|
108
|
+
expect(hashtags).to be_an Array
|
109
|
+
expect(hashtags.first).to be_a Twitter::Entity::Hashtag
|
110
|
+
expect(hashtags.first.indices).to eq([10, 33])
|
111
|
+
expect(hashtags.first.text).to eq('twitter')
|
112
|
+
end
|
113
|
+
it 'is empty when not set' do
|
114
|
+
hashtags = Twitter::DirectMessage.new(:id => 28_669_546_014).hashtags
|
115
|
+
expect(hashtags).to be_empty
|
116
|
+
end
|
117
|
+
it 'warns when not set' do
|
118
|
+
Twitter::DirectMessage.new(:id => 28_669_546_014).hashtags
|
119
|
+
expect($stderr.string).to match(/To get hashtags, you must pass `:include_entities => true` when requesting the Twitter::DirectMessage\./)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe '#media' do
|
124
|
+
it 'returns media' do
|
125
|
+
media = Twitter::DirectMessage.new(:id => 28_669_546_014, :entities => {:media => [{:id => 1, :type => 'photo'}]}).media
|
126
|
+
expect(media).to be_an Array
|
127
|
+
expect(media.first).to be_a Twitter::Media::Photo
|
128
|
+
end
|
129
|
+
it 'is empty when not set' do
|
130
|
+
media = Twitter::DirectMessage.new(:id => 28_669_546_014).media
|
131
|
+
expect(media).to be_empty
|
132
|
+
end
|
133
|
+
it 'warns when not set' do
|
134
|
+
Twitter::DirectMessage.new(:id => 28_669_546_014).media
|
135
|
+
expect($stderr.string).to match(/To get media, you must pass `:include_entities => true` when requesting the Twitter::DirectMessage\./)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe '#symbols' do
|
140
|
+
it 'returns an array of Entity::Symbol when symbols are set' do
|
141
|
+
symbols_array = [
|
142
|
+
{:text => 'PEP', :indices => [114, 118]},
|
143
|
+
{:text => 'COKE', :indices => [128, 133]}
|
144
|
+
]
|
145
|
+
symbols = Twitter::DirectMessage.new(:id => 28_669_546_014, :entities => {:symbols => symbols_array}).symbols
|
146
|
+
expect(symbols).to be_an Array
|
147
|
+
expect(symbols.size).to eq(2)
|
148
|
+
expect(symbols.first).to be_a Twitter::Entity::Symbol
|
149
|
+
expect(symbols.first.indices).to eq([114, 118])
|
150
|
+
expect(symbols.first.text).to eq('PEP')
|
151
|
+
end
|
152
|
+
it 'is empty when not set' do
|
153
|
+
symbols = Twitter::DirectMessage.new(:id => 28_669_546_014).symbols
|
154
|
+
expect(symbols).to be_empty
|
155
|
+
end
|
156
|
+
it 'warns when not set' do
|
157
|
+
Twitter::DirectMessage.new(:id => 28_669_546_014).symbols
|
158
|
+
expect($stderr.string).to match(/To get symbols, you must pass `:include_entities => true` when requesting the Twitter::DirectMessage\./)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe '#uris' do
|
163
|
+
it 'returns an array of Entity::URIs when entities are set' do
|
164
|
+
urls_array = [
|
165
|
+
{
|
166
|
+
:url => 'http://example.com/t.co',
|
167
|
+
:expanded_url => 'http://example.com/expanded',
|
168
|
+
:display_url => 'example.com/expanded…',
|
169
|
+
:indices => [10, 33],
|
170
|
+
}
|
171
|
+
]
|
172
|
+
direct_message = Twitter::DirectMessage.new(:id => 28_669_546_014, :entities => {:urls => urls_array})
|
173
|
+
expect(direct_message.uris).to be_an Array
|
174
|
+
expect(direct_message.uris.first).to be_a Twitter::Entity::URI
|
175
|
+
expect(direct_message.uris.first.indices).to eq([10, 33])
|
176
|
+
expect(direct_message.uris.first.display_uri).to be_a String
|
177
|
+
expect(direct_message.uris.first.display_uri).to eq('example.com/expanded…')
|
178
|
+
end
|
179
|
+
it 'is empty when not set' do
|
180
|
+
direct_message = Twitter::DirectMessage.new(:id => 28_669_546_014)
|
181
|
+
expect(direct_message.uris).to be_empty
|
182
|
+
end
|
183
|
+
it 'warns when not set' do
|
184
|
+
Twitter::DirectMessage.new(:id => 28_669_546_014).urls
|
185
|
+
expect($stderr.string).to match(/To get urls, you must pass `:include_entities => true` when requesting the Twitter::DirectMessage\./)
|
186
|
+
end
|
187
|
+
it 'can handle strange urls' do
|
188
|
+
urls_array = [
|
189
|
+
{
|
190
|
+
:url => 'http://with_underscore.example.com/t.co',
|
191
|
+
:expanded_url => 'http://with_underscore.example.com/expanded',
|
192
|
+
:display_url => 'with_underscore.example.com/expanded…',
|
193
|
+
:indices => [10, 33],
|
194
|
+
}
|
195
|
+
]
|
196
|
+
direct_message = Twitter::DirectMessage.new(:id => 28_669_546_014, :entities => {:urls => urls_array})
|
197
|
+
uri = direct_message.uris.first
|
198
|
+
expect { uri.url }.not_to raise_error
|
199
|
+
expect { uri.expanded_url }.not_to raise_error
|
200
|
+
expect { uri.display_url }.not_to raise_error
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
describe '#user_mentions' do
|
205
|
+
it 'returns an array of Entity::UserMention when entities are set' do
|
206
|
+
user_mentions_array = [
|
207
|
+
{
|
208
|
+
:screen_name => 'sferik',
|
209
|
+
:name => 'Erik Michaels-Ober',
|
210
|
+
:id_str => '7_505_382',
|
211
|
+
:indices => [0, 6],
|
212
|
+
:id => 7_505_382,
|
213
|
+
}
|
214
|
+
]
|
215
|
+
user_mentions = Twitter::DirectMessage.new(:id => 28_669_546_014, :entities => {:user_mentions => user_mentions_array}).user_mentions
|
216
|
+
expect(user_mentions).to be_an Array
|
217
|
+
expect(user_mentions.first).to be_a Twitter::Entity::UserMention
|
218
|
+
expect(user_mentions.first.indices).to eq([0, 6])
|
219
|
+
expect(user_mentions.first.id).to eq(7_505_382)
|
220
|
+
end
|
221
|
+
it 'is empty when not set' do
|
222
|
+
user_mentions = Twitter::DirectMessage.new(:id => 28_669_546_014).user_mentions
|
223
|
+
expect(user_mentions).to be_empty
|
224
|
+
end
|
225
|
+
it 'warns when not set' do
|
226
|
+
Twitter::DirectMessage.new(:id => 28_669_546_014).user_mentions
|
227
|
+
expect($stderr.string).to match(/To get user mentions, you must pass `:include_entities => true` when requesting the Twitter::DirectMessage\./)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
89
231
|
end
|