Skip to content

Commit

Permalink
Add entities to direct messages
Browse files Browse the repository at this point in the history
  • Loading branch information
sferik committed Dec 31, 2013
1 parent c596690 commit d911deb
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 81 deletions.
2 changes: 2 additions & 0 deletions lib/twitter/direct_message.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
require 'twitter/creatable'
require 'twitter/entities'
require 'twitter/identity'

module Twitter
class DirectMessage < Twitter::Identity
include Twitter::Creatable
include Twitter::Entities
attr_reader :text
alias_method :full_text, :text
object_attr_reader :User, :recipient
Expand Down
69 changes: 69 additions & 0 deletions lib/twitter/entities.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
require 'memoizable'
require 'twitter/entity/hashtag'
require 'twitter/entity/symbol'
require 'twitter/entity/uri'
require 'twitter/entity/user_mention'
require 'twitter/media_factory'

module Twitter
module Entities
include Memoizable

# @note Must include entities in your request for this method to work
# @return [Array<Twitter::Entity::Hashtag>]
def hashtags
entities(Entity::Hashtag, :hashtags)
end
memoize :hashtags

# @note Must include entities in your request for this method to work
# @return [Array<Twitter::Media>]
def media
entities(MediaFactory, :media)
end
memoize :media

# @note Must include entities in your request for this method to work
# @return [Array<Twitter::Entity::Symbol>]
def symbols
entities(Entity::Symbol, :symbols)
end
memoize :symbols

# @note Must include entities in your request for this method to work
# @return [Array<Twitter::Entity::URI>]
def uris
entities(Entity::URI, :urls)
end
memoize :uris
alias_method :urls, :uris

# @note Must include entities in your request for this method to work
# @return [Array<Twitter::Entity::UserMention>]
def user_mentions
entities(Entity::UserMention, :user_mentions)
end
memoize :user_mentions

private

# @return [Boolean]
def entities?
!@attrs[:entities].nil? && @attrs[:entities].any? { |_, array| !array.empty? }
end
memoize :entities?

# @param klass [Class]
# @param key [Symbol]
def entities(klass, key)
if entities?
Array(@attrs[:entities][key.to_sym]).map do |entity|
klass.new(entity)
end
else
warn "#{Kernel.caller.first}: To get #{key.to_s.tr('_', ' ')}, you must pass `:include_entities => true` when requesting the #{self.class}."
[]
end
end
end
end
60 changes: 3 additions & 57 deletions lib/twitter/tweet.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
require 'twitter/creatable'
require 'twitter/entities'
require 'twitter/identity'

module Twitter
class Tweet < Twitter::Identity
include Twitter::Creatable
include Twitter::Entities
attr_reader :favorite_count, :favorited, :in_reply_to_screen_name,
:in_reply_to_attrs_id, :in_reply_to_status_id,
:in_reply_to_user_id, :lang, :retweet_count, :retweeted,
Expand All @@ -21,12 +24,6 @@ class Tweet < Twitter::Identity
alias_method :retweeted_tweet?, :retweeted_status?
object_attr_reader :User, :user, :status

# @return [Boolean]
def entities?
!@attrs[:entities].nil? && @attrs[:entities].any? { |_, array| !array.empty? }
end
memoize :entities?

def filter_level
@attrs[:filter_level] || 'none'
end
Expand All @@ -44,69 +41,18 @@ def full_text
end
memoize :full_text

# @note Must include entities in your request for this method to work
# @return [Array<Twitter::Entity::Hashtag>]
def hashtags
entities(Entity::Hashtag, :hashtags)
end
memoize :hashtags

# @note Must include entities in your request for this method to work
# @return [Array<Twitter::Media>]
def media
entities(MediaFactory, :media)
end
memoize :media

# @return [Boolean]
def reply?
!!@attrs[:in_reply_to_status_id]
end
memoize :reply?

# @note Must include entities in your request for this method to work
# @return [Array<Twitter::Entity::Symbol>]
def symbols
entities(Entity::Symbol, :symbols)
end
memoize :symbols

