Skip to content

Commit

Permalink
converting ruby-summize gem to newly named twitter-search
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Croak committed Jul 15, 2008
0 parents commit 520eb1c
Show file tree
Hide file tree
Showing 6 changed files with 481 additions and 0 deletions.
74 changes: 74 additions & 0 deletions README.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# A Twitter Search client for Ruby.

Access the Twitter Search API from your Ruby code.

## Usage

Require the gem.

require 'TwitterSearch'

Set up a TwitterSearch::Client. Name your client (a.k.a. 'user agent') to something meaningful, such as your app's name. This helps Twitter Search answer any questions about your use of the API.

@client = TwitterSearch::Client.new 'politweets'

Request tweets by calling the query method of your client. It takes either a String or a Hash of arguments.

@tweets = @client.query 'twitter search'

The String form uses the default Twitter Search behavior, which in this example finds tweets containing both "twitter" and "search". It is identical to the more verbose, explicit version:

@tweets = @client.query :q => 'twitter search'

Use Twitter Search's query operators with the :q key to access the following behavior:

<table>
<tr><th>Operator</th><th>Finds tweets...</th></tr>

<tr><td><a href="http://search.twitter.com/search?q=twitter+search">:q => 'twitter search'</a></td><td>containing both "twitter" and "search". This is the default operator.</td></tr>
<tr><td><a href="http://search.twitter.com/search?q=%22happy+hour%22">:q => '<b>"</b>happy hour<b>"</b>'</a></td><td>containing the exact phrase "happy hour".</td></tr>
<tr><td><a href="http://search.twitter.com/search?q=obama+OR+hillary">:q => 'obama <b>OR</b> hillary'</a></td><td>containing either "obama" or "hillary" (or both).</td></tr>

<tr><td><a href="http://search.twitter.com/search?q=beer+-root">:q => 'beer <b>-</b>root'</a></td><td>containing "beer" but not "root".</td></tr>
<tr><td><a href="http://search.twitter.com/search?q=%23haiku">:q => '<b>#</b>haiku</a>'</td><td>containing the hashtag "haiku".</td></tr>
<tr><td><a href="http://search.twitter.com/search?q=from%3Aalexiskold">:q => '<b>from:</b>alexiskold'</a></td><td>sent from person "alexiskold".</td></tr>
<tr><td><a href="http://search.twitter.com/search?q=to%3Atechcrunch">:q => '<b>to:</b>techcrunch</a>'</td><td>sent to person "techcrunch".</td></tr>
<tr><td><a href="http://search.twitter.com/search?q=%40mashable">:q => '<b>@</b>mashable</a>'</td><td>referencing person "mashable".</td></tr>

<tr><td><a href="http://search.twitter.com/search?q=superhero+since%3A2008-05-01">:q => 'superhero <b>since:</b>2008-05-01'</a></td><td>containing "superhero" and sent since date "2008-05-01" (year-month-day).</td></tr>

<tr><td><a href="http://search.twitter.com/search?q=ftw+until%3A2008-05-03">:q => 'ftw <b>until:</b>2008-05-03'</a></td><td>containing "ftw" and sent up to date "2008-05-03".</td></tr>
<tr><td><a href="http://search.twitter.com/search?q=movie+-scary+%3A%29">:q => 'movie -scary <b>:)</b>'</a></td><td>containing "movie", but not "scary", and with a positive attitude.</td></tr>
<tr><td><a href="http://search.twitter.com/search?q=flight+%3A%28">:q => 'flight <b>:(</b>'</a></td><td>containing "flight" and with a negative attitude.</td></tr>
<tr><td><a href="http://search.twitter.com/search?q=traffic+%3F">:q => 'traffic <b>?</b>'</a></td><td>containing "traffic" and asking a question.</td></tr>

<tr><td><a href="http://search.twitter.com/search?q=hilarious+filter%3Alinks">:q => 'hilarious <b>filter:links</b>'</a></td><td>containing "hilarious" and linking to URLs.</td></tr>
</table>

### Foreign Languages

The Twitter Search API supports foreign languages, accessible via the :lang key. Use the [ISO 639-1](http://en.wikipedia.org/wiki/ISO_639-1) codes as the value:

@tweets = @client.query :q => 'programmé', :lang => 'fr'

### Pagination



## Gotchas

* Searches are case-insenstive.
* The "near" operator available in the Twitter Search web interface is not available via the API. You must geocode before making your Twitter Search API call.
* Searching for a positive attitude :) returns tweets containing the text :), =), :D, and :-)

## Authors

Written by Dustin Sallings (dustin@spy.net), forked by Dan Croak (dcroak@thoughtbot.com).

## Resources

