look-twitter-search 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.markdown ADDED
@@ -0,0 +1,79 @@
1
+ # A Twitter Search client for Ruby.
2
+
3
+ Access the Twitter Search API from your Ruby code.
4
+
5
+ ## Usage
6
+
7
+ Install the gem.
8
+
9
+ sudo gem install dancroak-twitter-search -s http://gems.github.com
10
+
11
+ Require the gem.
12
+
13
+ require 'twitter_search'
14
+
15
+ 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.
16
+
17
+ @client = TwitterSearch::Client.new 'politweets'
18
+
19
+ Request tweets by calling the query method of your client. It takes either a String or a Hash of arguments.
20
+
21
+ @tweets = @client.query 'twitter search'
22
+
23
+ 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:
24
+
25
+ @tweets = @client.query :q => 'twitter search'
26
+
27
+ Use the Twitter Search API's query operators with the :q key to access a variety of behavior.
28
+
29
+ ## Search Operators
30
+
31
+ The following operator examples find tweets...
32
+
33
+ * <a href="http://search.twitter.com/search?q=twitter+search">:q => 'twitter search'</a> - containing both "twitter" and "search". This is the default operator.
34
+ * <a href="http://search.twitter.com/search?q=%22happy+hour%22">:q => '<b>"</b>happy hour<b>"</b>'</a> - containing the exact phrase "happy hour".
35
+ * <a href="http://search.twitter.com/search?q=obama+OR+hillary">:q => 'obama <b>OR</b> hillary'</a> - containing either "obama" or "hillary" (or both).
36
+ * <a href="http://search.twitter.com/search?q=beer+-root">:q => 'beer <b>-</b>root'</a> - containing "beer" but not "root".
37
+ * <a href="http://search.twitter.com/search?q=%23haiku">:q => '<b>#</b>haiku</a>' - containing the hashtag "haiku".
38
+ * <a href="http://search.twitter.com/search?q=from%3Aalexiskold">:q => '<b>from:</b>alexiskold'</a> - sent from person "alexiskold".
39
+ * <a href="http://search.twitter.com/search?q=to%3Atechcrunch">:q => '<b>to:</b>techcrunch</a>' - sent to person "techcrunch".
40
+ * <a href="http://search.twitter.com/search?q=%40mashable">:q => '<b>@</b>mashable</a>' - referencing person "mashable".
41
+ * <a href="http://search.twitter.com/search?q=superhero+since%3A2008-05-01">:q => 'superhero <b>since:</b>2008-05-01'</a> - containing "superhero" and sent since date "2008-05-01" (year-month-day).
42
+ * <a href="http://search.twitter.com/search?q=ftw+until%3A2008-05-03">:q => 'ftw <b>until:</b>2008-05-03'</a> - containing "ftw" and sent up to date "2008-05-03".
43
+ * <a href="http://search.twitter.com/search?q=movie+-scary+%3A%29">:q => 'movie -scary <b>:)</b>'</a> - containing "movie", but not "scary", and with a positive attitude.
44
+ * <a href="http://search.twitter.com/search?q=flight+%3A%28">:q => 'flight <b>:(</b>'</a> - containing "flight" and with a negative attitude.
45
+ * <a href="http://search.twitter.com/search?q=traffic+%3F">:q => 'traffic <b>?</b>'</a> - containing "traffic" and asking a question.
46
+ * <a href="http://search.twitter.com/search?q=hilarious+filter%3Alinks">:q => 'hilarious <b>filter:links</b>'</a> - containing "hilarious" and linking to URLs.
47
+
48
+ ### Foreign Languages
49
+
50
+ 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:
51
+
52
+ @tweets = @client.query :q => 'programmé', :lang => 'fr'
53
+
54
+ ### Pagination
55
+
56
+ Alter the number of Tweets returned per page with the :rpp key. Stick with 10, 15, 20, 25, 30, or 50.
57
+
58
+ @tweets = @client.query :q => 'Boston Celtics', :rpp => '30'
59
+
60
+ ## Gotchas
61
+
62
+ * Searches are case-insenstive.
63
+ * 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, and use the :geocode key in your request using the pattern lat,lngmi or lat,lngkm:
64
+
65
+ @tweets = @client.query :q => 'Pearl Jam', :geocode => '43.4411,-70.9846mi'
66
+
67
+ * Searching for a positive attitude :) returns tweets containing the text :), =), :D, and :-)
68
+
69
+ ## Authors
70
+
71
+ Written by Dustin Sallings (dustin@spy.net), forked by Dan Croak (dcroak@thoughtbot.com).
72
+
73
+ ## Resources
74
+
75
+ * [Official Twitter Search API](http://search.twitter.com/api)
76
+
77
+ ## License
78
+
79
+ MIT License, same terms as Ruby.
data/Rakefile ADDED
@@ -0,0 +1,70 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ test_files_pattern = 'test/twitter_search_test.rb'
5
+ Rake::TestTask.new do |t|
6
+ t.libs << 'lib'
7
+ t.pattern = test_files_pattern
8
+ t.verbose = false
9
+ end
10
+
11
+ desc "Run the test suite"
12
+ task :default => :test
13
+
14
+ gem_spec = Gem::Specification.new do |gem_spec|
15
+ gem_spec.name = "twitter-search"
16
+ gem_spec.version = "0.5.2"
17
+ gem_spec.summary = "Ruby client for Twitter Search."
18
+ gem_spec.email = "dcroak@thoughtbot.com"
19
+ gem_spec.homepage = "http://github.com/dancroak/twitter-search"
20
+ gem_spec.description = "Ruby client for Twitter Search."
21
+ gem_spec.authors = ["Dustin Sallings", "Dan Croak"]
22
+ gem_spec.files = FileList["[A-Z]*", "{generators,lib,shoulda_macros,rails}/**/*"]
23
+ gem_spec.add_dependency('json', '>= 1.1.2')
24
+ end
25
+
26
+ desc "Generate a gemspec file"
27
+ task :gemspec do
28
+ File.open("#{gem_spec.name}.gemspec", 'w') do |f|
29
+ f.write gem_spec.to_yaml
30
+ end
31
+ end
32
+
33
+ require File.expand_path('lib/twitter_search', File.dirname(__FILE__))
34
+ require 'rubygems'
35
+ require 'yaml'
36
+
37
+ namespace :yaml do
38
+ desc "Write Twitter Search results to yaml file so API is not hit every test."
39
+ task :write do
40
+ write_yaml :tweets => 'Obama', :file => 'obama'
41
+ write_yaml :tweets => 'twitter search', :file => 'twitter_search'
42
+ write_yaml :tweets => {:q => 'twitter search'}, :file => 'twitter_search_and'
43
+ write_yaml :tweets => {:q => '"happy hour"'}, :file => 'happy_hour_exact'
44
+ write_yaml :tweets => {:q => 'obama OR hillary'}, :file => 'obama_or_hillary'
45
+ write_yaml :tweets => {:q => 'beer -root'}, :file => 'beer_minus_root'
46
+ write_yaml :tweets => {:q => '#haiku'}, :file => 'hashtag_haiku'
47
+ write_yaml :tweets => {:q => 'from:alexiskold'}, :file => 'from_alexiskold'
48
+ write_yaml :tweets => {:q => 'to:techcrunch'}, :file => 'to_techcrunch'
49
+ write_yaml :tweets => {:q => '@mashable'}, :file => 'reference_mashable'
50
+ write_yaml :tweets => {:q => '"happy hour" near:"san francisco"'}, :file => 'happy_hour_near_sf'
51
+ write_yaml :tweets => {:q => 'near:NYC within:15mi'}, :file => 'within_15mi_nyc'
52
+ write_yaml :tweets => {:q => 'superhero since:2008-05-01'}, :file => 'superhero_since'
53
+ write_yaml :tweets => {:q => 'ftw until:2008-05-03'}, :file => 'ftw_until'
54
+ write_yaml :tweets => {:q => 'movie -scary :)'}, :file => 'movie_positive_tude'
55
+ write_yaml :tweets => {:q => 'flight :('}, :file => 'flight_negative_tude'
56
+ write_yaml :tweets => {:q => 'traffic ?'}, :file => 'traffic_question'
57
+ write_yaml :tweets => {:q => 'hilarious filter:links'}, :file => 'hilarious_links'
58
+ write_yaml :tweets => {:q => 'congratulations', :lang => 'en'}, :file => 'english'
59
+ write_yaml :tweets => {:q => 'با', :lang => 'ar'}, :file => 'arabic'
60
+ write_yaml :tweets => {:q => 'Boston Celtics', :rpp => '30'}, :file => 'results_per_page'
61
+ end
62
+ end
63
+
64
+ def write_yaml(opts = {})
65
+ @client = TwitterSearch::Client.new 'twitter-search'
66
+ tweets = @client.query(opts[:tweets])
67
+ File.open(File.join(File.dirname(__FILE__), 'test', 'yaml', "#{opts[:file]}.yaml"), 'w+') do |file|
68
+ file.puts tweets.to_yaml
69
+ end
70
+ end
data/TODO.markdown ADDED
@@ -0,0 +1,7 @@
1
+ Add tests for:
2
+
3
+ * since_id: returns tweets with status ids greater than the given id.
4
+ * 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.
5
+ * 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".
6
+ * 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
7
+
@@ -0,0 +1,94 @@
1
+ require 'rubygems'
2
+ require 'net/http'
3
+ require 'json'
4
+ require 'cgi'
5
+
6
+ module TwitterSearch
7
+
8
+ class Tweet
9
+ VARS = [:text, :from_user, :to_user, :to_user_id, :id, :iso_language_code, :from_user_id, :created_at, :profile_image_url, :source ]
10
+ attr_reader *VARS
11
+ attr_reader :language
12
+
13
+ def initialize(opts)
14
+ @language = opts['iso_language_code']
15
+ VARS.each { |each| instance_variable_set "@#{each}", opts[each.to_s] }
16
+ end
17
+ end
18
+
19
+ class Tweets
20
+ VARS = [:since_id, :max_id, :results_per_page, :page, :query, :next_page]
21
+ attr_reader *VARS
22
+
23
+ include Enumerable
24
+
25
+ def initialize(opts)
26
+ @results = opts['results'].collect { |each| Tweet.new(each) }
27
+ VARS.each { |each| instance_variable_set "@#{each}", opts[each.to_s] }
28
+ end
29
+
30
+ def each(&block)
31
+ @results.each(&block)
32
+ end
33
+
34
+ def size
35
+ @results.size
36
+ end
37
+
38
+ def [](index)
39
+ @results[index]
40
+ end
41
+ end
42
+
43
+ class Client
44
+ TWITTER_API_URL = 'http://search.twitter.com/search.json'
45
+ TWITTER_API_DEFAULT_TIMEOUT = 5
46
+
47
+ attr_accessor :agent
48
+
49
+ def initialize(agent = 'twitter-search')
50
+ @agent = agent
51
+ end
52
+
53
+ def headers
54
+ { "Content-Type" => 'application/json',
55
+ "User-Agent" => @agent }
56
+ end
57
+
58
+ def timeout
59
+ TWITTER_API_DEFAULT_TIMEOUT
60
+ end
61
+
62
+ def query(opts = {})
63
+ url = URI.parse(TWITTER_API_URL)
64
+ url.query = sanitize_query(opts)
65
+
66
+ req = Net::HTTP::Get.new(url.path)
67
+ http = Net::HTTP.new(url.host, url.port)
68
+ http.read_timeout = timeout
69
+
70
+ json = http.start { |http|
71
+ http.get("#{url.path}?#{url.query}", headers)
72
+ }.body
73
+ Tweets.new JSON.parse(json)
74
+ end
75
+
76
+ private
77
+
78
+ def sanitize_query(opts)
79
+ if opts.is_a? String
80
+ "q=#{CGI.escape(opts)}"
81
+ elsif opts.is_a? Hash
82
+ "#{sanitize_query_hash(opts)}"
83
+ end
84
+ end
85
+
86
+ def sanitize_query_hash(query_hash)
87
+ query_hash.collect { |key, value|
88
+ "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}"
89
+ }.join('&')
90
+ end
91
+
92
+ end
93
+
94
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: look-twitter-search
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.3
5
+ platform: ruby
6
+ authors:
7
+ - Dustin Sallings
8
+ - Dan Croak
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-02-03 21:00:00 -08:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: json
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 1.1.2
25
+ version:
26
+ description: Ruby client for Twitter Search.
27
+ email: dcroak@thoughtbot.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files: []
33
+
34
+ files:
35
+ - Rakefile
36
+ - README.markdown
37
+ - TODO.markdown
38
+ - VERSION.yml
39
+ - lib/twitter_search.rb
40
+ has_rdoc: false
41
+ homepage: http://github.com/dancroak/twitter-search
42
+ post_install_message:
43
+ rdoc_options: []
44
+
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.2.0
63
+ signing_key:
64
+ specification_version: 2
65
+ summary: Ruby client for Twitter Search.
66
+ test_files: []
67
+