# @return [String] The URL to the tweet.
def uri
Addressable::URI.parse("https://twitter.com/#{user.screen_name}/status/#{id}")
end
memoize :uri
alias_method :url, :uri

# @note Must include entities in your request for this method to work
# @return [Array<Twitter::Entity::URI>]
def uris
entities(Entity::URI, :urls)
end
memoize :uris
alias_method :urls, :uris

# @note Must include entities in your request for this method to work
# @return [Array<Twitter::Entity::UserMention>]
def user_mentions
entities(Entity::UserMention, :user_mentions)
end
memoize :user_mentions

private

# @param klass [Class]
# @param key [Symbol]
def entities(klass, key)
if entities?
Array(@attrs[:entities][key.to_sym]).map do |entity|
klass.new(entity)
end
else
warn "#{Kernel.caller.first}: To get #{key.to_s.tr('_', ' ')}, you must pass `:include_entities => true` when requesting the #{self.class}."
[]
end
end
end
Status = Tweet # rubocop:disable ConstantName
end
141 changes: 141 additions & 0 deletions spec/twitter/direct_message_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

describe Twitter::DirectMessage do

before do
@old_stderr = $stderr
$stderr = StringIO.new
end

after do
$stderr = @old_stderr
end

describe '#==' do
it 'returns true when objects IDs are the same' do
direct_message = Twitter::DirectMessage.new(:id => 1, :text => 'foo')
Expand Down Expand Up @@ -86,4 +95,136 @@
end
end

describe '#hashtags' do
it 'returns an array of Entity::Hashtag when entities are set' do
hashtags_array = [
{
:text => 'twitter',
:indices => [10, 33],
}
]
hashtags = Twitter::DirectMessage.new(:id => 28_669_546_014, :entities => {:hashtags => hashtags_array}).hashtags
expect(hashtags).to be_an Array
expect(hashtags.first).to be_a Twitter::Entity::Hashtag
expect(hashtags.first.indices).to eq([10, 33])
expect(hashtags.first.text).to eq('twitter')
end
it 'is empty when not set' do
hashtags = Twitter::DirectMessage.new(:id => 28_669_546_014).hashtags
expect(hashtags).to be_empty
end
it 'warns when not set' do
Twitter::DirectMessage.new(:id => 28_669_546_014).hashtags
expect($stderr.string).to match(/To get hashtags, you must pass `:include_entities => true` when requesting the Twitter::DirectMessage\./)
end
end

describe '#media' do
it 'returns media' do
media = Twitter::DirectMessage.new(:id => 28_669_546_014, :entities => {:media => [{:id => 1, :type => 'photo'}]}).media
expect(media).to be_an Array
expect(media.first).to be_a Twitter::Media::Photo
end
it 'is empty when not set' do
media = Twitter::DirectMessage.new(:id => 28_669_546_014).media
expect(media).to be_empty
end
it 'warns when not set' do
Twitter::DirectMessage.new(:id => 28_669_546_014).media
expect($stderr.string).to match(/To get media, you must pass `:include_entities => true` when requesting the Twitter::DirectMessage\./)
end
end

describe '#symbols' do
it 'returns an array of Entity::Symbol when symbols are set' do
symbols_array = [
{:text => 'PEP', :indices => [114, 118]},
{:text => 'COKE', :indices => [128, 133]}
]
symbols = Twitter::DirectMessage.new(:id => 28_669_546_014, :entities => {:symbols => symbols_array}).symbols
expect(symbols).to be_an Array
expect(symbols.size).to eq(2)
expect(symbols.first).to be_a Twitter::Entity::Symbol
expect(symbols.first.indices).to eq([114, 118])
expect(symbols.first.text).to eq('PEP')
end
it 'is empty when not set' do
symbols = Twitter::DirectMessage.new(:id => 28_669_546_014).symbols
expect(symbols).to be_empty
end
it 'warns when not set' do
Twitter::DirectMessage.new(:id => 28_669_546_014).symbols
expect($stderr.string).to match(/To get symbols, you must pass `:include_entities => true` when requesting the Twitter::DirectMessage\./)
end
end

