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
         |