* [Official Twitter Search API](http://search.twitter.com/api)

## License

MIT License, same terms as Ruby.
7 changes: 7 additions & 0 deletions TODO.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Add tests for:

* rpp: tweets per page
* since_id: returns tweets with status ids greater than the given id.
* geocode: returns tweets by users located within a given radius of the given latitude/longitude, where the user's location is taken from their Twitter profile.
* show_user: when "true", adds "<user>:" to the beginning of the tweet. This is useful for readers that do not display Atom's author field. The default is "false".
* callback: if supplied, the response will use the JSONP format with a callback of the given name. E.g., http://search.twitter.com/search.json?callback=foo&q=twitter
65 changes: 65 additions & 0 deletions lib/twitter_search.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
require 'rubygems'
require 'net/http'
require 'json'
require 'cgi'

module TwitterSearch

class Tweet
VARS = [:text, :from_user, :created_at, :id]
attr_reader *VARS
attr_reader :language

def initialize(h)
@language = h['iso_language_code']
VARS.each { |v| instance_variable_set "@#{v}", h[v.to_s] }
end
end

class Tweets
VARS = [:since_id, :max_id, :results_per_page, :page, :query, :next_page]
attr_reader *VARS

include Enumerable

def initialize(h)
@results = h['results'].map { |tweet| Tweet.new tweet }
VARS.each { |v| instance_variable_set "@#{v}", h[v.to_s] }
end

def each(&block)
@results.each(&block)
end

def size
@results.size
end
end

class Client
def initialize(agent = 'twitter-search')
@agent = agent
end

def query(opts = {})
url = URI.parse 'http://search.twitter.com/search.json'
url.query = sanitize_query opts
Tweets.new JSON.parse(Net::HTTP.get(url))
end

private

def sanitize_query(opts)
if opts.is_a? String
"q=#{CGI.escape(opts)}"
elsif opts.is_a? Hash
"#{sanitize_query_hash(opts)}"
end
end

def sanitize_query_hash(query_hash)
query_hash.map{ |k,v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join('&')
end
end

end
40 changes: 40 additions & 0 deletions rakefile.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# coding: utf-8
# Dan Croak, July 2008

require File.expand_path('lib/twitter_search', File.dirname(__FILE__))
require 'rubygems'
require 'yaml'

namespace :yaml do
desc "Write Twitter Search results to yaml file so API is not hit every test."
task :write do
write_yaml :tweets => 'Obama', :file => 'obama'
write_yaml :tweets => 'twitter search', :file => 'twitter_search'
write_yaml :tweets => {:q => 'twitter search'}, :file => 'twitter_search_and'
write_yaml :tweets => {:q => '"happy hour"'}, :file => 'happy_hour_exact'
write_yaml :tweets => {:q => 'obama OR hillary'}, :file => 'obama_or_hillary'
write_yaml :tweets => {:q => 'beer -root'}, :file => 'beer_minus_root'
write_yaml :tweets => {:q => '#haiku'}, :file => 'hashtag_haiku'
write_yaml :tweets => {:q => 'from:alexiskold'}, :file => 'from_alexiskold'
write_yaml :tweets => {:q => 'to:techcrunch'}, :file => 'to_techcrunch'
write_yaml :tweets => {:q => '@mashable'}, :file => 'reference_mashable'
write_yaml :tweets => {:q => '"happy hour" near:"san francisco"'}, :file => 'happy_hour_near_sf'
write_yaml :tweets => {:q => 'near:NYC within:15mi'}, :file => 'within_15mi_nyc'
write_yaml :tweets => {:q => 'superhero since:2008-05-01'}, :file => 'superhero_since'
write_yaml :tweets => {:q => 'ftw until:2008-05-03'}, :file => 'ftw_until'
write_yaml :tweets => {:q => 'movie -scary :)'}, :file => 'movie_positive_tude'
write_yaml :tweets => {:q => 'flight :('}, :file => 'flight_negative_tude'
write_yaml :tweets => {:q => 'traffic ?'}, :file => 'traffic_question'
write_yaml :tweets => {:q => 'hilarious filter:links'}, :file => 'hilarious_links'
write_yaml :tweets => {:q => 'congratulations', :lang => 'en'}, :file => 'english'
write_yaml :tweets => {:q => 'با', :lang => 'ar'}, :file => 'arabic'
end
end

def write_yaml(opts = {})
@client = TwitterSearch::Client.new 'twitter-search'
tweets = @client.query(opts[:tweets])
File.open(File.join(File.dirname(__FILE__), 'test', 'yaml', "#{opts[:file]}.yaml"), 'w+') do |file|
file.puts tweets.to_yaml
end
end
Loading

0 comments on commit 520eb1c

Please sign in to comment.