describe '#uris' do
it 'returns an array of Entity::URIs when entities are set' do
urls_array = [
{
:url => 'http://example.com/t.co',
:expanded_url => 'http://example.com/expanded',
:display_url => 'example.com/expanded…',
:indices => [10, 33],
}
]
direct_message = Twitter::DirectMessage.new(:id => 28_669_546_014, :entities => {:urls => urls_array})
expect(direct_message.uris).to be_an Array
expect(direct_message.uris.first).to be_a Twitter::Entity::URI
expect(direct_message.uris.first.indices).to eq([10, 33])
expect(direct_message.uris.first.display_uri).to be_a String
expect(direct_message.uris.first.display_uri).to eq('example.com/expanded…')
end
it 'is empty when not set' do
direct_message = Twitter::DirectMessage.new(:id => 28_669_546_014)
expect(direct_message.uris).to be_empty
end
it 'warns when not set' do
Twitter::DirectMessage.new(:id => 28_669_546_014).urls
expect($stderr.string).to match(/To get urls, you must pass `:include_entities => true` when requesting the Twitter::DirectMessage\./)
end
it 'can handle strange urls' do
urls_array = [
{
:url => 'http://with_underscore.example.com/t.co',
:expanded_url => 'http://with_underscore.example.com/expanded',
:display_url => 'with_underscore.example.com/expanded…',
:indices => [10, 33],
}
]
direct_message = Twitter::DirectMessage.new(:id => 28_669_546_014, :entities => {:urls => urls_array})
uri = direct_message.uris.first
expect { uri.url }.not_to raise_error
expect { uri.expanded_url }.not_to raise_error
expect { uri.display_url }.not_to raise_error
end
end

describe '#user_mentions' do
it 'returns an array of Entity::UserMention when entities are set' do
user_mentions_array = [
{
:screen_name => 'sferik',
:name => 'Erik Michaels-Ober',
:id_str => '7_505_382',
:indices => [0, 6],
:id => 7_505_382,
}
]
user_mentions = Twitter::DirectMessage.new(:id => 28_669_546_014, :entities => {:user_mentions => user_mentions_array}).user_mentions
expect(user_mentions).to be_an Array
expect(user_mentions.first).to be_a Twitter::Entity::UserMention
expect(user_mentions.first.indices).to eq([0, 6])
expect(user_mentions.first.id).to eq(7_505_382)
end
it 'is empty when not set' do
user_mentions = Twitter::DirectMessage.new(:id => 28_669_546_014).user_mentions
expect(user_mentions).to be_empty
end
it 'warns when not set' do
Twitter::DirectMessage.new(:id => 28_669_546_014).user_mentions
expect($stderr.string).to match(/To get user mentions, you must pass `:include_entities => true` when requesting the Twitter::DirectMessage\./)
end
end

end
24 changes: 0 additions & 24 deletions spec/twitter/tweet_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,30 +52,6 @@
end
end

describe '#entities?' do
it 'returns false if there are no entities set' do
tweet = Twitter::Tweet.new(:id => 28_669_546_014)
expect(tweet.entities?).to be false
end

it 'returns false if there are blank lists of entities set' do
tweet = Twitter::Tweet.new(:id => 28_669_546_014, :entities => {:urls => []})
expect(tweet.entities?).to be false
end
it 'returns true if there are entities set' do
urls_array = [
{
:url => 'http://example.com/t.co',
:expanded_url => 'http://example.com/expanded',
:display_url => 'example.com/expanded…',
:indices => [10, 33],
}
]
tweet = Twitter::Tweet.new(:id => 28_669_546_014, :entities => {:urls => urls_array})
expect(tweet.entities?).to be true
end
end

describe '#filter_level' do
it 'returns the filter level when filter_level is set' do
tweet = Twitter::Tweet.new(:id => 28_669_546_014, :filter_level => 'high')
Expand Down

0 comments on commit d911deb

Please sign in to comment.