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.
@@ -49,7 +49,7 @@ module Twitter
49
49
  # @param path [String]
50
50
  # @param args [Array]
51
51
  # @return [Array<Twitter::User>]
52
- def threaded_user_objects_from_response(request_method, path, args)
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 threaded_objects_from_response(klass, request_method, path, args) # rubocop:disable ParameterLists
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)
@@ -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
- set_attrs(attrs)
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
- set_attrs(response[:body])
69
+ self.attrs = response[:body]
70
70
  end
71
71
 
72
- def set_attrs(attrs)
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.
@@ -38,7 +38,7 @@ module Twitter
38
38
  #
39
39
  # @return [Time]
40
40
  def as_of
41
- Time.parse(@attrs[:as_of]) if @attrs[:as_of]
41
+ Time.parse(@attrs[:as_of]) unless @attrs[:as_of].nil?
42
42
  end
43
43
  memoize :as_of
44
44
 
@@ -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
- attr_reader :favorite_count, :favorited, :in_reply_to_screen_name,
7
- :in_reply_to_attrs_id, :in_reply_to_status_id,
8
- :in_reply_to_user_id, :lang, :retweet_count, :retweeted,
9
- :source, :text, :truncated
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 retweeted_status?
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
@@ -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]) if @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
@@ -1,13 +1,12 @@
1
1
  module Twitter
2
2
  module Utils
3
- class << self
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)
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
@@ -1,8 +1,8 @@
1
1
  module Twitter
2
2
  class Version
3
3
  MAJOR = 5
4
- MINOR = 4
5
- PATCH = 1
4
+ MINOR = 5
5
+ PATCH = 0
6
6
  PRE = nil
7
7
 
8
8
  class << self
@@ -1 +1 @@
1
- {"sender_screen_name":"sferik","recipient_screen_name":"pengwynn","recipient_id":14100886,"recipient":{"profile_background_tile":false,"profile_sidebar_fill_color":"dddddd","description":"Christian husband and father. Dev Experience @ HP Cloud Services. Co-host of the @changelogshow. Mashup of design & development.","friends_count":1877,"follow_request_sent":false,"notifications":false,"profile_sidebar_border_color":"cccccc","verified":false,"time_zone":"Central Time (US & Canada)","favourites_count":32,"url":"http:\/\/wynnnetherland.com","profile_background_color":"efefef","listed_count":184,"lang":"en","created_at":"Sat Mar 08 16:34:22 +0000 2008","location":"Dallas, TX","show_all_inline_media":false,"statuses_count":3928,"profile_use_background_image":true,"profile_text_color":"666666","protected":false,"profile_image_url":"http:\/\/a2.twimg.com\/profile_images\/485575482\/komikazee_normal.png","id_str":"14100886","geo_enabled":true,"name":"Wynn Netherland","contributors_enabled":false,"following":true,"profile_background_image_url":"http:\/\/a1.twimg.com\/profile_background_images\/61741268\/twitter-small.png","profile_link_color":"35abe9","screen_name":"pengwynn","id":14100886,"utc_offset":-21600,"followers_count":2767},"created_at":"Tue Oct 26 21:24:23 +0000 2010","id_str":"1825786345","sender":{"profile_background_tile":false,"profile_sidebar_fill_color":"DDEEF6","description":"Adventures in hunger and foolishness.","friends_count":88,"follow_request_sent":false,"notifications":false,"profile_sidebar_border_color":"C0DEED","verified":false,"time_zone":"Pacific Time (US & Canada)","favourites_count":729,"url":null,"profile_background_color":"000000","listed_count":28,"lang":"en","created_at":"Mon Jul 16 12:59:01 +0000 2007","location":"San Francisco","show_all_inline_media":true,"statuses_count":2970,"profile_use_background_image":true,"profile_text_color":"333333","protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","id_str":"7505382","geo_enabled":true,"name":"Erik Michaels-Ober","contributors_enabled":false,"following":false,"profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","screen_name":"sferik","id":7505382,"utc_offset":-28800,"followers_count":898},"sender_id":7505382,"id":1825786345,"text":"Creating a fixture for the Twitter gem"}
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