Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Major changes for Twitter API v1.1

  • Loading branch information...
commit eab13be653c1b54aa679dbf16f252a2b6977b80e 1 parent 2829710
@sferik authored
View
2  README.md
@@ -273,7 +273,7 @@ Here are some fun facts about the 3.0 release:
* The entire library is implemented in just 2,000 lines of code
* With over 5,000 lines of specs, the spec-to-code ratio is over 2.5:1
-* The spec suite contains 661 examples and runs in under 2 seconds on a MacBook
+* The spec suite contains 662 examples and runs in under 2 seconds on a MacBook
* This project has 100% C0 code coverage (the tests execute every line of
source code at least once)
* At the time of release, this library is comprehensive: you can request all
View
291 lib/twitter/api.rb
@@ -25,7 +25,9 @@
module Twitter
module API
DEFAULT_CURSOR = -1
+ DEFAULT_TWEETS_PER_REQUEST = 20
MAX_USERS_PER_REQUEST = 100
+ MAX_TWEETS_PER_REQUEST = 200
METHOD_RATE_LIMITED = {
:accept => false,
:activity_about_me => true,
@@ -140,6 +142,9 @@ module API
:tos => true,
:trend_locations => true,
:trends => true,
+ :trends_available => true,
+ :trends_closest => true,
+ :trends_place => true,
:trends_daily => true,
:trends_weekly => true,
:tweet_activity => true,
@@ -383,7 +388,7 @@ def direct_messages_sent(options={})
# Destroys direct messages
#
- # @see https://dev.twitter.com/docs/api/1.1/post/direct_messages/destroy/:id
+ # @see https://dev.twitter.com/docs/api/1.1/post/direct_messages/destroy
# @note This method requires an access token with RWD (read, write & direct message) permissions. Consult The Application Permission Model for more information.
# @rate_limited No
# @authentication_required Requires user context
@@ -418,7 +423,8 @@ def direct_message_destroy(*args)
# Twitter.direct_message_create(7505382, "I'm sending you this message via @gem!") # Same as above
def direct_message_create(user, text, options={})
options.merge_user!(user)
- object_from_response(Twitter::DirectMessage, :post, "/1.1/direct_messages/new.json", options.merge(:text => text))
+ options[:text] = text
+ object_from_response(Twitter::DirectMessage, :post, "/1.1/direct_messages/new.json", options)
end
alias d direct_message_create
alias m direct_message_create
@@ -436,7 +442,7 @@ def direct_message_create(user, text, options={})
# @example Return the direct message with the id 1825786345
# Twitter.direct_message(1825786345)
def direct_message(id, options={})
- options.merge!(:id => id)
+ options[:id] = id
object_from_response(Twitter::DirectMessage, :get, "/1.1/direct_messages/show.json", options)
end
@@ -459,14 +465,14 @@ def direct_message(id, options={})
# @overload direct_messages(*ids)
# Returns direct messages
#
- # @see https://dev.twitter.com/docs/api/1.1/get/direct_messages/show/:id
+ # @see https://dev.twitter.com/docs/api/1.1/get/direct_messages/show
# @param ids [Array<Integer>, Set<Integer>] An array of Tweet IDs.
# @example Return the direct message with the id 1825786345
# Twitter.direct_messages(1825786345)
# @overload direct_messages(*ids, options)
# Returns direct messages
#
- # @see https://dev.twitter.com/docs/api/1.1/get/direct_messages/show/:id
+ # @see https://dev.twitter.com/docs/api/1.1/get/direct_messages/show
# @param ids [Array<Integer>, Set<Integer>] An array of Tweet IDs.
# @param options [Hash] A customizable set of options.
def direct_messages(*args)
@@ -475,7 +481,7 @@ def direct_messages(*args)
direct_messages_received(options)
else
args.flatten.threaded_map do |id|
- object_from_response(Twitter::DirectMessage, :get, "/1.1/direct_messages/show/#{id}.json", options)
+ direct_message(id, options)
end
end
end
@@ -532,23 +538,20 @@ def friend_ids(*args)
# Test for the existence of friendship between two users
#
- # @see https://dev.twitter.com/docs/api/1.1/get/friendships/exists
- # @note Consider using {Twitter::API::Friendships#friendship} instead of this method.
+ # @see https://dev.twitter.com/docs/api/1.1/get/friendships/show
# @rate_limited Yes
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
# @return [Boolean] true if user_a follows user_b, otherwise false.
- # @param user_a [Integer, String, Twitter::User] The Twitter user ID, screen name, or object of the subject user.
- # @param user_b [Integer, String, Twitter::User] The Twitter user ID, screen name, or object of the user to test for following.
+ # @param source [Integer, String, Twitter::User] The Twitter user ID, screen name, or object of the source user.
+ # @param target [Integer, String, Twitter::User] The Twitter user ID, screen name, or object of the target user.
# @param options [Hash] A customizable set of options.
# @example Return true if @sferik follows @pengwynn
# Twitter.friendship?('sferik', 'pengwynn')
# Twitter.friendship?('sferik', 14100886) # Same as above
# Twitter.friendship?(7505382, 14100886) # Same as above
- def friendship?(user_a, user_b, options={})
- options.merge_user!(user_a, nil, "a")
- options.merge_user!(user_b, nil, "b")
- get("/1.1/friendships/exists.json", options)[:body]
+ def friendship?(source, target, options={})
+ friendship(source, target, options).source.following?
end
# Returns an array of numeric IDs for every user who has a pending request to follow the authenticating user
@@ -563,7 +566,8 @@ def friendship?(user_a, user_b, options={})
# @example Return an array of numeric IDs for every user who has a pending request to follow the authenticating user
# Twitter.friendships_incoming
def friendships_incoming(options={})
- cursor_from_response(:ids, nil, :get, "/1.1/friendships/incoming.json", {:cursor => DEFAULT_CURSOR}.merge(options))
+ merge_default_cursor!(options)
+ cursor_from_response(:ids, nil, :get, "/1.1/friendships/incoming.json", options)
end
# Returns an array of numeric IDs for every protected user for whom the authenticating user has a pending follow request
@@ -578,7 +582,8 @@ def friendships_incoming(options={})
# @example Return an array of numeric IDs for every protected user for whom the authenticating user has a pending follow request
# Twitter.friendships_outgoing
def friendships_outgoing(options={})
- cursor_from_response(:ids, nil, :get, "/1.1/friendships/outgoing.json", {:cursor => DEFAULT_CURSOR}.merge(options))
+ merge_default_cursor!(options)
+ cursor_from_response(:ids, nil, :get, "/1.1/friendships/outgoing.json", options)
end
# Returns detailed information about the relationship between two users
@@ -624,7 +629,7 @@ def follow(*args)
options = args.extract_options!
# Twitter always turns on notifications if the "follow" option is present, even if it's set to false
# so only send follow if it's true
- options.merge!(:follow => true) if options.delete(:follow)
+ options[:follow] = true if !!options.delete(:follow)
existing_friends = Thread.new do
friend_ids.ids
end
@@ -654,10 +659,11 @@ def follow!(*args)
options = args.extract_options!
# Twitter always turns on notifications if the "follow" option is present, even if it's set to false
# so only send follow if it's true
- options.merge!(:follow => true) if options.delete(:follow)
+ options[:follow] = true if !!options.delete(:follow)
args.flatten.threaded_map do |user|
begin
- object_from_response(Twitter::User, :post, "/1.1/friendships/create.json", options.merge_user(user))
+ options.merge_user!(user)
+ object_from_response(Twitter::User, :post, "/1.1/friendships/create.json", options)
rescue Twitter::Error::Forbidden
# This error will be raised if the user doesn't have permission to
# follow list_member, for whatever reason.
@@ -727,7 +733,8 @@ def friendship_update(user, options={})
# Returns an array of user_ids that the currently authenticated user does not want to see retweets from.
#
- # @see https://dev.twitter.com/docs/api/1.1/get/friendships/no_retweet_ids
+ # @deprecated This method has been deprecated without replacement and will stop working on March 5, 2013.
+ # @see https://dev.twitter.com/docs/api/1/get/friendships/no_retweet_ids
# @rate_limited Yes
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
@@ -737,7 +744,8 @@ def friendship_update(user, options={})
# @example Enable rewteets and devise notifications for @sferik
# Twitter.no_retweet_ids
def no_retweet_ids(options={})
- get("/1.1/friendships/no_retweet_ids.json", options)[:body]
+ warn "#{Kernel.caller.first}: [DEPRECATION] Twitter::API#no_retweet_ids has been deprecated without replacement and will stop working on March 5, 2013."
+ get("/1/friendships/no_retweet_ids.json", options)[:body].map(&:to_i)
end
# Allows the authenticating user to accept the specified users' follow requests
@@ -927,27 +935,6 @@ def tos(options={})
get("/1.1/help/tos.json", options)[:body][:tos]
end
- # Returns all lists the authenticating or specified user subscribes to, including their own
- #
- # @see https://dev.twitter.com/docs/api/1.1/get/lists/all
- # @rate_limited Yes
- # @authentication_required Requires user context
- # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
- # @return [Array<Twitter::List>]
- # @overload lists_subscribed_to(options={})
- # @param options [Hash] A customizable set of options.
- # @example Return all lists the authenticating user subscribes to
- # Twitter.lists_subscribed_to
- # @overload lists_subscribed_to(user, options={})
- # @param user [Integer, String, Twitter::User] A Twitter user ID, screen name, or object.
- # @param options [Hash] A customizable set of options.
- # @example Return all lists the specified user subscribes to
- # Twitter.lists_subscribed_to('sferik')
- # Twitter.lists_subscribed_to(8863586)
- def lists_subscribed_to(*args)
- objects_from_response(Twitter::List, :get, "/1.1/lists/all.json", args)
- end
-
# Show tweet timeline for members of the specified list
#
# @see https://dev.twitter.com/docs/api/1.1/get/lists/statuses
@@ -1390,28 +1377,21 @@ def list_create(name, options={})
end
# List the lists of the specified user
+ # Returns all lists the authenticating or specified user subscribes to, including their own.
#
- # @see https://dev.twitter.com/docs/api/1.1/get/lists
- # @note Private lists will be included if the authenticated user is the same as the user whose lists are being returned.
+ # @see https://dev.twitter.com/docs/api/1.1/get/lists/list
# @rate_limited Yes
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
# @return [Twitter::Cursor]
- # @overload lists(options={})
- # @param options [Hash] A customizable set of options.
- # @option options [Integer] :cursor (-1) Breaks the results into pages. Provide values as returned in the response objects's next_cursor and previous_cursor attributes to page back and forth in the list.
- # @example List the authenticated user's lists
- # Twitter.lists
- # @overload lists(user, options={})
- # @param user [Integer, String, Twitter::User] A Twitter user ID, screen name, or object.
- # @param options [Hash] A customizable set of options.
- # @option options [Integer] :cursor (-1) Breaks the results into pages. Provide values as returned in the response objects's next_cursor and previous_cursor attributes to page back and forth in the list.
- # @example List @sferik's lists
- # Twitter.lists('sferik')
- # Twitter.lists(7505382)
+ # @param options [Hash] A customizable set of options.
+ # @option options [Integer] :cursor (-1) Breaks the results into pages. Provide values as returned in the response objects's next_cursor and previous_cursor attributes to page back and forth in the list.
+ # @example List the authenticated user's lists
+ # Twitter.lists
def lists(*args)
- lists_from_response(:get, "/1.1/lists.json", args)
+ lists_from_response(:get, "/1.1/lists/list.json", args)
end
+ alias lists_subscribed_to lists
# Show the specified list
#
@@ -1548,7 +1528,7 @@ def saved_search_destroy(*args)
# Returns tweets that match a specified query.
#
- # @see https://dev.twitter.com/docs/api/1.1/get/search
+ # @see https://dev.twitter.com/docs/api/1.1/get/search/tweets
# @see https://dev.twitter.com/docs/using-search
# @see https://dev.twitter.com/docs/history-rest-search-api
# @note As of April 1st 2010, the Search API provides an option to retrieve "popular tweets" in addition to real-time search results. In an upcoming release, this will become the default and clients that don't want to receive popular tweets in their search results will have to explicitly opt-out. See the result_type parameter below for more information.
@@ -1590,7 +1570,7 @@ def phoenix_search(q, options={})
search_collection_from_response(:get, "/phoenix_search.phoenix", options.merge(:q => q))
end
- # @see https://dev.twitter.com/docs/api/1.1/get/favorites
+ # @see https://dev.twitter.com/docs/api/1.1/get/favorites/list
# @rate_limited Yes
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
@@ -1614,12 +1594,10 @@ def phoenix_search(q, options={})
# Twitter.favorites('sferik')
def favorites(*args)
options = args.extract_options!
- url = if user = args.pop
- "/1.1/favorites/#{user}.json"
- else
- "/1.1/favorites.json"
+ if user = args.pop
+ options.merge_user!(user)
end
- collection_from_response(Twitter::Tweet, :get, url, options)
+ collection_from_response(Twitter::Tweet, :get, "/1.1/favorites/list.json", options)
end
# Favorites the specified Tweets as the authenticating user
@@ -1683,8 +1661,8 @@ def unfavorite(*args)
# @option options [Boolean, String, Integer] :trim_user Each tweet returned in a timeline will include a user object with only the author's numerical ID when set to true, 't' or 1.
# @option options [Boolean, String, Integer] :exclude_replies This parameter will prevent replies from appearing in the returned timeline. Using exclude_replies with the count parameter will mean you will receive up-to count tweets - this is because the count parameter retrieves that many tweets before filtering out retweets and replies.
# @option options [Boolean, String, Integer] :include_rts Specifies that the timeline should include native retweets in addition to regular tweets. Note: If you're using the trim_user parameter in conjunction with include_rts, the retweets will no longer contain a full user object.
+ # @option options [Boolean, String, Integer] :contributor_details Specifies that the contributors element should be enhanced to include the screen_name of the contributor.
# @option options [Boolean, String, Integer] :include_entities Specifies that each tweet should include an 'entities' node including metadata about the tweet such as: user_mentions, urls, and hashtags.
- # @option options [Boolean] :contributor_details Specifies that the contributors element should be enhanced to include the screen_name of the contributor.
# @example Return the 20 most recent Tweets, including retweets if they exist, posted by the authenticating user and the users they follow
# Twitter.home_timeline
def home_timeline(options={})
@@ -1713,44 +1691,62 @@ def mentions_timeline(options={})
# Returns the 20 most recent retweets posted by the specified user
#
- # @see https://dev.twitter.com/docs/api/1.1/get/statuses/retweeted_by_user
+ # @see https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline
+ # @note This method can only return up to 3,200 Tweets.
# @rate_limited Yes
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
# @return [Array<Twitter::Tweet>]
+ # @param user [Integer, String, Twitter::User] A Twitter user ID, screen name, or object.
# @param options [Hash] A customizable set of options.
# @option options [Integer] :since_id Returns results with an ID greater than (that is, more recent than) the specified ID.
# @option options [Integer] :max_id Returns results with an ID less than (that is, older than) or equal to the specified ID.
# @option options [Integer] :count Specifies the number of records to retrieve. Must be less than or equal to 200.
# @option options [Boolean, String, Integer] :trim_user Each tweet returned in a timeline will include a user object with only the author's numerical ID when set to true, 't' or 1.
- # @example Return the 20 most recent retweets posted by the authenticating user
+ # @option options [Boolean, String, Integer] :exclude_replies This parameter will prevent replies from appearing in the returned timeline. Using exclude_replies with the count parameter will mean you will receive up-to count tweets - this is because the count parameter retrieves that many tweets before filtering out retweets and replies.
+ # @option options [Boolean, String, Integer] :contributor_details Specifies that the contributors element should be enhanced to include the screen_name of the contributor.
+ # @example Return the 20 most recent retweets posted by @sferik
# Twitter.retweeted_by_user('sferik')
def retweeted_by_user(user, options={})
- collection_from_response(Twitter::Tweet, :get, "/1.1/statuses/retweeted_by_user.json", options.merge_user!(user))
+ options[:include_rts] = true
+ count = options[:count] || DEFAULT_TWEETS_PER_REQUEST
+ collect_with_count(count) do |count_options|
+ select_retweets(user_timeline(user, options.merge(count_options)))
+ end
end
alias retweeted_by retweeted_by_user
# Returns the 20 most recent retweets posted by the authenticating user
#
- # @see https://dev.twitter.com/docs/api/1.1/get/statuses/retweeted_by_me
+ # @see https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline
+ # @note This method can only return up to 3,200 Tweets.
# @rate_limited Yes
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
# @return [Array<Twitter::Tweet>]
+ # @param user [Integer, String, Twitter::User] A Twitter user ID, screen name, or object.
# @param options [Hash] A customizable set of options.
# @option options [Integer] :since_id Returns results with an ID greater than (that is, more recent than) the specified ID.
# @option options [Integer] :max_id Returns results with an ID less than (that is, older than) or equal to the specified ID.
# @option options [Integer] :count Specifies the number of records to retrieve. Must be less than or equal to 200.
# @option options [Boolean, String, Integer] :trim_user Each tweet returned in a timeline will include a user object with only the author's numerical ID when set to true, 't' or 1.
+ # @option options [Boolean, String, Integer] :exclude_replies This parameter will prevent replies from appearing in the returned timeline. Using exclude_replies with the count parameter will mean you will receive up-to count tweets - this is because the count parameter retrieves that many tweets before filtering out retweets and replies.
+ # @option options [Boolean, String, Integer] :contributor_details Specifies that the contributors element should be enhanced to include the screen_name of the contributor.
# @example Return the 20 most recent retweets posted by the authenticating user
# Twitter.retweeted_by_me
def retweeted_by_me(options={})
- collection_from_response(Twitter::Tweet, :get, "/1.1/statuses/retweeted_by_me.json", options)
+ options[:include_rts] = true
+ count = options[:count] || DEFAULT_TWEETS_PER_REQUEST
+ collect_with_count(count) do |count_options|
+ select_retweets(user_timeline(options.merge(count_options)))
+ end
end
+ alias retweeted_by retweeted_by_user
# Returns the 20 most recent retweets posted by users the specified user follows
#
- # @see https://dev.twitter.com/docs/api/1.1/get/statuses/retweeted_to_user
+ # @deprecated This method has been deprecated without replacement and will stop working on March 5, 2013.
+ # @see https://dev.twitter.com/docs/api/1/get/statuses/retweeted_to_user
# @rate_limited Yes
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
@@ -1761,16 +1757,20 @@ def retweeted_by_me(options={})
# @option options [Integer] :max_id Returns results with an ID less than (that is, older than) or equal to the specified ID.
# @option options [Integer] :count Specifies the number of records to retrieve. Must be less than or equal to 200.
# @option options [Boolean, String, Integer] :trim_user Each tweet returned in a timeline will include a user object with only the author's numerical ID when set to true, 't' or 1.
+ # @option options [Boolean, String, Integer] :include_entities Specifies that each tweet should include an 'entities' node including metadata about the tweet such as: user_mentions, urls, and hashtags.
# @example Return the 20 most recent retweets posted by users followed by the specified user
# Twitter.retweeted_to_user('sferik')
def retweeted_to_user(user, options={})
- collection_from_response(Twitter::Tweet, :get, "/1.1/statuses/retweeted_to_user.json", options.merge_user!(user))
+ warn "#{Kernel.caller.first}: [DEPRECATION] Twitter::API#retweeted_to_user has been deprecated without replacement and will stop working on March 5, 2013."
+ options.merge_user!(user)
+ collection_from_response(Twitter::Tweet, :get, "/1/statuses/retweeted_to_user.json", options)
end
alias retweeted_to retweeted_to_user
# Returns the 20 most recent retweets posted by users the authenticating user follow.
#
- # @see https://dev.twitter.com/docs/api/1.1/get/statuses/retweeted_to_me
+ # @see https://dev.twitter.com/docs/api/1.1/get/statuses/home_timeline
+ # @note This method can only return up to 800 Tweets, including retweets.
# @rate_limited Yes
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
@@ -1780,15 +1780,23 @@ def retweeted_to_user(user, options={})
# @option options [Integer] :max_id Returns results with an ID less than (that is, older than) or equal to the specified ID.
# @option options [Integer] :count Specifies the number of records to retrieve. Must be less than or equal to 200.
# @option options [Boolean, String, Integer] :trim_user Each tweet returned in a timeline will include a user object with only the author's numerical ID when set to true, 't' or 1.
+ # @option options [Boolean, String, Integer] :exclude_replies This parameter will prevent replies from appearing in the returned timeline. Using exclude_replies with the count parameter will mean you will receive up-to count tweets - this is because the count parameter retrieves that many tweets before filtering out retweets and replies.
+ # @option options [Boolean, String, Integer] :contributor_details Specifies that the contributors element should be enhanced to include the screen_name of the contributor.
+ # @option options [Boolean, String, Integer] :include_entities Specifies that each tweet should include an 'entities' node including metadata about the tweet such as: user_mentions, urls, and hashtags.
# @example Return the 20 most recent retweets posted by users followed by the authenticating user
# Twitter.retweeted_to_me
def retweeted_to_me(options={})
- collection_from_response(Twitter::Tweet, :get, "/1.1/statuses/retweeted_to_me.json", options)
+ options[:include_rts] = true
+ count = options[:count] || DEFAULT_TWEETS_PER_REQUEST
+ collect_with_count(count) do |count_options|
+ select_retweets(home_timeline(options.merge(count_options)))
+ end
end
# Returns the 20 most recent tweets of the authenticated user that have been retweeted by others
#
- # @see https://dev.twitter.com/docs/api/1.1/get/statuses/retweets_of_me
+ # @see https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline
+ # @note This method can only return up to 3,200 Tweets.
# @rate_limited Yes
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
@@ -1798,16 +1806,22 @@ def retweeted_to_me(options={})
# @option options [Integer] :max_id Returns results with an ID less than (that is, older than) or equal to the specified ID.
# @option options [Integer] :count Specifies the number of records to retrieve. Must be less than or equal to 200.
# @option options [Boolean, String, Integer] :trim_user Each tweet returned in a timeline will include a user object with only the author's numerical ID when set to true, 't' or 1.
+ # @option options [Boolean, String, Integer] :exclude_replies This parameter will prevent replies from appearing in the returned timeline. Using exclude_replies with the count parameter will mean you will receive up-to count tweets - this is because the count parameter retrieves that many tweets before filtering out retweets and replies.
+ # @option options [Boolean, String, Integer] :contributor_details Specifies that the contributors element should be enhanced to include the screen_name of the contributor.
# @example Return the 20 most recent tweets of the authenticated user that have been retweeted by others
# Twitter.retweets_of_me
def retweets_of_me(options={})
- collection_from_response(Twitter::Tweet, :get, "/1.1/statuses/retweets_of_me.json", options)
+ options[:include_rts] = false
+ count = options[:count] || DEFAULT_TWEETS_PER_REQUEST
+ collect_with_count(count) do |count_options|
+ user_timeline(options.merge(count_options)).select{|tweet| tweet.retweet_count.to_i > 0}
+ end
end
# Returns the 20 most recent Tweets posted by the specified user
#
# @see https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline
- # @note This method can only return up to 3200 Tweets.
+ # @note This method can only return up to 3,200 Tweets.
# @rate_limited Yes
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
@@ -1820,9 +1834,8 @@ def retweets_of_me(options={})
# @option options [Integer] :count Specifies the number of records to retrieve. Must be less than or equal to 200.
# @option options [Boolean, String, Integer] :trim_user Each tweet returned in a timeline will include a user object with only the author's numerical ID when set to true, 't' or 1.
# @option options [Boolean, String, Integer] :exclude_replies This parameter will prevent replies from appearing in the returned timeline. Using exclude_replies with the count parameter will mean you will receive up-to count tweets - this is because the count parameter retrieves that many tweets before filtering out retweets and replies.
+ # @option options [Boolean, String, Integer] :contributor_details Specifies that the contributors element should be enhanced to include the screen_name of the contributor.
# @option options [Boolean, String, Integer] :include_rts Specifies that the timeline should include native retweets in addition to regular tweets. Note: If you're using the trim_user parameter in conjunction with include_rts, the retweets will no longer contain a full user object.
- # @option options [Boolean, String, Integer] :include_entities Specifies that each tweet should include an 'entities' node including metadata about the tweet such as: user_mentions, urls, and hashtags.
- # @option options [Boolean] :contributor_details Specifies that the contributors element should be enhanced to include the screen_name of the contributor.
# @example Return the 20 most recent Tweets posted by @sferik
# Twitter.user_timeline('sferik')
def user_timeline(*args)
@@ -1870,8 +1883,7 @@ def network_timeline(options={})
# Show up to 100 users who retweeted the Tweet
#
- # @see https://dev.twitter.com/docs/api/1.1/get/statuses/:id/retweeted_by
- # @see https://dev.twitter.com/docs/api/1.1/get/statuses/:id/retweeted_by/ids
+ # @see https://dev.twitter.com/docs/api/1.1/get/statuses/retweets/:id
# @rate_limited Yes
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
@@ -1879,16 +1891,15 @@ def network_timeline(options={})
# @param id [Integer] The numerical ID of the desired Tweet.
# @param options [Hash] A customizable set of options.
# @option options [Integer] :count Specifies the number of records to retrieve. Must be less than or equal to 100.
- # @option options [Integer] :page Specifies the page of results to retrieve.
# @option options [Boolean, String, Integer] :trim_user Each tweet returned in a timeline will include a user object with only the author's numerical ID when set to true, 't' or 1.
# @option options [Boolean] :ids_only ('false') Only return user ids instead of full user objects.
# @example Show up to 100 users who retweeted the Tweet with the ID 28561922516
# Twitter.retweeters_of(28561922516)
def retweeters_of(id, options={})
if ids_only = !!options.delete(:ids_only)
- get("/1.1/statuses/#{id}/retweeted_by/ids.json", options)[:body]
+ retweets(id, options).map(&:user).map(&:id)
else
- collection_from_response(Twitter::User, :get, "/1.1/statuses/#{id}/retweeted_by.json", options)
+ retweets(id, options).map(&:user)
end
end
@@ -2154,13 +2165,14 @@ def update_with_media(status, media, options={})
# @option options [String] :exclude Setting this equal to 'hashtags' will remove all hashtags from the trends list.
# @return [Array<Twitter::Trend>]
# @example Return the top 10 trending topics for San Francisco
- # Twitter.local_trends(2487956)
- def local_trends(id=1, options={})
- options.merge!(:id => id)
+ # Twitter.trends(2487956)
+ def trends(id=1, options={})
+ options[:id] = id
response = get("/1.1/trends/place.json", options)
collection_from_array(Twitter::Trend, response[:body].first[:trends])
end
- alias trends local_trends
+ alias local_trends trends
+ alias trends_place trends
# Returns the locations that Twitter has trending topic information for
#
@@ -2169,18 +2181,34 @@ def local_trends(id=1, options={})
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
# @param options [Hash] A customizable set of options.
+ # @return [Array<Twitter::Place>]
+ # @example Return the locations that Twitter has trending topic information for
+ # Twitter.trends_available
+ def trends_available(options={})
+ collection_from_response(Twitter::Place, :get, "/1.1/trends/available.json", options)
+ end
+ alias trend_locations trends_available
+
+ # Returns the locations that Twitter has trending topic information for, closest to a specified location.
+ #
+ # @see https://dev.twitter.com/docs/api/1.1/get/trends/closest
+ # @rate_limited Yes
+ # @authentication_required Requires user context
+ # @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
+ # @param options [Hash] A customizable set of options.
# @option options [Float] :lat If provided with a :long option the available trend locations will be sorted by distance, nearest to furthest, to the co-ordinate pair. The valid ranges for latitude are -90.0 to +90.0 (North is positive) inclusive.
# @option options [Float] :long If provided with a :lat option the available trend locations will be sorted by distance, nearest to furthest, to the co-ordinate pair. The valid ranges for longitude are -180.0 to +180.0 (East is positive) inclusive.
# @return [Array<Twitter::Place>]
# @example Return the locations that Twitter has trending topic information for
- # Twitter.trend_locations
- def trend_locations(options={})
- collection_from_response(Twitter::Place, :get, "/1.1/trends/available.json", options)
+ # Twitter.trends_closest
+ def trends_closest(options={})
+ collection_from_response(Twitter::Place, :get, "/1.1/trends/closest.json", options)
end
# Returns the top 20 trending topics for each hour in a given day
#
- # @see https://dev.twitter.com/docs/api/1.1/get/trends/daily
+ # @deprecated This method has been deprecated without replacement and will stop working on March 5, 2013.
+ # @see https://dev.twitter.com/docs/api/1/get/trends/daily
# @rate_limited Yes
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
@@ -2191,12 +2219,14 @@ def trend_locations(options={})
# @example Return the top 20 trending topics for each hour of October 24, 2010
# Twitter.trends_daily(Date.parse("2010-10-24"))
def trends_daily(date=Date.today, options={})
- trends_periodically("/1.1/trends/daily.json", date, options)
+ warn "#{Kernel.caller.first}: [DEPRECATION] Twitter::API#trends_daily has been deprecated without replacement and will stop working on March 5, 2013."
+ trends_periodically("/1/trends/daily.json", date, options)
end
# Returns the top 30 trending topics for each day in a given week
#
- # @see https://dev.twitter.com/docs/api/1.1/get/trends/weekly
+ # @deprecated This method has been deprecated without replacement and will stop working on March 5, 2013.
+ # @see https://dev.twitter.com/docs/api/1/get/trends/weekly
# @rate_limited Yes
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
@@ -2207,7 +2237,8 @@ def trends_daily(date=Date.today, options={})
# @example Return the top ten topics that are currently trending on Twitter
# Twitter.trends_weekly(Date.parse("2010-10-24"))
def trends_weekly(date=Date.today, options={})
- trends_periodically("/1.1/trends/weekly.json", date, options)
+ warn "#{Kernel.caller.first}: [DEPRECATION] Twitter::API#trends_weekly has been deprecated without replacement and will stop working on March 5, 2013."
+ trends_periodically("/1/trends/weekly.json", date, options)
end
# Returns an array of user objects that the authenticating user is blocking
@@ -2222,7 +2253,8 @@ def trends_weekly(date=Date.today, options={})
# @example Return an array of user objects that the authenticating user is blocking
# Twitter.blocking
def blocking(options={})
- collection_from_response(Twitter::User, :get, "/1.1/blocks/list.json", options)
+ merge_default_cursor!(options)
+ cursor_from_response(:users, Twitter::User, :get, "/1.1/blocks/list.json", options)
end
# Returns an array of numeric user ids the authenticating user is blocking
@@ -2235,13 +2267,13 @@ def blocking(options={})
# @param options [Hash] A customizable set of options.
# @example Return an array of numeric user ids the authenticating user is blocking
# Twitter.blocking_ids
- def blocked_ids(options={})
- get("/1.1/blocks/ids.json", options)[:body]
+ def blocked_ids(*args)
+ ids_from_response(:get, "/1.1/blocks/ids.json", args)
end
# Returns true if the authenticating user is blocking a target user
#
- # @see https://dev.twitter.com/docs/api/1.1/get/blocks/exists
+ # @see https://dev.twitter.com/docs/api/1.1/get/blocks/ids
# @rate_limited Yes
# @authentication_required Requires user context
# @raise [Twitter::Error::Unauthorized] Error raised when supplied user credentials are not valid.
@@ -2252,7 +2284,16 @@ def blocked_ids(options={})
# Twitter.block?('sferik')
# Twitter.block?(7505382) # Same as above
def block?(user, options={})
- exists?(:get, "/1.1/blocks/exists.json", user, options)
+ merge_default_cursor!(options)
+ user_id = case user
+ when Integer
+ user
+ when String
+ user(user).id
+ when Twitter::User
+ user.id
+ end
+ blocked_ids(options).all.map(&:to_i).include?(user_id)
end
# Blocks the users specified by the authenticating user
@@ -2416,7 +2457,11 @@ def user(*args)
# Twitter.user?('sferik')
# Twitter.user?(7505382) # Same as above
def user?(user, options={})
- exists?(:get, "/1.1/users/show.json", user, options)
+ options.merge_user!(user)
+ get("/1.1/users/show.json", options)
+ true
+ rescue Twitter::Error::NotFound
+ false
end
# Returns an array of users that the specified user can contribute to
@@ -2529,10 +2574,37 @@ def following_followers_of(*args)
private
- def retweets(tweets)
+ # @param tweets [Array]
+ # @return [Array]
+ def select_retweets(tweets)
tweets.select(&:retweet?)
end
+ # @param collection [Array]
+ # @param max_id [Integer, NilClass]
+ # @return [Array]
+ def collect_with_max_id(collection=[], max_id=nil, &block)
+ tweets = yield(max_id)
+ return collection if tweets.nil?
+ collection += tweets
+ tweets.empty? ? collection.flatten : collect_with_max_id(collection, tweets.last.id - 1, &block)
+ end
+
+ # @param count [Integer]
+ # @return [Array]
+ def collect_with_count(count, &block)
+ options = {}
+ options[:count] = MAX_TWEETS_PER_REQUEST
+ collect_with_max_id do |max_id|
+ options[:max_id] = max_id unless max_id.nil?
+ if count > 0
+ tweets = yield(options)
+ count -= tweets.length
+ tweets
+ end
+ end.flatten.compact[0...count]
+ end
+
# @param klass [Class]
# @param array [Array]
# @return [Array]
@@ -2675,19 +2747,6 @@ def list_users(request_method, url, args)
cursor_from_response(:users, Twitter::User, request_method, url, options, {}, calling_method)
end
- # @param request_method [Symbol]
- # @param url [String]
- # @param user [Integer, String, Twitter::User] A Twitter user ID, screen name, or object.
- # @param params [Hash]
- # @return [Boolean]
- def exists?(request_method, url, user, params={}, options={})
- params.merge_user!(user)
- send(request_method.to_sym, url, params, options)
- true
- rescue Twitter::Error::NotFound
- false
- end
-
def list_user?(request_method, url, args)
options = args.extract_options!
options.merge_user!(args.pop)
@@ -2730,7 +2789,7 @@ def trends_periodically(url, date, options)
end
def merge_default_cursor!(options)
- options.merge!(:cursor => DEFAULT_CURSOR) unless options[:cursor]
+ options[:cursor] = DEFAULT_CURSOR unless options[:cursor]
end
def screen_name
View
12 lib/twitter/core_ext/hash.rb
@@ -48,22 +48,22 @@ def merge_owner!(user)
#
# @param user[Integer, String, Twitter::User] A Twitter user ID, screen_name, or object.
# @return [Hash]
- def merge_user(user, prefix=nil, suffix=nil)
- self.dup.merge_user!(user, prefix, suffix)
+ def merge_user(user, prefix=nil)
+ self.dup.merge_user!(user, prefix)
end
# Take a user and merge it into the hash with the correct key
#
# @param user[Integer, String, Twitter::User] A Twitter user ID, screen_name, or object.
# @return [Hash]
- def merge_user!(user, prefix=nil, suffix=nil)
+ def merge_user!(user, prefix=nil)
case user
when Integer
- self[[prefix, "user_id", suffix].compact.join("_").to_sym] = user
+ self[[prefix, "user_id"].compact.join("_").to_sym] = user
when String
- self[[prefix, "screen_name", suffix].compact.join("_").to_sym] = user
+ self[[prefix, "screen_name"].compact.join("_").to_sym] = user
when Twitter::User
- self[[prefix, "user_id", suffix].compact.join("_").to_sym] = user.id
+ self[[prefix, "user_id"].compact.join("_").to_sym] = user.id
end
self
end
View
4 lib/twitter/response/parse_json.rb
@@ -9,10 +9,6 @@ def parse(body)
case body
when /\A^\s*$\z/, nil
nil
- when 'true'
- true
- when 'false'
- false
else
MultiJson.load(body, :symbolize_keys => true)
end
View
1  spec/fixtures/false.json
@@ -1 +0,0 @@
-false
View
1  spec/fixtures/following.json
@@ -0,0 +1 @@
+{"relationship":{"target":{"followed_by":true,"id_str":"14100886","following":false,"screen_name":"pengwynn","id":14100886},"source":{"marked_spam":false,"notifications_enabled":false,"followed_by":false,"want_retweets":true,"id_str":"7505382","blocking":false,"all_replies":false,"following":true,"screen_name":"sferik","id":7505382}}}
View
0  spec/fixtures/id_list.json → spec/fixtures/ids_list.json
File renamed without changes
View
0  spec/fixtures/id_list2.json → spec/fixtures/ids_list2.json
File renamed without changes
View
1  spec/fixtures/not_following.json
@@ -0,0 +1 @@
+{"relationship":{"target":{"followed_by":false,"id_str":"14100886","following":true,"screen_name":"sferik","id":7505382},"source":{"marked_spam":false,"notifications_enabled":false,"followed_by":true,"want_retweets":true,"id_str":"7505382","blocking":false,"all_replies":false,"following":false,"screen_name":"pengwynn","id":14100886}}}
View
1  spec/fixtures/relationship.json
@@ -1 +0,0 @@
-{"relationship":{"target":{"followed_by":true,"id_str":"14100886","following":true,"screen_name":"pengwynn","id":14100886},"source":{"marked_spam":false,"notifications_enabled":false,"followed_by":true,"want_retweets":true,"id_str":"7505382","blocking":false,"all_replies":false,"following":true,"screen_name":"sferik","id":7505382}}}
View
2  spec/fixtures/statuses.json
@@ -1 +1 @@
-[{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"contributors":null,"in_reply_to_screen_name":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"in_reply_to_user_id":null,"in_reply_to_status_id":null,"created_at":"Sat Oct 16 17:07:46 +0000 2010","retweeted":false,"id_str":"27558893223","user":{"follow_request_sent":false,"profile_background_color":"000000","description":"Adventures in hunger and foolishness.","verified":false,"favourites_count":729,"notifications":false,"profile_use_background_image":true,"profile_text_color":"333333","listed_count":28,"profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","url":null,"statuses_count":2968,"show_all_inline_media":true,"lang":"en","profile_background_tile":false,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_sidebar_fill_color":"DDEEF6","location":"San Francisco","contributors_enabled":false,"protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","id_str":"7505382","friends_count":88,"profile_sidebar_border_color":"C0DEED","name":"Erik Michaels-Ober","following":false,"screen_name":"sferik","id":7505382,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","utc_offset":-28800,"followers_count":898},"coordinates":null,"id":27558893223,"truncated":false,"text":"Ruby is the best programming language for hiding the ugly bits."},{"place":null,"coordinates":null,"retweet_count":null,"geo":null,"favorited":false,"source":"<a href=\"http://www.echofon.com/\" rel=\"nofollow\">Echofon</a>","in_reply_to_status_id":null,"created_at":"Fri Oct 15 18:26:47 +0000 2010","contributors":null,"in_reply_to_user_id":null,"user":{"friends_count":112,"description":"degradable","follow_request_sent":false,"profile_use_background_image":true,"profile_sidebar_border_color":"C0DEED","verified":false,"profile_background_image_url":"http://a1.twimg.com/profile_background_images/133569392/nature02922-f1.2.jpg","profile_background_color":"C0DEED","url":null,"show_all_inline_media":true,"notifications":false,"profile_background_tile":true,"lang":"en","statuses_count":2915,"geo_enabled":true,"favourites_count":707,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_text_color":"333333","profile_image_url":"http://a0.twimg.com/profile_images/323331048/me_normal.jpg","location":"San Francisco","protected":false,"contributors_enabled":false,"profile_link_color":"0084B4","screen_name":"sferik","name":"Erik Michaels-Ober","listed_count":28,"following":true,"time_zone":"Pacific Time (US & Canada)","followers_count":894,"id":7505382,"utc_offset":-28800,"profile_sidebar_fill_color":"DDEEF6"},"truncated":false,"in_reply_to_screen_name":null,"id":27467028175,"retweeted":false,"text":"There are 1.3 billion people in China; when people say there are 1 billion they are rounding off the entire population of the United States."},{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"in_reply_to_screen_name":null,"in_reply_to_user_id":null,"source":"\u003Ca href=\"http:\/\/twitter.com\/tweetbutton\" rel=\"nofollow\"\u003ETweet Button\u003C\/a\u003E","retweet_count":null,"created_at":"Mon Oct 11 20:57:56 +0000 2010","id_str":"27068258331","retweeted":false,"user":{"statuses_count":2972,"description":"Adventures in hunger and foolishness.","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","contributors_enabled":false,"notifications":false,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","profile_background_color":"000000","url":null,"verified":false,"follow_request_sent":false,"lang":"en","profile_use_background_image":true,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_text_color":"333333","location":"San Francisco","id_str":"7505382","protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","name":"Erik Michaels-Ober","following":false,"followers_count":897,"screen_name":"sferik","id":7505382,"listed_count":28,"profile_background_tile":false,"utc_offset":-28800,"friends_count":89,"profile_sidebar_fill_color":"DDEEF6"},"coordinates":null,"id":27068258331,"truncated":false,"text":"The new Windows Phone campaign is the best advertising from Microsoft since \"Start Me Up\" (1995). Great work by CP+B. http:\/\/t.co\/tIzxopI"},{"in_reply_to_status_id_str":null,"place":{"country_code":"US","place_type":"city","url":"http:\/\/api.twitter.com\/1\/geo\/id\/4552eed9a8b61ff9.json","country":"The United States of America","bounding_box":{"type":"Polygon","coordinates":[[[-123.632497,38.29571],[-122.833844,38.29571],[-122.833844,38.808369],[-123.632497,38.808369]]]},"attributes":{},"full_name":"Russian River-Coastal, CA","name":"Russian River-Coastal","id":"4552eed9a8b61ff9"},"geo":{"type":"Point","coordinates":[38.524535,-123.088368]},"favorited":false,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"in_reply_to_screen_name":null,"in_reply_to_user_id":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"created_at":"Sun Oct 10 18:26:22 +0000 2010","id_str":"26959930192","retweeted":false,"user":{"statuses_count":2972,"description":"Adventures in hunger and foolishness.","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","contributors_enabled":false,"notifications":false,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","profile_background_color":"000000","url":null,"verified":false,"follow_request_sent":false,"lang":"en","profile_use_background_image":true,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_text_color":"333333","location":"San Francisco","id_str":"7505382","protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","name":"Erik Michaels-Ober","following":false,"followers_count":897,"screen_name":"sferik","id":7505382,"listed_count":28,"profile_background_tile":false,"utc_offset":-28800,"friends_count":89,"profile_sidebar_fill_color":"DDEEF6"},"coordinates":{"type":"Point","coordinates":[-123.088368,38.524535]},"id":26959930192,"truncated":false,"text":"Fear not to sow seeds because of the birds. http:\/\/twitpic.com\/2wg621"},{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"in_reply_to_screen_name":null,"in_reply_to_user_id":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"created_at":"Wed Oct 06 00:03:47 +0000 2010","id_str":"26503221778","retweeted":false,"user":{"statuses_count":2972,"description":"Adventures in hunger and foolishness.","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","contributors_enabled":false,"notifications":false,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","profile_background_color":"000000","url":null,"verified":false,"follow_request_sent":false,"lang":"en","profile_use_background_image":true,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_text_color":"333333","location":"San Francisco","id_str":"7505382","protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","name":"Erik Michaels-Ober","following":false,"followers_count":897,"screen_name":"sferik","id":7505382,"listed_count":28,"profile_background_tile":false,"utc_offset":-28800,"friends_count":89,"profile_sidebar_fill_color":"DDEEF6"},"coordinates":null,"id":26503221778,"truncated":false,"text":"Speaking of things that are maddening: the interview with the Wall Street guys on the most recent This American Life http:\/\/bit.ly\/af9pSD"},{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"contributors":null,"in_reply_to_screen_name":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"in_reply_to_user_id":null,"in_reply_to_status_id":null,"created_at":"Wed Sep 29 00:49:44 +0000 2010","retweeted":false,"id_str":"25836892941","user":{"follow_request_sent":false,"profile_background_color":"000000","description":"Adventures in hunger and foolishness.","verified":false,"favourites_count":729,"notifications":false,"profile_use_background_image":true,"profile_text_color":"333333","listed_count":28,"profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","url":null,"statuses_count":2968,"show_all_inline_media":true,"lang":"en","profile_background_tile":false,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_sidebar_fill_color":"DDEEF6","location":"San Francisco","contributors_enabled":false,"protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","id_str":"7505382","friends_count":88,"profile_sidebar_border_color":"C0DEED","name":"Erik Michaels-Ober","following":false,"screen_name":"sferik","id":7505382,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","utc_offset":-28800,"followers_count":898},"coordinates":null,"id":25836892941,"truncated":false,"text":"Holy cow! RailsAdmin is up to 200 watchers (from 100 yesterday). http:\/\/github.com\/sferik\/rails_admin"},{"place":null,"retweet_count":null,"geo":null,"retweeted":false,"in_reply_to_status_id":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","truncated":false,"in_reply_to_status_id_str":null,"created_at":"Mon Sep 27 23:35:56 +0000 2010","in_reply_to_user_id":null,"favorited":false,"in_reply_to_user_id_str":null,"user":{"time_zone":"Pacific Time (US & Canada)","description":"Adventures in hunger and foolishness.","profile_sidebar_fill_color":"DDEEF6","followers_count":898,"listed_count":29,"notifications":false,"friends_count":88,"statuses_count":2962,"profile_use_background_image":true,"profile_sidebar_border_color":"C0DEED","show_all_inline_media":true,"favourites_count":727,"url":null,"contributors_enabled":false,"profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","lang":"en","geo_enabled":true,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_background_color":"000000","location":"San Francisco","profile_background_tile":false,"protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","verified":false,"profile_text_color":"333333","name":"Erik Michaels-Ober","follow_request_sent":false,"following":false,"screen_name":"sferik","id":7505382,"id_str":"7505382","utc_offset":-28800,"profile_link_color":"0084B4"},"contributors":null,"coordinates":null,"in_reply_to_screen_name":null,"id":25732982065,"id_str":"25732982065","text":"Kind of cool that Facebook acts as a mirror for open-source projects that they use or like http:\/\/mirror.facebook.net\/"},{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"in_reply_to_screen_name":null,"in_reply_to_user_id":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"created_at":"Mon Sep 27 14:55:28 +0000 2010","id_str":"25693598875","retweeted":false,"user":{"statuses_count":2972,"description":"Adventures in hunger and foolishness.","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","contributors_enabled":false,"notifications":false,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","profile_background_color":"000000","url":null,"verified":false,"follow_request_sent":false,"lang":"en","profile_use_background_image":true,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_text_color":"333333","location":"San Francisco","id_str":"7505382","protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","name":"Erik Michaels-Ober","following":false,"followers_count":897,"screen_name":"sferik","id":7505382,"listed_count":28,"profile_background_tile":false,"utc_offset":-28800,"friends_count":89,"profile_sidebar_fill_color":"DDEEF6"},"coordinates":null,"id":25693598875,"truncated":false,"text":"RailsAdmin already has 100 watchers, 12 forks, and 6 contributors in less than 2 months. Let's keep the momentum going! http:\/\/bit.ly\/cCMMqD"},{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"contributors":null,"in_reply_to_screen_name":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"in_reply_to_user_id":null,"in_reply_to_status_id":null,"created_at":"Tue Sep 14 03:25:46 +0000 2010","retweeted":false,"id_str":"24443017910","user":{"profile_background_color":"000000","description":"Adventures in hunger and foolishness.","verified":false,"follow_request_sent":false,"notifications":false,"profile_use_background_image":true,"profile_text_color":"333333","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","url":null,"listed_count":28,"lang":"en","profile_background_tile":false,"created_at":"Mon Jul 16 12:59:01 +0000 2007","friends_count":88,"profile_sidebar_fill_color":"DDEEF6","location":"San Francisco","statuses_count":2968,"protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","id_str":"7505382","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","name":"Erik Michaels-Ober","contributors_enabled":false,"following":false,"screen_name":"sferik","id":7505382,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","utc_offset":-28800,"followers_count":898},"coordinates":null,"id":24443017910,"truncated":false,"text":"This week's This American Life is amazing. @JoeLipari is an American hero. http:\/\/bit.ly\/d9RbnB"},{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"contributors":null,"in_reply_to_screen_name":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"in_reply_to_user_id":null,"in_reply_to_status_id":null,"created_at":"Sat Sep 11 02:17:29 +0000 2010","retweeted":false,"id_str":"24158227743","user":{"profile_background_color":"000000","description":"Adventures in hunger and foolishness.","verified":false,"follow_request_sent":false,"notifications":false,"profile_use_background_image":true,"profile_text_color":"333333","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","url":null,"listed_count":28,"lang":"en","profile_background_tile":false,"created_at":"Mon Jul 16 12:59:01 +0000 2007","friends_count":88,"profile_sidebar_fill_color":"DDEEF6","location":"San Francisco","statuses_count":2968,"protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","id_str":"7505382","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","name":"Erik Michaels-Ober","contributors_enabled":false,"following":false,"screen_name":"sferik","id":7505382,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","utc_offset":-28800,"followers_count":898},"coordinates":null,"id":24158227743,"truncated":false,"text":"RT @polyseme: OH: shofars should be called jewvuzelas."},{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"in_reply_to_screen_name":null,"in_reply_to_user_id":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"created_at":"Fri Sep 10 18:07:47 +0000 2010","id_str":"24126395365","retweeted":false,"user":{"statuses_count":2972,"description":"Adventures in hunger and foolishness.","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","contributors_enabled":false,"notifications":false,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","profile_background_color":"000000","url":null,"verified":false,"follow_request_sent":false,"lang":"en","profile_use_background_image":true,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_text_color":"333333","location":"San Francisco","id_str":"7505382","protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","name":"Erik Michaels-Ober","following":false,"followers_count":897,"screen_name":"sferik","id":7505382,"listed_count":28,"profile_background_tile":false,"utc_offset":-28800,"friends_count":89,"profile_sidebar_fill_color":"DDEEF6"},"coordinates":null,"id":24126395365,"truncated":false,"text":"Spent this morning fixing broken windows in RailsAdmin http:\/\/github.com\/sferik\/rails_admin\/compare\/ab6c598...0e3770f"},{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"in_reply_to_screen_name":null,"in_reply_to_user_id":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"created_at":"Fri Sep 10 18:02:34 +0000 2010","id_str":"24126047148","retweeted":false,"user":{"statuses_count":2972,"description":"Adventures in hunger and foolishness.","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","contributors_enabled":false,"notifications":false,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","profile_background_color":"000000","url":null,"verified":false,"follow_request_sent":false,"lang":"en","profile_use_background_image":true,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_text_color":"333333","location":"San Francisco","id_str":"7505382","protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","name":"Erik Michaels-Ober","following":false,"followers_count":897,"screen_name":"sferik","id":7505382,"listed_count":28,"profile_background_tile":false,"utc_offset":-28800,"friends_count":89,"profile_sidebar_fill_color":"DDEEF6"},"coordinates":null,"id":24126047148,"truncated":false,"text":"I'm a big believer that the broken windows theory applies to software development http:\/\/en.wikipedia.org\/wiki\/Broken_windows_theory"},{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"in_reply_to_screen_name":null,"in_reply_to_user_id":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"created_at":"Thu Sep 09 17:12:21 +0000 2010","id_str":"24028079777","retweeted":false,"user":{"statuses_count":2972,"description":"Adventures in hunger and foolishness.","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","contributors_enabled":false,"notifications":false,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","profile_background_color":"000000","url":null,"verified":false,"follow_request_sent":false,"lang":"en","profile_use_background_image":true,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_text_color":"333333","location":"San Francisco","id_str":"7505382","protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","name":"Erik Michaels-Ober","following":false,"followers_count":897,"screen_name":"sferik","id":7505382,"listed_count":28,"profile_background_tile":false,"utc_offset":-28800,"friends_count":89,"profile_sidebar_fill_color":"DDEEF6"},"coordinates":null,"id":24028079777,"truncated":false,"text":"I hope you idiots are happy with your piece of shit Android phones. http:\/\/www.apple.com\/pr\/library\/2010\/09\/09statement.html"},{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"in_reply_to_screen_name":null,"in_reply_to_user_id":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"created_at":"Wed Sep 01 17:55:15 +0000 2010","id_str":"22728299854","retweeted":false,"user":{"statuses_count":2972,"description":"Adventures in hunger and foolishness.","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","contributors_enabled":false,"notifications":false,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","profile_background_color":"000000","url":null,"verified":false,"follow_request_sent":false,"lang":"en","profile_use_background_image":true,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_text_color":"333333","location":"San Francisco","id_str":"7505382","protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","name":"Erik Michaels-Ober","following":false,"followers_count":897,"screen_name":"sferik","id":7505382,"listed_count":28,"profile_background_tile":false,"utc_offset":-28800,"friends_count":89,"profile_sidebar_fill_color":"DDEEF6"},"coordinates":null,"id":22728299854,"truncated":false,"text":"Ping: kills MySpace dead."},{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"in_reply_to_screen_name":null,"in_reply_to_user_id":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"created_at":"Wed Sep 01 17:43:30 +0000 2010","id_str":"22727444431","retweeted":false,"user":{"statuses_count":2972,"description":"Adventures in hunger and foolishness.","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","contributors_enabled":false,"notifications":false,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","profile_background_color":"000000","url":null,"verified":false,"follow_request_sent":false,"lang":"en","profile_use_background_image":true,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_text_color":"333333","location":"San Francisco","id_str":"7505382","protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","name":"Erik Michaels-Ober","following":false,"followers_count":897,"screen_name":"sferik","id":7505382,"listed_count":28,"profile_background_tile":false,"utc_offset":-28800,"friends_count":89,"profile_sidebar_fill_color":"DDEEF6"},"coordinates":null,"id":22727444431,"truncated":false,"text":"Crazy that iTunes Ping didn't leak a drop."},{"in_reply_to_status_id_str":null,"place":{"country_code":"US","place_type":"neighborhood","url":"http:\/\/api.twitter.com\/1\/geo\/id\/5c92ab5379de3839.json","country":"The United States of America","bounding_box":{"type":"Polygon","coordinates":[[[-122.40348192,37.77752898],[-122.387436,37.77752898],[-122.387436,37.79448597],[-122.40348192,37.79448597]]]},"attributes":{},"full_name":"South Beach, San Francisco","name":"South Beach","id":"5c92ab5379de3839"},"geo":{"type":"Point","coordinates":[37.782365,-122.392431]},"favorited":false,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"in_reply_to_screen_name":null,"in_reply_to_user_id":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"created_at":"Wed Sep 01 05:53:01 +0000 2010","id_str":"22683247815","retweeted":false,"user":{"statuses_count":2972,"description":"Adventures in hunger and foolishness.","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","contributors_enabled":false,"notifications":false,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","profile_background_color":"000000","url":null,"verified":false,"follow_request_sent":false,"lang":"en","profile_use_background_image":true,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_text_color":"333333","location":"San Francisco","id_str":"7505382","protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","name":"Erik Michaels-Ober","following":false,"followers_count":897,"screen_name":"sferik","id":7505382,"listed_count":28,"profile_background_tile":false,"utc_offset":-28800,"friends_count":89,"profile_sidebar_fill_color":"DDEEF6"},"coordinates":{"type":"Point","coordinates":[-122.392431,37.782365]},"id":22683247815,"truncated":false,"text":"The plot thickens http:\/\/twitpic.com\/2k5lt2"},{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"in_reply_to_screen_name":null,"in_reply_to_user_id":null,"source":"\u003Ca href=\"http:\/\/twitter.com\/tweetbutton\" rel=\"nofollow\"\u003ETweet Button\u003C\/a\u003E","retweet_count":null,"created_at":"Fri Aug 27 23:01:19 +0000 2010","id_str":"22305399947","retweeted":false,"user":{"statuses_count":2972,"description":"Adventures in hunger and foolishness.","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","contributors_enabled":false,"notifications":false,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","profile_background_color":"000000","url":null,"verified":false,"follow_request_sent":false,"lang":"en","profile_use_background_image":true,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_text_color":"333333","location":"San Francisco","id_str":"7505382","protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","name":"Erik Michaels-Ober","following":false,"followers_count":897,"screen_name":"sferik","id":7505382,"listed_count":28,"profile_background_tile":false,"utc_offset":-28800,"friends_count":89,"profile_sidebar_fill_color":"DDEEF6"},"coordinates":null,"id":22305399947,"truncated":false,"text":"140 Proof Provides A Piece Of The Twitter Advertising\u00a0Puzzle http:\/\/t.co\/R2cUSDe via @techcrunch"},{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"in_reply_to_screen_name":null,"in_reply_to_user_id":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"created_at":"Fri Aug 27 22:33:42 +0000 2010","id_str":"22303907694","retweeted":false,"user":{"statuses_count":2972,"description":"Adventures in hunger and foolishness.","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","contributors_enabled":false,"notifications":false,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","profile_background_color":"000000","url":null,"verified":false,"follow_request_sent":false,"lang":"en","profile_use_background_image":true,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_text_color":"333333","location":"San Francisco","id_str":"7505382","protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","name":"Erik Michaels-Ober","following":false,"followers_count":897,"screen_name":"sferik","id":7505382,"listed_count":28,"profile_background_tile":false,"utc_offset":-28800,"friends_count":89,"profile_sidebar_fill_color":"DDEEF6"},"coordinates":null,"id":22303907694,"truncated":false,"text":"Try as you may http:\/\/www.thedoghousediaries.com\/?p=1940"},{"in_reply_to_status_id_str":null,"place":null,"geo":null,"favorited":false,"in_reply_to_user_id_str":null,"in_reply_to_status_id":null,"contributors":null,"in_reply_to_screen_name":null,"in_reply_to_user_id":null,"source":"\u003Ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003EEchofon\u003C\/a\u003E","retweet_count":null,"created_at":"Thu Aug 19 01:38:01 +0000 2010","id_str":"21538122473","retweeted":false,"user":{"statuses_count":2972,"description":"Adventures in hunger and foolishness.","show_all_inline_media":true,"favourites_count":729,"profile_sidebar_border_color":"C0DEED","contributors_enabled":false,"notifications":false,"geo_enabled":true,"time_zone":"Pacific Time (US & Canada)","profile_background_color":"000000","url":null,"verified":false,"follow_request_sent":false,"lang":"en","profile_use_background_image":true,"created_at":"Mon Jul 16 12:59:01 +0000 2007","profile_text_color":"333333","location":"San Francisco","id_str":"7505382","protected":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/323331048\/me_normal.jpg","profile_background_image_url":"http:\/\/a3.twimg.com\/profile_background_images\/162641967\/we_concept_bg2.png","profile_link_color":"0084B4","name":"Erik Michaels-Ober","following":false,"followers_count":897,"screen_name":"sferik","id":7505382,"listed_count":28,"profile_background_tile":false,"utc_offset":-28800,"friends_count":89,"profile_sidebar_fill_color":"DDEEF6"},"coordinates":null,"id":21538122473,"truncated":false,"text":"I know @SarahPalinUSA has a right to use Twitter, but should she?"}]
+[{"created_at":"Fri Sep 07 16:35:24 +0000 2012","id":244111636544225280,"id_str":"244111636544225280","text":"Happy Birthday @imdane. Watch out for those @rally pranksters!","source":"\u003ca href=\"http:\/\/twitter.com\/download\/iphone\" rel=\"nofollow\"\u003eTwitter for iPhone\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":5819322,"id_str":"5819322","name":"Maggie Utgoff","screen_name":"mutgoff","location":"san francisco","description":"I live every week like it's Shark Week. ","url":"http:\/\/www.mutgoff.com","entities":{"url":{"urls":[{"url":"http:\/\/www.mutgoff.com","expanded_url":null,"indices":[0,22]}]},"description":{"urls":[]}},"protected":false,"followers_count":263063,"friends_count":708,"listed_count":534,"created_at":"Mon May 07 01:02:52 +0000 2007","favourites_count":444,"utc_offset":-28800,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":4604,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"FFFFFF","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/344662358\/x88fe902ff835983434794eb1f9d7370.jpg","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/344662358\/x88fe902ff835983434794eb1f9d7370.jpg","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1199277090\/Screen_shot_2010-12-26_at_11.31.51_AM_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1199277090\/Screen_shot_2010-12-26_at_11.31.51_AM_normal.png","profile_link_color":"9DDD95","profile_sidebar_border_color":"A0EEF5","profile_sidebar_fill_color":"1A3F57","profile_text_color":"72B9BF","profile_use_background_image":true,"show_all_inline_media":true,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":{"type":"Point","coordinates":[43.46481998,-73.64247884]},"coordinates":{"type":"Point","coordinates":[-73.64247884,43.46481998]},"place":{"id":"003cd76c24b9fa3b","url":"https:\/\/api.twitter.com\/1.1\/geo\/id\/003cd76c24b9fa3b.json","place_type":"city","name":"Bolton","full_name":"Bolton, NY","country_code":"US","country":"United States","bounding_box":{"type":"Polygon","coordinates":[[[-73.750813,43.442073],[-73.525347,43.442073],[-73.525347,43.678377],[-73.750813,43.678377]]]},"attributes":{}},"contributors":null,"retweet_count":0,"entities":{"hashtags":[],"urls":[],"user_mentions":[{"screen_name":"imdane","name":"Dane Hurtubise","id":14076314,"id_str":"14076314","indices":[15,22]},{"screen_name":"rally","name":"Rally","id":16364838,"id_str":"16364838","indices":[44,50]}]},"favorited":false,"retweeted":false},{"created_at":"Fri Sep 07 16:33:36 +0000 2012","id":244111183165157376,"id_str":"244111183165157376","text":"If you like good real-life stories, check out @NarrativelyNY\u2019s just-launched site http:\/\/t.co\/wiUL07jE (and also visit http:\/\/t.co\/ZoyQxqWA)","source":"\u003ca href=\"http:\/\/tapbots.com\" rel=\"nofollow\"\u003eTweetbot for Mac\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":14163141,"id_str":"14163141","name":"David Friedman","screen_name":"ironicsans","location":"New York","description":"Photographer. Idea blogger. Occasional historian.","url":"http:\/\/www.davidfriedman.info","entities":{"url":{"urls":[{"url":"http:\/\/www.davidfriedman.info","expanded_url":null,"indices":[0,29]}]},"description":{"urls":[]}},"protected":false,"followers_count":4131,"friends_count":1270,"listed_count":220,"created_at":"Mon Mar 17 13:47:33 +0000 2008","favourites_count":1377,"utc_offset":-18000,"time_zone":"Eastern Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":4753,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"AAB4B5","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/66248418\/Untitled-1.gif","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/66248418\/Untitled-1.gif","profile_background_tile":true,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/427291735\/n645611374_892426_9102_normal.jpg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/427291735\/n645611374_892426_9102_normal.jpg","profile_link_color":"0084B4","profile_sidebar_border_color":"BDDCAD","profile_sidebar_fill_color":"DDFFCC","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":true,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/wiUL07jE","expanded_url":"http:\/\/narrative.ly","display_url":"narrative.ly","indices":[82,102]},{"url":"http:\/\/t.co\/ZoyQxqWA","expanded_url":"http:\/\/www.kickstarter.com\/projects\/narratively\/narratively","display_url":"kickstarter.com\/projects\/narra\u2026","indices":[119,139]}],"user_mentions":[{"screen_name":"NarrativelyNY","name":"Narratively","id":576457087,"id_str":"576457087","indices":[46,60]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 16:30:14 +0000 2012","id":244110336414859264,"id_str":"244110336414859264","text":"Something else to vote for: \"New Rails workshops to bring more women into the Boston software scene\" http:\/\/t.co\/eNBuckHc \/cc @bostonrb","source":"\u003ca href=\"http:\/\/itunes.apple.com\/us\/app\/twitter\/id409789998?mt=12\" rel=\"nofollow\"\u003eTwitter for Mac\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":43234200,"id_str":"43234200","name":"Pat Shaughnessy","screen_name":"pat_shaughnessy","location":"Boston","description":"Blogger, Rubyist, Writing a new eBook: http:\/\/patshaughnessy.net\/ruby-under-a-microscope","url":"http:\/\/patshaughnessy.net","entities":{"url":{"urls":[{"url":"http:\/\/patshaughnessy.net","expanded_url":null,"indices":[0,25]}]},"description":{"urls":[]}},"protected":false,"followers_count":734,"friends_count":362,"listed_count":38,"created_at":"Fri May 29 00:55:48 +0000 2009","favourites_count":35,"utc_offset":-18000,"time_zone":"Eastern Time (US & Canada)","geo_enabled":false,"verified":false,"statuses_count":1620,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1950093297\/pat2_normal.jpg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1950093297\/pat2_normal.jpg","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":false,"default_profile":true,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/eNBuckHc","expanded_url":"http:\/\/news.ycombinator.com\/item?id=4489199","display_url":"news.ycombinator.com\/item?id=4489199","indices":[101,121]}],"user_mentions":[{"screen_name":"bostonrb","name":"Boston Ruby Group","id":21431343,"id_str":"21431343","indices":[126,135]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 16:28:05 +0000 2012","id":244109797308379136,"id_str":"244109797308379136","text":"Pushing the button to launch the site. http:\/\/t.co\/qLoEn5jG","source":"\u003ca href=\"http:\/\/instagr.am\" rel=\"nofollow\"\u003eInstagram\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":1882641,"id_str":"1882641","name":"Caleb Elston","screen_name":"calebelston","location":"San Francisco","description":"Co-founder & CEO of Yobongo. Dubious of people who claim to be experts. Formerly VP Products at Justin.tv. Advisor to Simpler.","url":"http:\/\/www.calebelston.com","entities":{"url":{"urls":[{"url":"http:\/\/www.calebelston.com","expanded_url":null,"indices":[0,26]}]},"description":{"urls":[]}},"protected":false,"followers_count":1960,"friends_count":151,"listed_count":136,"created_at":"Thu Mar 22 14:34:22 +0000 2007","favourites_count":815,"utc_offset":-28800,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":7068,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"666666","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/322151965\/ngb.gif","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/322151965\/ngb.gif","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/2584558450\/elyaf9epw0kcnh9gxglp_normal.jpeg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/2584558450\/elyaf9epw0kcnh9gxglp_normal.jpeg","profile_link_color":"0099CC","profile_sidebar_border_color":"E3E3E3","profile_sidebar_fill_color":"FFFFFF","profile_text_color":"292E38","profile_use_background_image":false,"show_all_inline_media":true,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/qLoEn5jG","expanded_url":"http:\/\/instagr.am\/p\/PR7YFvRhiO\/","display_url":"instagr.am\/p\/PR7YFvRhiO\/","indices":[39,59]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 16:23:50 +0000 2012","id":244108728834592770,"id_str":"244108728834592770","text":"RT @olivercameron: Mosaic looks cool: http:\/\/t.co\/A8013C9k","source":"web","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":1882641,"id_str":"1882641","name":"Caleb Elston","screen_name":"calebelston","location":"San Francisco","description":"Co-founder & CEO of Yobongo. Dubious of people who claim to be experts. Formerly VP Products at Justin.tv. Advisor to Simpler.","url":"http:\/\/www.calebelston.com","entities":{"url":{"urls":[{"url":"http:\/\/www.calebelston.com","expanded_url":null,"indices":[0,26]}]},"description":{"urls":[]}},"protected":false,"followers_count":1960,"friends_count":151,"listed_count":136,"created_at":"Thu Mar 22 14:34:22 +0000 2007","favourites_count":815,"utc_offset":-28800,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":7068,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"666666","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/322151965\/ngb.gif","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/322151965\/ngb.gif","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/2584558450\/elyaf9epw0kcnh9gxglp_normal.jpeg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/2584558450\/elyaf9epw0kcnh9gxglp_normal.jpeg","profile_link_color":"0099CC","profile_sidebar_border_color":"E3E3E3","profile_sidebar_fill_color":"FFFFFF","profile_text_color":"292E38","profile_use_background_image":false,"show_all_inline_media":true,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"created_at":"Fri Sep 07 16:12:47 +0000 2012","id":244105944508796931,"id_str":"244105944508796931","text":"Mosaic looks cool: http:\/\/t.co\/A8013C9k","source":"\u003ca href=\"http:\/\/itunes.apple.com\/us\/app\/twitter\/id409789998?mt=12\" rel=\"nofollow\"\u003eTwitter for Mac\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":13634322,"id_str":"13634322","name":"Oliver Cameron","screen_name":"olivercameron","location":"Palo Alto, CA","description":"Co-founder of @everyme.","url":"http:\/\/everyme.com","entities":{"url":{"urls":[{"url":"http:\/\/everyme.com","expanded_url":null,"indices":[0,18]}]},"description":{"urls":[]}},"protected":false,"followers_count":1365,"friends_count":218,"listed_count":57,"created_at":"Mon Feb 18 18:08:32 +0000 2008","favourites_count":8,"utc_offset":0,"time_zone":"London","geo_enabled":false,"verified":false,"statuses_count":3346,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"FFFFFF","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/5435833\/pat_20060420022220.gif","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/5435833\/pat_20060420022220.gif","profile_background_tile":true,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1237999642\/Oliver_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1237999642\/Oliver_normal.png","profile_link_color":"454545","profile_sidebar_border_color":"FFFFFF","profile_sidebar_fill_color":"FFFFFF","profile_text_color":"000000","profile_use_background_image":false,"show_all_inline_media":true,"default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":1,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/A8013C9k","expanded_url":"http:\/\/heymosaic.com\/i\/1Z8ssK","display_url":"heymosaic.com\/i\/1Z8ssK","indices":[19,39]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false},"retweet_count":1,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/A8013C9k","expanded_url":"http:\/\/heymosaic.com\/i\/1Z8ssK","display_url":"heymosaic.com\/i\/1Z8ssK","indices":[38,58]}],"user_mentions":[{"screen_name":"olivercameron","name":"Oliver Cameron","id":13634322,"id_str":"13634322","indices":[3,17]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 16:20:31 +0000 2012","id":244107890632294400,"id_str":"244107890632294400","text":"The Weatherman is Not a Moron: http:\/\/t.co\/ZwL5Gnq5. An excerpt from my book, THE SIGNAL AND THE NOISE (http:\/\/t.co\/fNXj8vCE)","source":"\u003ca href=\"http:\/\/www.tweetdeck.com\" rel=\"nofollow\"\u003eTweetDeck\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":16017475,"id_str":"16017475","name":"Nate Silver","screen_name":"fivethirtyeight","location":"New York","description":"FiveThirtyEight blogger (http:\/\/nyti.ms\/Qp8cqb). Author, The Signal and the Noise (http:\/\/amzn.to\/QdyFYV). Sports\/politics\/food geek.","url":"http:\/\/amzn.to\/QdyFYV","entities":{"url":{"urls":[{"url":"http:\/\/amzn.to\/QdyFYV","expanded_url":null,"indices":[0,21]}]},"description":{"urls":[]}},"protected":false,"followers_count":183238,"friends_count":475,"listed_count":8160,"created_at":"Wed Aug 27 20:56:45 +0000 2008","favourites_count":6,"utc_offset":-18000,"time_zone":"Eastern Time (US & Canada)","geo_enabled":false,"verified":true,"statuses_count":6786,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1110592135\/fivethirtyeight73_twitter_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1110592135\/fivethirtyeight73_twitter_normal.png","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":false,"default_profile":true,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":19,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/ZwL5Gnq5","expanded_url":"http:\/\/nyti.ms\/OW7n5p","display_url":"nyti.ms\/OW7n5p","indices":[31,51]},{"url":"http:\/\/t.co\/fNXj8vCE","expanded_url":"http:\/\/amzn.to\/Qg2SEu","display_url":"amzn.to\/Qg2SEu","indices":[104,124]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 16:20:15 +0000 2012","id":244107823733174272,"id_str":"244107823733174272","text":"RT @randomhacks: Going to Code Across Austin II: Y'all Come Hack Now, Sat, Sep 8 http:\/\/t.co\/Sk5BM7U3 We'll see y'all there! #rhok @cod ...","source":"web","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":64482503,"id_str":"64482503","name":"Code for America","screen_name":"codeforamerica","location":"San Francisco, California","description":"Code for America helps governments work better for everyone with the people and the power of the web.","url":"http:\/\/www.codeforamerica.org","entities":{"url":{"urls":[{"url":"http:\/\/www.codeforamerica.org","expanded_url":null,"indices":[0,29]}]},"description":{"urls":[]}},"protected":false,"followers_count":11824,"friends_count":783,"listed_count":981,"created_at":"Mon Aug 10 18:59:29 +0000 2009","favourites_count":20,"utc_offset":-28800,"time_zone":"Pacific Time (US & Canada)","geo_enabled":false,"verified":false,"statuses_count":3611,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"EBEBEB","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme7\/bg.gif","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme7\/bg.gif","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1118630094\/logosquare_bigger_normal.jpg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1118630094\/logosquare_bigger_normal.jpg","profile_link_color":"990000","profile_sidebar_border_color":"DFDFDF","profile_sidebar_fill_color":"F3F3F3","profile_text_color":"333333","profile_use_background_image":false,"show_all_inline_media":false,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"created_at":"Fri Sep 07 16:11:02 +0000 2012","id":244105505390350336,"id_str":"244105505390350336","text":"Going to Code Across Austin II: Y'all Come Hack Now, Sat, Sep 8 http:\/\/t.co\/Sk5BM7U3 We'll see y'all there! #rhok @codeforamerica @TheaClay","source":"\u003ca href=\"http:\/\/twitter.com\/tweetbutton\" rel=\"nofollow\"\u003eTweet Button\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":75361247,"id_str":"75361247","name":"Random Hacks","screen_name":"randomhacks","location":"USA","description":"Official Twitter account for Random Hacks of Kindness.","url":"http:\/\/www.rhok.org","entities":{"url":{"urls":[{"url":"http:\/\/www.rhok.org","expanded_url":null,"indices":[0,19]}]},"description":{"urls":[]}},"protected":false,"followers_count":3917,"friends_count":202,"listed_count":209,"created_at":"Fri Sep 18 19:22:26 +0000 2009","favourites_count":1,"utc_offset":-28800,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":1173,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/102109549\/rhok_social_media_wallpaper.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/102109549\/rhok_social_media_wallpaper.png","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/905274924\/rhok_social_media_logo_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/905274924\/rhok_social_media_logo_normal.png","profile_link_color":"2087E7","profile_sidebar_border_color":"2087E7","profile_sidebar_fill_color":"E8E7E7","profile_text_color":"030303","profile_use_background_image":true,"show_all_inline_media":false,"default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":2,"entities":{"hashtags":[{"text":"rhok","indices":[109,114]}],"urls":[{"url":"http:\/\/t.co\/Sk5BM7U3","expanded_url":"http:\/\/zvents.com\/e\/IhP3T\/7o","display_url":"zvents.com\/e\/IhP3T\/7o","indices":[64,84]}],"user_mentions":[{"screen_name":"codeforamerica","name":"Code for America","id":64482503,"id_str":"64482503","indices":[115,130]},{"screen_name":"TheaClay","name":"Thea Clay","id":34324747,"id_str":"34324747","indices":[131,140]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false},"retweet_count":2,"entities":{"hashtags":[{"text":"rhok","indices":[126,131]}],"urls":[{"url":"http:\/\/t.co\/Sk5BM7U3","expanded_url":"http:\/\/zvents.com\/e\/IhP3T\/7o","display_url":"zvents.com\/e\/IhP3T\/7o","indices":[81,101]}],"user_mentions":[{"screen_name":"randomhacks","name":"Random Hacks","id":75361247,"id_str":"75361247","indices":[3,15]},{"screen_name":"cod","name":"Chris OBrien","id":13791662,"id_str":"13791662","indices":[132,136]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 16:17:55 +0000 2012","id":244107236262170624,"id_str":"244107236262170624","text":"RT @jondot: Just published: \"Pragmatic Concurrency With #Ruby\" http:\/\/t.co\/kGEykswZ \/cc @JRuby @headius","source":"\u003ca href=\"http:\/\/twitter.com\/download\/iphone\" rel=\"nofollow\"\u003eTwitter for iPhone\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":10248172,"id_str":"10248172","name":"Fredrik Bj\u00f6rk","screen_name":"fbjork","location":"San Francisco, CA","description":"Director of Engineering at @banjo","url":"http:\/\/ban.jo","entities":{"url":{"urls":[{"url":"http:\/\/ban.jo","expanded_url":null,"indices":[0,13]}]},"description":{"urls":[]}},"protected":false,"followers_count":266,"friends_count":343,"listed_count":18,"created_at":"Wed Nov 14 14:58:28 +0000 2007","favourites_count":7,"utc_offset":-28800,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":944,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"131516","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme14\/bg.gif","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme14\/bg.gif","profile_background_tile":true,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/2167836514\/252562_10150648192185221_786305220_19068177_4887761_n_normal.jpg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/2167836514\/252562_10150648192185221_786305220_19068177_4887761_n_normal.jpg","profile_link_color":"009999","profile_sidebar_border_color":"EEEEEE","profile_sidebar_fill_color":"EFEFEF","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":true,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"created_at":"Fri Sep 07 15:53:34 +0000 2012","id":244101108983803904,"id_str":"244101108983803904","text":"Just published: \"Pragmatic Concurrency With #Ruby\" http:\/\/t.co\/kGEykswZ \/cc @JRuby @headius","source":"web","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":25607541,"id_str":"25607541","name":"dotan nahum","screen_name":"jondot","location":"","description":"I'm just a mean code machine. Constantly scanning, hunting and building the next big thing.","url":"http:\/\/blog.paracode.com","entities":{"url":{"urls":[{"url":"http:\/\/blog.paracode.com","expanded_url":null,"indices":[0,24]}]},"description":{"urls":[]}},"protected":false,"followers_count":410,"friends_count":85,"listed_count":13,"created_at":"Sat Mar 21 00:26:10 +0000 2009","favourites_count":0,"utc_offset":-10800,"time_zone":"Greenland","geo_enabled":false,"verified":false,"statuses_count":784,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"2B1F44","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/437973354\/nwgrand_516_142243.jpg","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/437973354\/nwgrand_516_142243.jpg","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1181955409\/nd_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1181955409\/nd_normal.png","profile_link_color":"1C62B9","profile_sidebar_border_color":"F1A253","profile_sidebar_fill_color":"221309","profile_text_color":"755C8A","profile_use_background_image":true,"show_all_inline_media":false,"default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":8,"entities":{"hashtags":[{"text":"Ruby","indices":[44,49]}],"urls":[{"url":"http:\/\/t.co\/kGEykswZ","expanded_url":"http:\/\/blog.paracode.com\/2012\/09\/07\/pragmatic-concurrency-with-ruby\/","display_url":"blog.paracode.com\/2012\/09\/07\/pra\u2026","indices":[51,71]}],"user_mentions":[{"screen_name":"jruby","name":"JRuby Dev Team","id":16132186,"id_str":"16132186","indices":[78,84]},{"screen_name":"headius","name":"Charles Nutter","id":9989362,"id_str":"9989362","indices":[85,93]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false},"retweet_count":8,"entities":{"hashtags":[{"text":"Ruby","indices":[56,61]}],"urls":[{"url":"http:\/\/t.co\/kGEykswZ","expanded_url":"http:\/\/blog.paracode.com\/2012\/09\/07\/pragmatic-concurrency-with-ruby\/","display_url":"blog.paracode.com\/2012\/09\/07\/pra\u2026","indices":[63,83]}],"user_mentions":[{"screen_name":"jondot","name":"dotan nahum","id":25607541,"id_str":"25607541","indices":[3,10]},{"screen_name":"jruby","name":"JRuby Dev Team","id":16132186,"id_str":"16132186","indices":[90,96]},{"screen_name":"headius","name":"Charles Nutter","id":9989362,"id_str":"9989362","indices":[97,105]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 16:14:53 +0000 2012","id":244106476048764928,"id_str":"244106476048764928","text":"If you are wondering how we computed the split bubbles: http:\/\/t.co\/BcaqSs5u","source":"\u003ca href=\"http:\/\/itunes.apple.com\/us\/app\/twitter\/id409789998?mt=12\" rel=\"nofollow\"\u003eTwitter for Mac\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":43593,"id_str":"43593","name":"Mike Bostock","screen_name":"mbostock","location":"San Francisco, CA","description":"Purveyor of fine misinformations.","url":"http:\/\/bost.ocks.org","entities":{"url":{"urls":[{"url":"http:\/\/bost.ocks.org","expanded_url":null,"indices":[0,20]}]},"description":{"urls":[]}},"protected":false,"followers_count":4090,"friends_count":181,"listed_count":227,"created_at":"Tue Dec 05 21:57:30 +0000 2006","favourites_count":124,"utc_offset":-28800,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":2237,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"131516","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme14\/bg.gif","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme14\/bg.gif","profile_background_tile":true,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1434042628\/mbostock-sf_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1434042628\/mbostock-sf_normal.png","profile_link_color":"9F0606","profile_sidebar_border_color":"EEEEEE","profile_sidebar_fill_color":"EFEFEF","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":true,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":1,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/BcaqSs5u","expanded_url":"http:\/\/bl.ocks.org\/3422480","display_url":"bl.ocks.org\/3422480","indices":[56,76]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 16:11:24 +0000 2012","id":244105599351148544,"id_str":"244105599351148544","text":"\u201cWrite drunk. Edit sober.\u201d\u2014Ernest Hemingway","source":"\u003ca href=\"http:\/\/stone.com\/neue\" rel=\"nofollow\"\u003eTwittelator Neue\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":485409945,"id_str":"485409945","name":"Fake Jack Dorsey","screen_name":"FakeDorsey","location":"San Francisco","description":"Simplify, bitches.","url":"http:\/\/square.twitter.com","entities":{"url":{"urls":[{"url":"http:\/\/square.twitter.com","expanded_url":null,"indices":[0,25]}]},"description":{"urls":[]}},"protected":false,"followers_count":3275,"friends_count":1,"listed_count":61,"created_at":"Tue Feb 07 05:16:26 +0000 2012","favourites_count":4,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":86,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1810072255\/Untitled_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1810072255\/Untitled_normal.png","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":false,"default_profile":true,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":14,"entities":{"hashtags":[],"urls":[],"user_mentions":[]},"favorited":false,"retweeted":false},{"created_at":"Fri Sep 07 16:07:16 +0000 2012","id":244104558433951744,"id_str":"244104558433951744","text":"RT @wcmaier: Better banking through better ops: build something new with us @Simplify (remote, PDX) http:\/\/t.co\/8WgzKZH3","source":"\u003ca href=\"http:\/\/tapbots.com\/tweetbot\" rel=\"nofollow\"\u003eTweetbot for iOS\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":18713,"id_str":"18713","name":"Alex Payne","screen_name":"al3x","location":"Berlin (Aug 31 - Sept 21)","description":"Programmer. Writer. Secular Humanist.","url":"http:\/\/al3x.net","entities":{"url":{"urls":[{"url":"http:\/\/al3x.net","expanded_url":null,"indices":[0,15]}]},"description":{"urls":[]}},"protected":false,"followers_count":36487,"friends_count":323,"listed_count":2272,"created_at":"Thu Nov 23 19:29:11 +0000 2006","favourites_count":4615,"utc_offset":3600,"time_zone":"Berlin","geo_enabled":true,"verified":false,"statuses_count":23134,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"E5E9EB","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/357750272\/small_3_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/357750272\/small_3_normal.png","profile_link_color":"336699","profile_sidebar_border_color":"333333","profile_sidebar_fill_color":"C3CBD0","profile_text_color":"232323","profile_use_background_image":false,"show_all_inline_media":true,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"created_at":"Fri Sep 07 15:27:38 +0000 2012","id":244094582411890689,"id_str":"244094582411890689","text":"Better banking through better ops: build something new with us @Simplify (remote, PDX) http:\/\/t.co\/8WgzKZH3","source":"\u003ca href=\"http:\/\/tapbots.com\/tweetbot\" rel=\"nofollow\"\u003eTweetbot for iOS\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":11125102,"id_str":"11125102","name":"Will Maier","screen_name":"wcmaier","location":"Madison, WI, USA","description":"I help @Simplify ship beautiful things. Previously @lt_kije.","url":"http:\/\/wcm.aier.us\/","entities":{"url":{"urls":[{"url":"http:\/\/wcm.aier.us\/","expanded_url":null,"indices":[0,19]}]},"description":{"urls":[]}},"protected":false,"followers_count":240,"friends_count":193,"listed_count":16,"created_at":"Thu Dec 13 12:35:31 +0000 2007","favourites_count":2,"utc_offset":-21600,"time_zone":"Central Time (US & Canada)","geo_enabled":false,"verified":false,"statuses_count":3898,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/39909052\/kije-final_normal.jpg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/39909052\/kije-final_normal.jpg","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":true,"default_profile":true,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":3,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/8WgzKZH3","expanded_url":"http:\/\/careers.simple.com\/apply\/LKW4tQ\/Operations-Engineer.html","display_url":"careers.simple.com\/apply\/LKW4tQ\/O\u2026","indices":[87,107]}],"user_mentions":[{"screen_name":"Simplify","name":"Simple","id":71165241,"id_str":"71165241","indices":[63,72]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false},"retweet_count":3,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/8WgzKZH3","expanded_url":"http:\/\/careers.simple.com\/apply\/LKW4tQ\/Operations-Engineer.html","display_url":"careers.simple.com\/apply\/LKW4tQ\/O\u2026","indices":[100,120]}],"user_mentions":[{"screen_name":"wcmaier","name":"Will Maier","id":11125102,"id_str":"11125102","indices":[3,11]},{"screen_name":"Simplify","name":"Simple","id":71165241,"id_str":"71165241","indices":[76,85]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 16:05:38 +0000 2012","id":244104146997870594,"id_str":"244104146997870594","text":"We just announced Mosaic, what we've been working on since the Yobongo acquisition. My personal post, http:\/\/t.co\/ELOyIRZU @heymosaic","source":"web","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":1882641,"id_str":"1882641","name":"Caleb Elston","screen_name":"calebelston","location":"San Francisco","description":"Co-founder & CEO of Yobongo. Dubious of people who claim to be experts. Formerly VP Products at Justin.tv. Advisor to Simpler.","url":"http:\/\/www.calebelston.com","entities":{"url":{"urls":[{"url":"http:\/\/www.calebelston.com","expanded_url":null,"indices":[0,26]}]},"description":{"urls":[]}},"protected":false,"followers_count":1960,"friends_count":151,"listed_count":136,"created_at":"Thu Mar 22 14:34:22 +0000 2007","favourites_count":815,"utc_offset":-28800,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":7068,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"666666","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/322151965\/ngb.gif","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/322151965\/ngb.gif","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/2584558450\/elyaf9epw0kcnh9gxglp_normal.jpeg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/2584558450\/elyaf9epw0kcnh9gxglp_normal.jpeg","profile_link_color":"0099CC","profile_sidebar_border_color":"E3E3E3","profile_sidebar_fill_color":"FFFFFF","profile_text_color":"292E38","profile_use_background_image":false,"show_all_inline_media":true,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":4,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/ELOyIRZU","expanded_url":"http:\/\/calebelston.com\/2012\/09\/07\/meet-mosaic\/","display_url":"calebelston.com\/2012\/09\/07\/mee\u2026","indices":[102,122]}],"user_mentions":[{"screen_name":"heymosaic","name":"Mosaic","id":772256556,"id_str":"772256556","indices":[123,133]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 16:01:18 +0000 2012","id":244103057175113729,"id_str":"244103057175113729","text":"Donate $10 or more --&gt; get your favorite car magnet: http:\/\/t.co\/NfRhl2s2 #Obama2012","source":"web","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":813286,"id_str":"813286","name":"Barack Obama","screen_name":"BarackObama","location":"Washington, DC","description":"This account is run by #Obama2012 campaign staff. Tweets from the President are signed -bo.","url":"http:\/\/www.barackobama.com","entities":{"url":{"urls":[{"url":"http:\/\/www.barackobama.com","expanded_url":null,"indices":[0,26]}]},"description":{"urls":[]}},"protected":false,"followers_count":19449227,"friends_count":673288,"listed_count":175179,"created_at":"Mon Mar 05 22:08:25 +0000 2007","favourites_count":0,"utc_offset":-18000,"time_zone":"Eastern Time (US & Canada)","geo_enabled":false,"verified":true,"statuses_count":5968,"lang":"en","contributors_enabled":true,"is_translator":false,"profile_background_color":"77B0DC","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/584034019\/tkwyaf768hs9bylnus1k.jpeg","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/584034019\/tkwyaf768hs9bylnus1k.jpeg","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/2325704772\/wrrmef61i6jl91kwkmzq_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/2325704772\/wrrmef61i6jl91kwkmzq_normal.png","profile_link_color":"2574AD","profile_sidebar_border_color":"C2E0F6","profile_sidebar_fill_color":"C2E0F6","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":false,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":147,"entities":{"hashtags":[{"text":"Obama2012","indices":[77,87]}],"urls":[{"url":"http:\/\/t.co\/NfRhl2s2","expanded_url":"http:\/\/OFA.BO\/eWNq2T","display_url":"OFA.BO\/eWNq2T","indices":[56,76]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 16:00:25 +0000 2012","id":244102834398851073,"id_str":"244102834398851073","text":"RT @tenderlove: If corporations are people, can we use them to drive in the carpool lane?","source":"\u003ca href=\"http:\/\/sites.google.com\/site\/yorufukurou\/\" rel=\"nofollow\"\u003eYoruFukurou\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":20941662,"id_str":"20941662","name":"James Edward Gray II","screen_name":"JEG2","location":"Edmond, OK","description":"Rubyist, Husband, Father, Atheist, Oklahoman, and all around weird guy.","url":"http:\/\/blog.grayproductions.net","entities":{"url":{"urls":[{"url":"http:\/\/blog.grayproductions.net","expanded_url":null,"indices":[0,31]}]},"description":{"urls":[]}},"protected":false,"followers_count":4206,"friends_count":174,"listed_count":389,"created_at":"Sun Feb 15 22:05:54 +0000 2009","favourites_count":0,"utc_offset":-21600,"time_zone":"Central Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":11780,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"EBEBEB","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme7\/bg.gif","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme7\/bg.gif","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/2311650093\/fkgorpzafxmsafxpf6wi_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/2311650093\/fkgorpzafxmsafxpf6wi_normal.png","profile_link_color":"990000","profile_sidebar_border_color":"DFDFDF","profile_sidebar_fill_color":"F3F3F3","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":true,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"created_at":"Fri Sep 07 15:57:28 +0000 2012","id":244102091730210816,"id_str":"244102091730210816","text":"If corporations are people, can we use them to drive in the carpool lane?","source":"\u003ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003eEchofon\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":14761655,"id_str":"14761655","name":"Aaron Patterson","screen_name":"tenderlove","location":"Seattle, WA","description":"\u3072\u3052\u306e\u5c71\u7537\u3002 When I'm not trimming my beard, I'm hanging out with my lady, @ebiltwin.","url":"http:\/\/tenderlovemaking.com","entities":{"url":{"urls":[{"url":"http:\/\/tenderlovemaking.com","expanded_url":null,"indices":[0,27]}]},"description":{"urls":[]}},"protected":false,"followers_count":10869,"friends_count":365,"listed_count":862,"created_at":"Tue May 13 17:25:31 +0000 2008","favourites_count":275,"utc_offset":-28800,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":14623,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1261953917\/headshot_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1261953917\/headshot_normal.png","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":false,"default_profile":true,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":10,"entities":{"hashtags":[],"urls":[],"user_mentions":[]},"favorited":false,"retweeted":false},"retweet_count":10,"entities":{"hashtags":[],"urls":[],"user_mentions":[{"screen_name":"tenderlove","name":"Aaron Patterson","id":14761655,"id_str":"14761655","indices":[3,14]}]},"favorited":false,"retweeted":false},{"created_at":"Fri Sep 07 16:00:03 +0000 2012","id":244102741125890048,"id_str":"244102741125890048","text":"LDN\u2014Obama's nomination; Putin woos APEC; Bombs hit Damascus; Quakes shake China; Canada cuts Iran ties; weekend read: http:\/\/t.co\/OFs6dVW4","source":"web","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":632391565,"id_str":"632391565","name":"Evening Edition","screen_name":"eveningedition","location":"","description":"The perfect commute-sized way to catch up on the day\u2019s news after a long day at work. Brought to you by @MuleDesign.","url":"http:\/\/evening-edition.com","entities":{"url":{"urls":[{"url":"http:\/\/evening-edition.com","expanded_url":null,"indices":[0,26]}]},"description":{"urls":[]}},"protected":false,"followers_count":3357,"friends_count":3,"listed_count":115,"created_at":"Tue Jul 10 23:02:44 +0000 2012","favourites_count":19,"utc_offset":null,"time_zone":null,"geo_enabled":false,"verified":false,"statuses_count":76,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"FFFFFF","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/2406639576\/q8cnprnmdv0z0gt6wtda_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/2406639576\/q8cnprnmdv0z0gt6wtda_normal.png","profile_link_color":"CC3333","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":false,"show_all_inline_media":false,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":3,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/OFs6dVW4","expanded_url":"http:\/\/evening-edition.com","display_url":"evening-edition.com","indices":[118,138]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 16:00:00 +0000 2012","id":244102729860009984,"id_str":"244102729860009984","text":"RT @ggreenwald: Democrats parade Osama bin Laden's corpse as their proudest achievement: why this goulish jingoism is so warped http:\/\/t ...","source":"\u003ca href=\"http:\/\/www.echofon.com\/\" rel=\"nofollow\"\u003eEchofon\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":14561327,"id_str":"14561327","name":"DHH","screen_name":"dhh","location":"Chicago, USA","description":"Creator of Ruby on Rails, Partner at 37signals, Co-author of NYT Best-Seller Rework, and racing driver in ALMS.","url":"http:\/\/david.heinemeierhansson.com","entities":{"url":{"urls":[{"url":"http:\/\/david.heinemeierhansson.com","expanded_url":null,"indices":[0,34]}]},"description":{"urls":[]}},"protected":false,"followers_count":63074,"friends_count":140,"listed_count":4874,"created_at":"Sun Apr 27 20:19:25 +0000 2008","favourites_count":5,"utc_offset":-21600,"time_zone":"Central Time (US & Canada)","geo_enabled":true,"verified":true,"statuses_count":8710,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/2556368541\/alng5gtlmjhrdlr3qxqv_normal.jpeg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/2556368541\/alng5gtlmjhrdlr3qxqv_normal.jpeg","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":true,"default_profile":true,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"created_at":"Fri Sep 07 15:23:23 +0000 2012","id":244093513216696321,"id_str":"244093513216696321","text":"Democrats parade Osama bin Laden's corpse as their proudest achievement: why this goulish jingoism is so warped http:\/\/t.co\/kood278s","source":"web","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":16076032,"id_str":"16076032","name":"Glenn Greenwald","screen_name":"ggreenwald","location":"","description":"Columnist & blogger for the Guardian (http:\/\/is.gd\/WWjIKY) - author, With Liberty and Justice for Some - dog\/animal fanatic ","url":"http:\/\/is.gd\/WWjIKY","entities":{"url":{"urls":[{"url":"http:\/\/is.gd\/WWjIKY","expanded_url":null,"indices":[0,19]}]},"description":{"urls":[]}},"protected":false,"followers_count":93616,"friends_count":610,"listed_count":5680,"created_at":"Mon Sep 01 03:13:32 +0000 2008","favourites_count":22,"utc_offset":-16200,"time_zone":"Caracas","geo_enabled":false,"verified":true,"statuses_count":22441,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C0DEED","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme1\/bg.png","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/2182259529\/glenn_normal.jpg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/2182259529\/glenn_normal.jpg","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":false,"default_profile":true,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":95,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/kood278s","expanded_url":"http:\/\/is.gd\/6rrjXd","display_url":"is.gd\/6rrjXd","indices":[112,132]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false},"retweet_count":95,"entities":{"hashtags":[],"urls":[],"user_mentions":[{"screen_name":"ggreenwald","name":"Glenn Greenwald","id":16076032,"id_str":"16076032","indices":[3,14]}]},"favorited":false,"retweeted":false},{"created_at":"Fri Sep 07 15:59:03 +0000 2012","id":244102490646278146,"id_str":"244102490646278146","text":"The story of Mars Curiosity's gears, made by a factory in Rockford, IL: http:\/\/t.co\/MwCRsHQg","source":"\u003ca href=\"http:\/\/itunes.apple.com\/us\/app\/twitter\/id409789998?mt=12\" rel=\"nofollow\"\u003eTwitter for Mac\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":14372143,"id_str":"14372143","name":"Jason Fried","screen_name":"jasonfried","location":"Chicago, IL","description":"Founder of 37signals. Co-author of REWORK. Credo: It's simple until you make it complicated.","url":"http:\/\/www.37signals.com","entities":{"url":{"urls":[{"url":"http:\/\/www.37signals.com","expanded_url":null,"indices":[0,24]}]},"description":{"urls":[]}},"protected":false,"followers_count":90623,"friends_count":94,"listed_count":6724,"created_at":"Sun Apr 13 01:31:17 +0000 2008","favourites_count":502,"utc_offset":-21600,"time_zone":"Central Time (US & Canada)","geo_enabled":false,"verified":true,"statuses_count":11501,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"000000","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/157820538\/37sicon1.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/157820538\/37sicon1.png","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/585991126\/jasonfried-avatar_normal.jpg","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/585991126\/jasonfried-avatar_normal.jpg","profile_link_color":"0099CC","profile_sidebar_border_color":"FFF8AD","profile_sidebar_fill_color":"F6FFD1","profile_text_color":"000000","profile_use_background_image":true,"show_all_inline_media":true,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":4,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/MwCRsHQg","expanded_url":"http:\/\/kottke.org\/12\/09\/the-story-of-mars-curiositys-gears","display_url":"kottke.org\/12\/09\/the-stor\u2026","indices":[72,92]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 15:57:56 +0000 2012","id":244102209942458368,"id_str":"244102209942458368","text":"@episod @twitterapi now https:\/\/t.co\/I17jUTu2 and https:\/\/t.co\/deDu4Hgw seem to be missing \"1.1\" from the URL.","source":"\u003ca href=\"http:\/\/itunes.apple.com\/us\/app\/twitter\/id409789998?mt=12\" rel=\"nofollow\"\u003eTwitter for Mac\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":244100786940964865,"in_reply_to_status_id_str":"244100786940964865","in_reply_to_user_id":819797,"in_reply_to_user_id_str":"819797","in_reply_to_screen_name":"episod","user":{"id":7505382,"id_str":"7505382","name":"Erik Michaels-Ober","screen_name":"sferik","location":"San Francisco","description":"Vagabond.","url":"https:\/\/github.com\/sferik","entities":{"url":{"urls":[{"url":"https:\/\/github.com\/sferik","expanded_url":null,"indices":[0,25]}]},"description":{"urls":[]}},"protected":false,"followers_count":2383,"friends_count":210,"listed_count":126,"created_at":"Mon Jul 16 12:59:01 +0000 2007","favourites_count":4157,"utc_offset":-28800,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":8342,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"000000","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/643217856\/we_concept_bg2.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/643217856\/we_concept_bg2.png","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1759857427\/image1326743606_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1759857427\/image1326743606_normal.png","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":true,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"entities":{"hashtags":[],"urls":[{"url":"https:\/\/t.co\/I17jUTu2","expanded_url":"https:\/\/dev.twitter.com\/docs\/api\/post\/direct_messages\/destroy","display_url":"dev.twitter.com\/docs\/api\/post\/\u2026","indices":[24,45]},{"url":"https:\/\/t.co\/deDu4Hgw","expanded_url":"https:\/\/dev.twitter.com\/docs\/api\/post\/direct_messages\/new","display_url":"dev.twitter.com\/docs\/api\/post\/\u2026","indices":[50,71]}],"user_mentions":[{"screen_name":"episod","name":"Taylor Singletary","id":819797,"id_str":"819797","indices":[0,7]},{"screen_name":"twitterapi","name":"Twitter API","id":6253282,"id_str":"6253282","indices":[8,19]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 15:50:47 +0000 2012","id":244100411563339777,"id_str":"244100411563339777","text":"@episod @twitterapi Did you catch https:\/\/t.co\/VHsQvZT0 as well?","source":"\u003ca href=\"http:\/\/itunes.apple.com\/us\/app\/twitter\/id409789998?mt=12\" rel=\"nofollow\"\u003eTwitter for Mac\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":244097234432565248,"in_reply_to_status_id_str":"244097234432565248","in_reply_to_user_id":819797,"in_reply_to_user_id_str":"819797","in_reply_to_screen_name":"episod","user":{"id":7505382,"id_str":"7505382","name":"Erik Michaels-Ober","screen_name":"sferik","location":"San Francisco","description":"Vagabond.","url":"https:\/\/github.com\/sferik","entities":{"url":{"urls":[{"url":"https:\/\/github.com\/sferik","expanded_url":null,"indices":[0,25]}]},"description":{"urls":[]}},"protected":false,"followers_count":2383,"friends_count":210,"listed_count":126,"created_at":"Mon Jul 16 12:59:01 +0000 2007","favourites_count":4157,"utc_offset":-28800,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":8342,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"000000","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/643217856\/we_concept_bg2.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/643217856\/we_concept_bg2.png","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1759857427\/image1326743606_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1759857427\/image1326743606_normal.png","profile_link_color":"0084B4","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"show_all_inline_media":true,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"entities":{"hashtags":[],"urls":[{"url":"https:\/\/t.co\/VHsQvZT0","expanded_url":"https:\/\/twitter.com\/sferik\/status\/243988000076337152","display_url":"twitter.com\/sferik\/status\/\u2026","indices":[34,55]}],"user_mentions":[{"screen_name":"episod","name":"Taylor Singletary","id":819797,"id_str":"819797","indices":[0,7]},{"screen_name":"twitterapi","name":"Twitter API","id":6253282,"id_str":"6253282","indices":[8,19]}]},"favorited":false,"retweeted":false,"possibly_sensitive":false},{"created_at":"Fri Sep 07 15:47:01 +0000 2012","id":244099460672679938,"id_str":"244099460672679938","text":"Gentlemen, you can't fight in here! This is the war room! http:\/\/t.co\/kMxMYyqF","source":"\u003ca href=\"http:\/\/instagr.am\" rel=\"nofollow\"\u003eInstagram\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":2897431,"id_str":"2897431","name":"Dave Wiskus ","screen_name":"dwiskus","location":"Denver \/ Amsterdam","description":"I draw pictures of software for money.","url":"http:\/\/betterelevation.com\/","entities":{"url":{"urls":[{"url":"http:\/\/betterelevation.com\/","expanded_url":null,"indices":[0,27]}]},"description":{"urls":[]}},"protected":false,"followers_count":2367,"friends_count":271,"listed_count":187,"created_at":"Thu Mar 29 21:37:02 +0000 2007","favourites_count":3314,"utc_offset":-25200,"time_zone":"Mountain Time (US & Canada)","geo_enabled":false,"verified":false,"statuses_count":12827,"lang":"en","contributors_enabled":false,"is_translator":false,"profile_background_color":"C6E2EE","profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme2\/bg.gif","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme2\/bg.gif","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1514640834\/dwiskus-avatar-2011_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1514640834\/dwiskus-avatar-2011_normal.png","profile_link_color":"1F98C7","profile_sidebar_border_color":"C6E2EE","profile_sidebar_fill_color":"DAECF4","profile_text_color":"663B12","profile_use_background_image":true,"show_all_inline_media":false,"default_profile":false,"default_profile_image":false,"following":true,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"entities":{"hashtags":[],"urls":[{"url":"http:\/\/t.co\/kMxMYyqF","expanded_url":"http:\/\/instagr.am\/p\/PR5cDLzFz5\/","display_url":"instagr.am\/p\/PR5cDLzFz5\/","indices":[58,78]}],"user_mentions":[]},"favorited":false,"retweeted":false,"possibly_sensitive":false}]
View
1  spec/fixtures/true.json
@@ -1 +0,0 @@
-true
View
119 spec/twitter/api/blocks_spec.rb
@@ -9,60 +9,119 @@
describe "#blocking" do
before do
stub_get("/1.1/blocks/list.json").
- to_return(:body => fixture("users.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ with(:query => {:cursor => "-1"}).
+ to_return(:body => fixture("users_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.blocking
a_get("/1.1/blocks/list.json").
+ with(:query => {:cursor => "-1"}).
should have_been_made
end
it "returns an array of user objects that the authenticating user is blocking" do
- users = @client.blocking
- users.should be_an Array
- users.first.should be_a Twitter::User
- users.first.id.should eq 7505382
+ blocking = @client.blocking
+ blocking.should be_a Twitter::Cursor
+ blocking.users.should be_an Array
+ blocking.users.first.should be_a Twitter::User
+ blocking.users.first.id.should eq 7505382
end
end
describe "#blocked_ids" do
before do
stub_get("/1.1/blocks/ids.json").
- to_return(:body => fixture("ids.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ with(:query => {:cursor => "-1"}).
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.blocked_ids
a_get("/1.1/blocks/ids.json").
+ with(:query => {:cursor => "-1"}).
should have_been_made
end
it "returns an array of numeric user IDs the authenticating user is blocking" do
- ids = @client.blocked_ids
- ids.should be_an Array
- ids.first.should eq 47
+ blocked_ids = @client.blocked_ids
+ blocked_ids.should be_a Twitter::Cursor
+ blocked_ids.ids.should be_an Array
+ blocked_ids.ids.first.should eq 14100886
end
end
describe "#block?" do
- before do
- stub_get("/1.1/blocks/exists.json").
- with(:query => {:screen_name => "sferik"}).
- to_return(:body => fixture("sferik.json"), :headers => {:content_type => "application/json; charset=utf-8"})
- stub_get("/1.1/blocks/exists.json").
- with(:query => {:screen_name => "pengwynn"}).
- to_return(:body => fixture("not_found.json"), :status => 404, :headers => {:content_type => "application/json; charset=utf-8"})
- end
- it "requests the correct resource" do
- @client.block?("sferik")
- a_get("/1.1/blocks/exists.json").
- with(:query => {:screen_name => "sferik"}).
- should have_been_made
- end
- it "returns true if block exists" do
- block = @client.block?("sferik")
- block.should be_true
- end
- it "returns false if block does not exist" do
- block = @client.block?("pengwynn")
- block.should be_false
+ context "with a screen name passed" do
+ before do
+ stub_get("/1.1/blocks/ids.json").
+ with(:query => {:cursor => "-1"}).
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/blocks/ids.json").
+ with(:query => {:cursor => "1305102810874389703"}).
+ to_return(:body => fixture("ids_list2.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/users/show.json").
+ with(:query => {:screen_name => "pengwynn"}).
+ to_return(:body => fixture("pengwynn.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/users/show.json").
+ with(:query => {:screen_name => "sferik"}).
+ to_return(:body => fixture("sferik.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ end
+ it "requests the correct resource" do
+ @client.block?("sferik")
+ a_get("/1.1/blocks/ids.json").
+ with(:query => {:cursor => "-1"}).
+ should have_been_made
+ a_get("/1.1/blocks/ids.json").
+ with(:query => {:cursor => "1305102810874389703"}).
+ should have_been_made
+ a_get("/1.1/users/show.json").
+ with(:query => {:screen_name => "sferik"}).
+ should have_been_made
+ end
+ it "returns true if block exists" do
+ block = @client.block?("pengwynn")
+ block.should be_true
+ end
+ it "returns false if block does not exist" do
+ block = @client.block?("sferik")
+ block.should be_false
+ end
+ end
+ context "with a user ID passed" do
+ before do
+ stub_get("/1.1/blocks/ids.json").
+ with(:query => {:cursor => "-1"}).
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/blocks/ids.json").
+ with(:query => {:cursor => "1305102810874389703"}).
+ to_return(:body => fixture("ids_list2.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ end
+ it "requests the correct resources" do
+ @client.block?(7505382)
+ a_get("/1.1/blocks/ids.json").
+ with(:query => {:cursor => "-1"}).
+ should have_been_made
+ a_get("/1.1/blocks/ids.json").
+ with(:query => {:cursor => "1305102810874389703"}).
+ should have_been_made
+ end
+ end
+ context "with a user object passed" do
+ before do
+ stub_get("/1.1/blocks/ids.json").
+ with(:query => {:cursor => "-1"}).
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/blocks/ids.json").
+ with(:query => {:cursor => "1305102810874389703"}).
+ to_return(:body => fixture("ids_list2.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ end
+ it "requests the correct resources" do
+ user = Twitter::User.new(:id => '7505382')
+ @client.block?(user)
+ a_get("/1.1/blocks/ids.json").
+ with(:query => {:cursor => "-1"}).
+ should have_been_made
+ a_get("/1.1/blocks/ids.json").
+ with(:query => {:cursor => "1305102810874389703"}).
+ should have_been_made
+ end
end
end
View
6 spec/twitter/api/direct_messages_spec.rb
@@ -103,12 +103,14 @@
describe "#direct_messages" do
context "with ids passed" do
before do
- stub_get("/1.1/direct_messages/show/1825786345.json").
+ stub_get("/1.1/direct_messages/show.json").
+ with(:query => {:id => "1825786345"}).
to_return(:body => fixture("direct_message.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.direct_messages(1825786345)
- a_get("/1.1/direct_messages/show/1825786345.json").
+ a_get("/1.1/direct_messages/show.json").
+ with(:query => {:id => "1825786345"}).
should have_been_made
end
it "returns an array of direct messages" do
View
79 spec/twitter/api/friendships_spec.rb
@@ -11,7 +11,7 @@
before do
stub_get("/1.1/followers/ids.json").
with(:query => {:cursor => "-1", :screen_name => "sferik"}).
- to_return(:body => fixture("id_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.follower_ids("sferik")
@@ -30,7 +30,7 @@
before do
stub_get("/1.1/followers/ids.json").
with(:query => {:cursor => "-1"}).
- to_return(:body => fixture("id_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.follower_ids
@@ -52,7 +52,7 @@
before do
stub_get("/1.1/friends/ids.json").
with(:query => {:cursor => "-1", :screen_name => "sferik"}).
- to_return(:body => fixture("id_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.friend_ids("sferik")
@@ -71,7 +71,7 @@
before do
stub_get("/1.1/friends/ids.json").
with(:query => {:cursor => "-1"}).
- to_return(:body => fixture("id_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.friend_ids
@@ -91,17 +91,17 @@
describe "#friendship?" do
context "with screen names passed" do
before do
- stub_get("/1.1/friendships/exists.json").
- with(:query => {:screen_name_a => "sferik", :screen_name_b => "pengwynn"}).
- to_return(:body => fixture("true.json"), :headers => {:content_type => "application/json; charset=utf-8"})
- stub_get("/1.1/friendships/exists.json").
- with(:query => {:screen_name_a => "pengwynn", :screen_name_b => "sferik"}).
- to_return(:body => fixture("false.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/friendships/show.json").
+ with(:query => {:source_screen_name => "sferik", :target_screen_name => "pengwynn"}).
+ to_return(:body => fixture("following.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/friendships/show.json").
+ with(:query => {:source_screen_name => "pengwynn", :target_screen_name => "sferik"}).
+ to_return(:body => fixture("not_following.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.friendship?("sferik", "pengwynn")
- a_get("/1.1/friendships/exists.json").
- with(:query => {:screen_name_a => "sferik", :screen_name_b => "pengwynn"}).
+ a_get("/1.1/friendships/show.json").
+ with(:query => {:source_screen_name => "sferik", :target_screen_name => "pengwynn"}).
should have_been_made
end
it "returns true if user A follows user B" do
@@ -115,29 +115,29 @@
end
context "with user IDs passed" do
before do
- stub_get("/1.1/friendships/exists.json").
- with(:query => {:user_id_a => "7505382", :user_id_b => "14100886"}).
- to_return(:body => fixture("true.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/friendships/show.json").
+ with(:query => {:source_id => "7505382", :target_id => "14100886"}).
+ to_return(:body => fixture("following.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.friendship?(7505382, 14100886)
- a_get("/1.1/friendships/exists.json").
- with(:query => {:user_id_a => "7505382", :user_id_b => "14100886"}).
+ a_get("/1.1/friendships/show.json").
+ with(:query => {:source_id => "7505382", :target_id => "14100886"}).
should have_been_made
end
end
context "with user objects passed" do
before do
- stub_get("/1.1/friendships/exists.json").
- with(:query => {:user_id_a => "7505382", :user_id_b => "14100886"}).
- to_return(:body => fixture("true.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/friendships/show.json").
+ with(:query => {:source_id => "7505382", :target_id => "14100886"}).
+ to_return(:body => fixture("following.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
user1 = Twitter::User.new(:id => '7505382')
user2 = Twitter::User.new(:id => '14100886')
@client.friendship?(user1, user2)
- a_get("/1.1/friendships/exists.json").
- with(:query => {:user_id_a => "7505382", :user_id_b => "14100886"}).
+ a_get("/1.1/friendships/show.json").
+ with(:query => {:source_id => "7505382", :target_id => "14100886"}).
should have_been_made
end
end
@@ -147,7 +147,7 @@
before do
stub_get("/1.1/friendships/incoming.json").
with(:query => {:cursor => "-1"}).
- to_return(:body => fixture("id_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.friendships_incoming
@@ -167,7 +167,7 @@
before do
stub_get("/1.1/friendships/outgoing.json").
with(:query => {:cursor => "-1"}).
- to_return(:body => fixture("id_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.friendships_outgoing
@@ -188,7 +188,7 @@
before do
stub_get("/1.1/friendships/show.json").
with(:query => {:source_screen_name => "sferik", :target_screen_name => "pengwynn"}).
- to_return(:body => fixture("relationship.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("following.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.friendship("sferik", "pengwynn")
@@ -206,7 +206,7 @@
before do
stub_get("/1.1/friendships/show.json").
with(:query => {:source_screen_name => "0", :target_screen_name => "311"}).
- to_return(:body => fixture("relationship.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("following.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.friendship("0", "311")
@@ -219,7 +219,7 @@
before do
stub_get("/1.1/friendships/show.json").
with(:query => {:source_id => "7505382", :target_id => "14100886"}).
- to_return(:body => fixture("relationship.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("following.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.friendship(7505382, 14100886)
@@ -232,7 +232,7 @@
before do
stub_get("/1.1/friendships/show.json").
with(:query => {:source_id => "7505382", :target_id => "14100886"}).
- to_return(:body => fixture("relationship.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("following.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
user1 = Twitter::User.new(:id => '7505382')
@@ -250,7 +250,7 @@
before do
stub_get("/1.1/friends/ids.json").
with(:query => {:cursor => "-1"}).
- to_return(:body => fixture("id_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
stub_post("/1.1/users/lookup.json").
with(:body => {:screen_name => "sferik,pengwynn"}).
to_return(:body => fixture("friendships.json"), :headers => {:content_type => "application/json; charset=utf-8"})
@@ -281,7 +281,7 @@
before do
stub_get("/1.1/friends/ids.json").
with(:query => {:cursor => "-1"}).
- to_return(:body => fixture("id_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
stub_post("/1.1/users/lookup.json").
with(:body => {:screen_name => "sferik,pengwynn"}).
to_return(:body => fixture("friendships.json"), :headers => {:content_type => "application/json; charset=utf-8"})
@@ -312,7 +312,7 @@
before do
stub_get("/1.1/friends/ids.json").
with(:query => {:cursor => "-1"}).
- to_return(:body => fixture("id_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
stub_post("/1.1/users/lookup.json").
with(:body => {:screen_name => "sferik,pengwynn"}).
to_return(:body => fixture("friendships.json"), :headers => {:content_type => "application/json; charset=utf-8"})
@@ -549,7 +549,7 @@
before do
stub_post("/1.1/friendships/update.json").
with(:body => {:screen_name => "sferik", :retweets => "true"}).
- to_return(:body => fixture("relationship.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("following.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.friendship_update("sferik", :retweets => true)
@@ -566,12 +566,19 @@
describe "#no_retweet_ids" do
before do
- stub_get("/1.1/friendships/no_retweet_ids.json").
+ stub_get("/1/friendships/no_retweet_ids.json").
to_return(:body => fixture("ids.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
+ before :each do
+ @old_stderr = $stderr
+ $stderr = StringIO.new
+ end
+ after :each do
+ $stderr = @old_stderr
+ end
it "requests the correct resource" do
@client.no_retweet_ids
- a_get("/1.1/friendships/no_retweet_ids.json").
+ a_get("/1/friendships/no_retweet_ids.json").
should have_been_made
end
it "returns detailed information about the relationship between two users" do
@@ -580,6 +587,10 @@
no_retweet_ids.first.should be_an Integer
no_retweet_ids.first.should eq 47
end
+ it "should warn when called" do
+ @client.no_retweet_ids
+ $stderr.string.should =~ /\[DEPRECATION\] Twitter::API#no_retweet_ids has been deprecated without replacement and will stop working on March 5, 2013\./
+ end
end
describe "#accept" do
View
91 spec/twitter/api/lists_spec.rb
@@ -6,41 +6,6 @@
@client = Twitter::Client.new
end
- describe "#lists_subscribed_to" do
- context "with a screen name passed" do
- before do
- stub_get("/1.1/lists/all.json").
- with(:query => {:screen_name => "sferik"}).
- to_return(:body => fixture("all.json"), :headers => {:content_type => "application/json; charset=utf-8"})
- end
- it "requests the correct resource" do
- @client.lists_subscribed_to("sferik")
- a_get("/1.1/lists/all.json").
- with(:query => {:screen_name => "sferik"}).
- should have_been_made
- end
- it "returns the lists the specified user subscribes to" do
- lists = @client.lists_subscribed_to("sferik")
- lists.should be_an Array
- lists.first.should be_a Twitter::List
- lists.first.name.should eq "Rubyists"
- end
- end
- context "without a screen name passed" do
- before do
- stub_get("/1.1/account/verify_credentials.json").
- to_return(:body => fixture("sferik.json"), :headers => {:content_type => "application/json; charset=utf-8"})
- stub_get("/1.1/lists/all.json").
- to_return(:body => fixture("all.json"), :headers => {:content_type => "application/json; charset=utf-8"})
- end
- it "requests the correct resource" do
- @client.lists_subscribed_to
- a_get("/1.1/lists/all.json").
- should have_been_made
- end
- end
- end
-
describe "#list_timeline" do
context "with a screen name passed" do
before do
@@ -58,7 +23,7 @@
tweets = @client.list_timeline("sferik", "presidents")
tweets.should be_an Array
tweets.first.should be_a Twitter::Tweet
- tweets.first.text.should eq "Ruby is the best programming language for hiding the ugly bits."
+ tweets.first.text.should eq "Happy Birthday @imdane. Watch out for those @rally pranksters!"
end
end
context "without a screen name passed" do
@@ -822,45 +787,23 @@
end
describe "#lists" do
- context "with a screen name passed" do
- before do
- stub_get("/1.1/lists.json").
- with(:query => {:screen_name => 'sferik', :cursor => "-1"}).
- to_return(:body => fixture("lists.json"), :headers => {:content_type => "application/json; charset=utf-8"})
- end
- it "requests the correct resource" do
- @client.lists("sferik")
- a_get("/1.1/lists.json").
- with(:query => {:screen_name => 'sferik', :cursor => "-1"}).
- should have_been_made
- end
- it "returns the requested lists" do
- lists = @client.lists("sferik")
- lists.should be_a Twitter::Cursor
- lists.lists.should be_an Array
- lists.lists.first.should be_a Twitter::List
- lists.lists.first.name.should eq "Rubyists"
- end
+ before do
+ stub_get("/1.1/lists/list.json").
+ with(:query => {:cursor => "-1"}).
+ to_return(:body => fixture("lists.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
- context "without arguments passed" do
- before do
- stub_get("/1.1/lists.json").
- with(:query => {:cursor => "-1"}).
- to_return(:body => fixture("lists.json"), :headers => {:content_type => "application/json; charset=utf-8"})
- end
- it "requests the correct resource" do
- @client.lists
- a_get("/1.1/lists.json").
- with(:query => {:cursor => "-1"}).
- should have_been_made
- end
- it "returns the requested list" do
- lists = @client.lists
- lists.should be_a Twitter::Cursor
- lists.lists.should be_an Array
- lists.lists.first.should be_a Twitter::List
- lists.lists.first.name.should eq "Rubyists"
- end
+ it "requests the correct resource" do
+ @client.lists
+ a_get("/1.1/lists/list.json").
+ with(:query => {:cursor => "-1"}).
+ should have_been_made
+ end
+ it "returns the requested list" do
+ lists = @client.lists
+ lists.should be_a Twitter::Cursor
+ lists.lists.should be_an Array
+ lists.lists.first.should be_a Twitter::List
+ lists.lists.first.name.should eq "Rubyists"
end
end
View
119 spec/twitter/api/statuses_spec.rb
@@ -9,12 +9,14 @@
describe "#favorites" do
context "with a screen name passed" do
before do
- stub_get("/1.1/favorites/sferik.json").
+ stub_get("/1.1/favorites/list.json").
+ with(:query => {:screen_name => "sferik"}).
to_return(:body => fixture("favorites.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.favorites("sferik")
- a_get("/1.1/favorites/sferik.json").
+ a_get("/1.1/favorites/list.json").
+ with(:query => {:screen_name => "sferik"}).
should have_been_made
end
it "returns the 20 most recent favorite Tweets for the authenticating user or user specified by the ID parameter" do
@@ -26,12 +28,12 @@
end
context "without arguments passed" do
before do
- stub_get("/1.1/favorites.json").
+ stub_get("/1.1/favorites/list.json").
to_return(:body => fixture("favorites.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.favorites
- a_get("/1.1/favorites.json").
+ a_get("/1.1/favorites/list.json").
should have_been_made
end
it "returns the 20 most recent favorite Tweets for the authenticating user or user specified by the ID parameter" do
@@ -97,7 +99,7 @@
tweets = @client.home_timeline
tweets.should be_an Array
tweets.first.should be_a Twitter::Tweet
- tweets.first.text.should eq "Ruby is the best programming language for hiding the ugly bits."
+ tweets.first.text.should eq "Happy Birthday @imdane. Watch out for those @rally pranksters!"
end
end
@@ -115,57 +117,78 @@
tweets = @client.mentions_timeline
tweets.should be_an Array
tweets.first.should be_a Twitter::Tweet
- tweets.first.text.should eq "Ruby is the best programming language for hiding the ugly bits."
+ tweets.first.text.should eq "Happy Birthday @imdane. Watch out for those @rally pranksters!"
end
end
describe "#retweeted_by_user" do
before do
- stub_get("/1.1/statuses/retweeted_by_user.json").
- with(:query => {:screen_name => "sferik"}).
+ stub_get("/1.1/statuses/user_timeline.json").
+ with(:query => {:include_rts => "true", :screen_name => "sferik", :count => "200"}).
+ to_return(:body => fixture("statuses.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/statuses/user_timeline.json").
+ with(:query => {:include_rts => "true", :screen_name => "sferik", :count => "200", :max_id => "244102729860009983"}).
to_return(:body => fixture("statuses.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.retweeted_by_user("sferik")
- a_get("/1.1/statuses/retweeted_by_user.json").
- with(:query => {:screen_name => "sferik"}).
+ a_get("/1.1/statuses/user_timeline.json").
+ with(:query => {:include_rts => "true", :screen_name => "sferik", :count => "200"}).
should have_been_made
+ a_get("/1.1/statuses/user_timeline.json").
+ with(:query => {:include_rts => "true", :screen_name => "sferik", :count => "200", :max_id => "244102729860009983"}).
+ should have_been_made.times(3)
end
it "returns the 20 most recent retweets posted by the authenticating user" do
tweets = @client.retweeted_by_user("sferik")
tweets.should be_an Array
tweets.first.should be_a Twitter::Tweet
- tweets.first.text.should eq "Ruby is the best programming language for hiding the ugly bits."
+ tweets.first.text.should eq "RT @olivercameron: Mosaic looks cool: http://t.co/A8013C9k"
end
end
- describe "retweeted_by_me" do
+ describe "#retweeted_by_me" do
before do
- stub_get("/1.1/statuses/retweeted_by_me.json").
+ stub_get("/1.1/statuses/user_timeline.json").
+ with(:query => {:include_rts => "true", :count => "200"}).
+ to_return(:body => fixture("statuses.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/statuses/user_timeline.json").
+ with(:query => {:include_rts => "true", :count => "200", :max_id => "244102729860009983"}).
to_return(:body => fixture("statuses.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.retweeted_by_me
- a_get("/1.1/statuses/retweeted_by_me.json").
+ a_get("/1.1/statuses/user_timeline.json").
+ with(:query => {:include_rts => "true", :count => "200"}).
should have_been_made
+ a_get("/1.1/statuses/user_timeline.json").
+ with(:query => {:include_rts => "true", :count => "200", :max_id => "244102729860009983"}).
+ should have_been_made.times(3)
end
it "returns the 20 most recent retweets posted by the authenticating user" do
tweets = @client.retweeted_by_me
tweets.should be_an Array
tweets.first.should be_a Twitter::Tweet
- tweets.first.text.should eq "Ruby is the best programming language for hiding the ugly bits."
+ tweets.first.text.should eq "RT @olivercameron: Mosaic looks cool: http://t.co/A8013C9k"
end
end
describe "#retweeted_to_user" do
before do
- stub_get("/1.1/statuses/retweeted_to_user.json").
+ stub_get("/1/statuses/retweeted_to_user.json").
with(:query => {:screen_name => "sferik"}).
to_return(:body => fixture("statuses.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
+ before :each do
+ @old_stderr = $stderr
+ $stderr = StringIO.new
+ end
+ after :each do
+ $stderr = @old_stderr
+ end
it "requests the correct resource" do
@client.retweeted_to_user("sferik")
- a_get("/1.1/statuses/retweeted_to_user.json").
+ a_get("/1/statuses/retweeted_to_user.json").
with(:query => {:screen_name => "sferik"}).
should have_been_made
end
@@ -173,43 +196,63 @@
tweets = @client.retweeted_to_user("sferik")
tweets.should be_an Array
tweets.first.should be_a Twitter::Tweet
- tweets.first.text.should eq "Ruby is the best programming language for hiding the ugly bits."
+ tweets.first.text.should eq "Happy Birthday @imdane. Watch out for those @rally pranksters!"
+ end
+ it "should warn when called" do
+ @client.retweeted_to_user("sferik")
+ $stderr.string.should =~ /\[DEPRECATION\] Twitter::API#retweeted_to_user has been deprecated without replacement and will stop working on March 5, 2013\./
end
end
describe "#retweeted_to_me" do
before do
- stub_get("/1.1/statuses/retweeted_to_me.json").
+ stub_get("/1.1/statuses/home_timeline.json").
+ with(:query => {:include_rts => "true", :count => "200"}).
+ to_return(:body => fixture("statuses.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/statuses/home_timeline.json").
+ with(:query => {:include_rts => "true", :count => "200", :max_id => "244102729860009983"}).
to_return(:body => fixture("statuses.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.retweeted_to_me
- a_get("/1.1/statuses/retweeted_to_me.json").
+ stub_get("/1.1/statuses/home_timeline.json").
+ with(:query => {:include_rts => "true", :count => "200"}).
should have_been_made
+ stub_get("/1.1/statuses/home_timeline.json").
+ with(:query => {:include_rts => "true", :count => "200", :max_id => "244102729860009983"}).
+ should have_been_made.times(3)
end
it "returns the 20 most recent retweets posted by users the authenticating user follow" do
tweets = @client.retweeted_to_me
tweets.should be_an Array
tweets.first.should be_a Twitter::Tweet
- tweets.first.text.should eq "Ruby is the best programming language for hiding the ugly bits."
+ tweets.first.text.should eq "RT @olivercameron: Mosaic looks cool: http://t.co/A8013C9k"
end
end
describe "#retweets_of_me" do
before do
- stub_get("/1.1/statuses/retweets_of_me.json").
+ stub_get("/1.1/statuses/user_timeline.json").
+ with(:query => {:include_rts => "false", :count => "200"}).
+ to_return(:body => fixture("statuses.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/statuses/user_timeline.json").
+ with(:query => {:include_rts => "false", :count => "200", :max_id => "244102490646278145"}).
to_return(:body => fixture("statuses.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
@client.retweets_of_me
- a_get("/1.1/statuses/retweets_of_me.json").
+ a_get("/1.1/statuses/user_timeline.json").
+ with(:query => {:include_rts => "false", :count => "200"}).
+ should have_been_made
+ a_get("/1.1/statuses/user_timeline.json").
+ with(:query => {:include_rts => "false", :count => "200", :max_id => "244102490646278145"}).
should have_been_made
end
it "returns the 20 most recent tweets of the authenticated user that have been retweeted by others" do
tweets = @client.retweets_of_me
tweets.should be_an Array
tweets.first.should be_a Twitter::Tweet
- tweets.first.text.should eq "Ruby is the best programming language for hiding the ugly bits."
+ tweets.first.text.should eq "RT @olivercameron: Mosaic looks cool: http://t.co/A8013C9k"
end
end
@@ -230,7 +273,7 @@
tweets = @client.user_timeline("sferik")
tweets.should be_an Array
tweets.first.should be_a Twitter::Tweet
- tweets.first.text.should eq "Ruby is the best programming language for hiding the ugly bits."
+ tweets.first.text.should eq "Happy Birthday @imdane. Watch out for those @rally pranksters!"
end
end
context "without a screen name passed" do
@@ -293,42 +336,42 @@
tweets = @client.network_timeline
tweets.should be_an Array
tweets.first.should be_a Twitter::Tweet
- tweets.first.text.should eq "Ruby is the best programming language for hiding the ugly bits."
+ tweets.first.text.should eq "Happy Birthday @imdane. Watch out for those @rally pranksters!"
end
end
describe "#retweeters_of" do
context "with ids_only passed" do
before do
- stub_get("/1.1/statuses/27467028175/retweeted_by/ids.json").
- to_return(:body => fixture("ids.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/statuses/retweets/28561922516.json").
+ to_return(:body => fixture("retweets.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
- @client.retweeters_of(27467028175, :ids_only => true)
- a_get("/1.1/statuses/27467028175/retweeted_by/ids.json").
+ @client.retweeters_of(28561922516, :ids_only => true)
+ a_get("/1.1/statuses/retweets/28561922516.json").
should have_been_made
end
it "returns an array of numeric user IDs of retweeters of a Tweet" do
- ids = @client.retweeters_of(27467028175, :ids_only => true)
+ ids = @client.retweeters_of(28561922516, :ids_only => true)
ids.should be_an Array
- ids.first.should eq 47
+ ids.first.should eq 7505382
end
end
context "without ids_only passed" do
before do
- stub_get("/1.1/statuses/27467028175/retweeted_by.json").
- to_return(:body => fixture("retweeters_of.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ stub_get("/1.1/statuses/retweets/28561922516.json").
+ to_return(:body => fixture("retweets.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
- @client.retweeters_of(27467028175)
- a_get("/1.1/statuses/27467028175/retweeted_by.json").
+ @client.retweeters_of(28561922516)
+ a_get("/1.1/statuses/retweets/28561922516.json").
should have_been_made
end
it "returns an array of user of retweeters of a Tweet" do
- users = @client.retweeters_of(27467028175)
+ users = @client.retweeters_of(28561922516)
users.should be_an Array
users.first.should be_a Twitter::User
- users.first.name.should eq "Dave W Baldwin"
+ users.first.id.should eq 7505382
end
end
end
View
62 spec/twitter/api/trends_spec.rb
@@ -6,7 +6,7 @@
@client = Twitter::Client.new
end
- describe "#local_trends" do
+ describe "#trends" do
context "with woeid passed" do
before do
stub_get("/1.1/trends/place.json").
@@ -14,13 +14,13 @@
to_return(:body => fixture("matching_trends.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
- @client.local_trends(2487956)
+ @client.trends(2487956)
a_get("/1.1/trends/place.json").
with(:query => {:id => "2487956"}).
should have_been_made
end
it "returns the top 10 trending topics for a specific WOEID" do
- matching_trends = @client.local_trends(2487956)
+ matching_trends = @client.trends(2487956)
matching_trends.should be_an Array
matching_trends.first.should be_a Twitter::Trend
matching_trends.first.name.should eq "#sevenwordsaftersex"
@@ -33,7 +33,7 @@
to_return(:body => fixture("matching_trends.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
- @client.local_trends
+ @client.trends
a_get("/1.1/trends/place.json").
with(:query => {:id => "1"}).
should have_been_made
@@ -41,18 +41,36 @@
end
end
- describe "#trend_locations" do
+ describe "#trends_available" do
before do
stub_get("/1.1/trends/available.json").
to_return(:body => fixture("locations.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resource" do
- @client.trend_locations
+ @client.trends_available
a_get("/1.1/trends/available.json").
should have_been_made
end
it "returns the locations that Twitter has trending topic information for" do
- locations = @client.trend_locations
+ locations = @client.trends_available
+ locations.should be_an Array
+ locations.first.should be_a Twitter::Place
+ locations.first.name.should eq "Ireland"
+ end
+ end
+
+ describe "#trends_closest" do
+ before do
+ stub_get("/1.1/trends/closest.json").
+ to_return(:body => fixture("locations.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ end
+ it "requests the correct resource" do
+ @client.trends_closest
+ a_get("/1.1/trends/closest.json").
+ should have_been_made
+ end
+ it "returns the locations that Twitter has trending topic information for" do
+ locations = @client.trends_closest
locations.should be_an Array
locations.first.should be_a Twitter::Place
locations.first.name.should eq "Ireland"
@@ -61,13 +79,20 @@
describe "#trends_daily" do
before do
- stub_get("/1.1/trends/daily.json").
+ stub_get("/1/trends/daily.json").
with(:query => {:date => "2010-10-24"}).
to_return(:body => fixture("trends_daily.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
+ before :each do
+ @old_stderr = $stderr
+ $stderr = StringIO.new
+ end
+ after :each do
+ $stderr = @old_stderr
+ end
it "requests the correct resource" do
@client.trends_daily(Date.parse("2010-10-24"))
- a_get("/1.1/trends/daily.json").
+ a_get("/1/trends/daily.json").
with(:query => {:date => "2010-10-24"}).
should have_been_made
end
@@ -78,17 +103,28 @@
trends["2010-10-24 17:00".to_sym].first.should be_a Twitter::Trend
trends["2010-10-24 17:00".to_sym].first.name.should eq "#bigbangcomeback"
end
+ it "should warn when called" do
+ @client.trends_daily(Date.parse("2010-10-24"))
+ $stderr.string.should =~ /\[DEPRECATION\] Twitter::API#trends_daily has been deprecated without replacement and will stop working on March 5, 2013\./
+ end
end
describe "#trends_weekly" do
before do
- stub_get("/1.1/trends/weekly.json").
+ stub_get("/1/trends/weekly.json").
with(:query => {:date => "2010-10-24"}).
to_return(:body => fixture("trends_weekly.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
+ before :each do
+ @old_stderr = $stderr
+ $stderr = StringIO.new
+ end
+ after :each do
+ $stderr = @old_stderr
+ end
it "requests the correct resource" do
@client.trends_weekly(Date.parse("2010-10-24"))
- a_get("/1.1/trends/weekly.json").
+ a_get("/1/trends/weekly.json").
with(:query => {:date => "2010-10-24"}).
should have_been_made
end
@@ -99,6 +135,10 @@
trends["2010-10-24".to_sym].first.should be_a Twitter::Trend
trends["2010-10-24".to_sym].first.name.should eq "#youcantbeuglyand"
end
+ it "should warn when called" do
+ @client.trends_weekly(Date.parse("2010-10-24"))
+ $stderr.string.should =~ /\[DEPRECATION\] Twitter::API#trends_weekly has been deprecated without replacement and will stop working on March 5, 2013\./
+ end
end
end
View
8 spec/twitter/cursor_spec.rb
@@ -15,10 +15,10 @@
@client = Twitter::Client.new
stub_get("/1.1/followers/ids.json").
with(:query => {:cursor => "-1", :screen_name => "sferik"}).
- to_return(:body => fixture("id_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
stub_get("/1.1/followers/ids.json").
with(:query => {:cursor => "1305102810874389703", :screen_name => "sferik"}).
- to_return(:body => fixture("id_list2.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("ids_list2.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resources" do
@client.follower_ids("sferik").all
@@ -40,10 +40,10 @@
@client = Twitter::Client.new
stub_get("/1.1/followers/ids.json").
with(:query => {:cursor => "-1", :screen_name => "sferik"}).
- to_return(:body => fixture("id_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("ids_list.json"), :headers => {:content_type => "application/json; charset=utf-8"})
stub_get("/1.1/followers/ids.json").
with(:query => {:cursor => "1305102810874389703", :screen_name => "sferik"}).
- to_return(:body => fixture("id_list2.json"), :headers => {:content_type => "application/json; charset=utf-8"})
+ to_return(:body => fixture("ids_list2.json"), :headers => {:content_type => "application/json; charset=utf-8"})
end
it "requests the correct resources" do
@client.follower_ids("sferik").each{}
Please sign in to comment.
Something went wrong with that request. Please try again.