secobarbital-twitter 0.9.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/History +271 -0
  2. data/License +20 -0
  3. data/Notes +33 -0
  4. data/README.rdoc +19 -0
  5. data/Rakefile +39 -0
  6. data/VERSION.yml +5 -0
  7. data/examples/connect.rb +30 -0
  8. data/examples/friendship_existance.rb +13 -0
  9. data/examples/helpers/config_store.rb +38 -0
  10. data/examples/httpauth.rb +11 -0
  11. data/examples/ids.rb +13 -0
  12. data/examples/lists.rb +11 -0
  13. data/examples/oauth.rb +27 -0
  14. data/examples/search.rb +15 -0
  15. data/examples/timeline.rb +19 -0
  16. data/examples/tumblr.rb +9 -0
  17. data/examples/unauthorized.rb +16 -0
  18. data/examples/update.rb +11 -0
  19. data/examples/user.rb +5 -0
  20. data/lib/twitter/base.rb +371 -0
  21. data/lib/twitter/httpauth.rb +39 -0
  22. data/lib/twitter/local_trends.rb +15 -0
  23. data/lib/twitter/oauth.rb +58 -0
  24. data/lib/twitter/request.rb +71 -0
  25. data/lib/twitter/search.rb +157 -0
  26. data/lib/twitter/trends.rb +41 -0
  27. data/lib/twitter.rb +148 -0
  28. data/test/fixtures/blocking.json +1632 -0
  29. data/test/fixtures/firehose.json +1 -0
  30. data/test/fixtures/follower_ids.json +1 -0
  31. data/test/fixtures/followers.json +1 -0
  32. data/test/fixtures/friend_ids.json +1 -0
  33. data/test/fixtures/friends_timeline.json +1 -0
  34. data/test/fixtures/friendship.json +1 -0
  35. data/test/fixtures/home_timeline.json +1 -0
  36. data/test/fixtures/ids.json +1 -0
  37. data/test/fixtures/list.json +1 -0
  38. data/test/fixtures/list_statuses.json +1 -0
  39. data/test/fixtures/list_statuses_1_1.json +1 -0
  40. data/test/fixtures/list_statuses_2_1.json +1 -0
  41. data/test/fixtures/list_subscriptions.json +1 -0
  42. data/test/fixtures/list_users.json +1 -0
  43. data/test/fixtures/lists.json +1 -0
  44. data/test/fixtures/memberships.json +1 -0
  45. data/test/fixtures/mentions.json +1 -0
  46. data/test/fixtures/not_found.json +1 -0
  47. data/test/fixtures/people_search.json +39 -0
  48. data/test/fixtures/rate_limit_exceeded.json +1 -0
  49. data/test/fixtures/retweet.json +1 -0
  50. data/test/fixtures/retweeted_by_me.json +1 -0
  51. data/test/fixtures/retweeted_to_me.json +1 -0
  52. data/test/fixtures/retweeters_of_tweet.json +166 -0
  53. data/test/fixtures/retweets.json +1 -0
  54. data/test/fixtures/retweets_of_me.json +1 -0
  55. data/test/fixtures/sample-image.png +0 -0
  56. data/test/fixtures/search.json +1 -0
  57. data/test/fixtures/search_from_jnunemaker.json +1 -0
  58. data/test/fixtures/status.json +1 -0
  59. data/test/fixtures/status_show.json +1 -0
  60. data/test/fixtures/trends_available.json +253 -0
  61. data/test/fixtures/trends_current.json +1 -0
  62. data/test/fixtures/trends_current_exclude.json +1 -0
  63. data/test/fixtures/trends_daily.json +1925 -0
  64. data/test/fixtures/trends_daily_date.json +1 -0
  65. data/test/fixtures/trends_daily_exclude.json +1 -0
  66. data/test/fixtures/trends_location.json +57 -0
  67. data/test/fixtures/trends_weekly.json +1 -0
  68. data/test/fixtures/trends_weekly_date.json +1 -0
  69. data/test/fixtures/trends_weekly_exclude.json +1 -0
  70. data/test/fixtures/unauthorized.json +1 -0
  71. data/test/fixtures/update_profile_background_image.json +1 -0
  72. data/test/fixtures/update_profile_image.json +1 -0
  73. data/test/fixtures/user.json +1 -0
  74. data/test/fixtures/user_timeline.json +710 -0
  75. data/test/fixtures/users.json +1 -0
  76. data/test/test_helper.rb +46 -0
  77. data/test/twitter/base_test.rb +364 -0
  78. data/test/twitter/httpauth_test.rb +76 -0
  79. data/test/twitter/oauth_test.rb +108 -0
  80. data/test/twitter/request_test.rb +217 -0
  81. data/test/twitter/search_test.rb +208 -0
  82. data/test/twitter/trends_test.rb +112 -0
  83. data/test/twitter_test.rb +106 -0
  84. metadata +280 -0
@@ -0,0 +1,157 @@
1
+ module Twitter
2
+ class Search
3
+ include HTTParty
4
+ include Enumerable
5
+ base_uri "api.twitter.com/#{API_VERSION}/search"
6
+ format :json
7
+
8
+ attr_reader :result, :query
9
+
10
+ def initialize(q=nil, options={})
11
+ @options = options
12
+ clear
13
+ containing(q) if q && q.strip != ""
14
+ end
15
+
16
+ def user_agent
17
+ @options[:user_agent] || "Ruby Twitter Gem"
18
+ end
19
+
20
+ def from(user, exclude=false)
21
+ @query[:q] << "#{exclude ? "-" : ""}from:#{user}"
22
+ self
23
+ end
24
+
25
+ def to(user, exclude=false)
26
+ @query[:q] << "#{exclude ? "-" : ""}to:#{user}"
27
+ self
28
+ end
29
+
30
+ def referencing(user, exclude=false)
31
+ @query[:q] << "#{exclude ? "-" : ""}@#{user}"
32
+ self
33
+ end
34
+ alias :references :referencing
35
+ alias :ref :referencing
36
+
37
+ def containing(word, exclude=false)
38
+ @query[:q] << "#{exclude ? "-" : ""}#{word}"
39
+ self
40
+ end
41
+ alias :contains :containing
42
+
43
+ # adds filtering based on hash tag ie: #twitter
44
+ def hashed(tag, exclude=false)
45
+ @query[:q] << "#{exclude ? "-" : ""}\##{tag}"
46
+ self
47
+ end
48
+
49
+ # Search for a phrase instead of a group of words
50
+ def phrase(phrase)
51
+ @query[:phrase] = phrase
52
+ self
53
+ end
54
+
55
+ # lang must be ISO 639-1 code ie: en, fr, de, ja, etc.
56
+ #
57
+ # when I tried en it limited my results a lot and took
58
+ # out several tweets that were english so i'd avoid
59
+ # this unless you really want it
60
+ def lang(lang)
61
+ @query[:lang] = lang
62
+ self
63
+ end
64
+
65
+ # popular|recent
66
+ def result_type(result_type)
67
+ @query[:result_type] = result_type
68
+ self
69
+ end
70
+
71
+ # Limits the number of results per page
72
+ def per_page(num)
73
+ @query[:rpp] = num
74
+ self
75
+ end
76
+
77
+ # Which page of results to fetch
78
+ def page(num)
79
+ @query[:page] = num
80
+ self
81
+ end
82
+
83
+ # Only searches tweets since a given id.
84
+ # Recommended to use this when possible.
85
+ def since(since_id)
86
+ @query[:since_id] = since_id
87
+ self
88
+ end
89
+
90
+ # From the advanced search form, not documented in the API
91
+ # Format YYYY-MM-DD
92
+ def since_date(since_date)
93
+ @query[:since] = since_date
94
+ self
95
+ end
96
+
97
+ # From the advanced search form, not documented in the API
98
+ # Format YYYY-MM-DD
99
+ def until_date(until_date)
100
+ @query[:until] = until_date
101
+ self
102
+ end
103
+
104
+ # Ranges like 25km and 50mi work.
105
+ def geocode(lat, long, range)
106
+ @query[:geocode] = [lat, long, range].join(",")
107
+ self
108
+ end
109
+
110
+ def max(id)
111
+ @query[:max_id] = id
112
+ self
113
+ end
114
+
115
+ # Clears all the query filters to make a new search
116
+ def clear
117
+ @fetch = nil
118
+ @query = {}
119
+ @query[:q] = []
120
+ self
121
+ end
122
+
123
+ def fetch(force=false)
124
+ if @fetch.nil? || force
125
+ query = @query.dup
126
+ query[:q] = query[:q].join(" ")
127
+ perform_get(query)
128
+ end
129
+
130
+ @fetch
131
+ end
132
+
133
+ def each
134
+ fetch()["results"].each{|r| yield r}
135
+ end
136
+
137
+ def next_page?
138
+ !!fetch()["next_page"]
139
+ end
140
+
141
+ def fetch_next_page
142
+ if next_page?
143
+ s = Search.new(nil, :user_agent => user_agent)
144
+ s.perform_get(fetch()["next_page"][1..-1])
145
+ s
146
+ end
147
+ end
148
+
149
+ protected
150
+
151
+ def perform_get(query)
152
+ response = self.class.get("http://api.twitter.com/#{API_VERSION}/search.json", :query => query, :format => :json, :headers => {"User-Agent" => user_agent})
153
+ @fetch = Twitter.mash(response)
154
+ end
155
+
156
+ end
157
+ end
@@ -0,0 +1,41 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), "local_trends")
2
+
3
+ module Twitter
4
+ class Trends
5
+ include HTTParty
6
+ base_uri "search.twitter.com/trends"
7
+ format :json
8
+
9
+ # :exclude => 'hashtags' to exclude hashtags
10
+ def self.current(options={})
11
+ mashup(get("/current.json", :query => options))
12
+ end
13
+
14
+ # :exclude => 'hashtags' to exclude hashtags
15
+ # :date => yyyy-mm-dd for specific date
16
+ def self.daily(options={})
17
+ mashup(get("/daily.json", :query => options))
18
+ end
19
+
20
+ # :exclude => 'hashtags' to exclude hashtags
21
+ # :date => yyyy-mm-dd for specific date
22
+ def self.weekly(options={})
23
+ mashup(get("/weekly.json", :query => options))
24
+ end
25
+
26
+ def self.available(query={})
27
+ LocalTrends.available(query)
28
+ end
29
+
30
+ def self.for_location(woeid)
31
+ LocalTrends.for_location(woeid)
32
+ end
33
+
34
+ private
35
+
36
+ def self.mashup(response)
37
+ response["trends"].values.flatten.map{|t| Twitter.mash(t)}
38
+ end
39
+
40
+ end
41
+ end
data/lib/twitter.rb ADDED
@@ -0,0 +1,148 @@
1
+ require "forwardable"
2
+ require "oauth"
3
+ require "hashie"
4
+ require "httparty"
5
+ require "json"
6
+
7
+ module Twitter
8
+ include HTTParty
9
+ API_VERSION = "1".freeze
10
+ base_uri "api.twitter.com/#{API_VERSION}"
11
+ format :json
12
+
13
+ class TwitterError < StandardError
14
+ attr_reader :data
15
+
16
+ def initialize(data)
17
+ @data = data
18
+ super
19
+ end
20
+ end
21
+
22
+ class RateLimitExceeded < TwitterError; end
23
+ class Unauthorized < TwitterError; end
24
+ class General < TwitterError; end
25
+
26
+ class Unavailable < StandardError; end
27
+ class InformTwitter < StandardError; end
28
+ class NotFound < StandardError; end
29
+
30
+ def self.firehose
31
+ perform_get("/statuses/public_timeline.json")
32
+ end
33
+
34
+ def self.user(id)
35
+ perform_get("/users/show/#{id}.json")
36
+ end
37
+
38
+ def self.status(id)
39
+ perform_get("/statuses/show/#{id}.json")
40
+ end
41
+
42
+ def self.friend_ids(id)
43
+ perform_get("/friends/ids/#{id}.json")
44
+ end
45
+
46
+ def self.follower_ids(id)
47
+ perform_get("/followers/ids/#{id}.json")
48
+ end
49
+
50
+ def self.timeline(id, options={})
51
+ perform_get("/statuses/user_timeline/#{id}.json", :query => options)
52
+ end
53
+
54
+ # :per_page = max number of statues to get at once
55
+ # :page = which page of tweets you wish to get
56
+ def self.list_timeline(list_owner_username, slug, query = {})
57
+ perform_get("/#{list_owner_username}/lists/#{slug}/statuses.json", :query => query)
58
+ end
59
+
60
+ private
61
+
62
+ def self.perform_get(uri, options = {})
63
+ make_friendly(get(uri, options))
64
+ end
65
+
66
+ def self.make_friendly(response)
67
+ raise_errors(response)
68
+ data = parse(response)
69
+ # Don't mash arrays of integers
70
+ if data && data.first.is_a?(Integer)
71
+ data
72
+ else
73
+ mash(data)
74
+ end
75
+ end
76
+
77
+ def self.raise_errors(response)
78
+ case response.code.to_i
79
+ when 400
80
+ data = parse(response)
81
+ raise RateLimitExceeded.new(data), "(#{response.code}): #{response.message} - #{data['error'] if data}"
82
+ when 401
83
+ data = parse(response)
84
+ raise Unauthorized.new(data), "(#{response.code}): #{response.message} - #{data['error'] if data}"
85
+ when 403
86
+ data = parse(response)
87
+ raise General.new(data), "(#{response.code}): #{response.message} - #{data['error'] if data}"
88
+ when 404
89
+ raise NotFound, "(#{response.code}): #{response.message}"
90
+ when 500
91
+ raise InformTwitter, "Twitter had an internal error. Please let them know in the group. (#{response.code}): #{response.message}"
92
+ when 502..503
93
+ raise Unavailable, "(#{response.code}): #{response.message}"
94
+ end
95
+ end
96
+
97
+ def self.parse(response)
98
+ return '' if response.body == ''
99
+ JSON.parse(response.body)
100
+ end
101
+
102
+ def self.mash(obj)
103
+ if obj.is_a?(Array)
104
+ obj.map{|item| make_mash_with_consistent_hash(item)}
105
+ elsif obj.is_a?(Hash)
106
+ make_mash_with_consistent_hash(obj)
107
+ else
108
+ obj
109
+ end
110
+ end
111
+
112
+ # Lame workaround for the fact that mash doesn't hash correctly
113
+ def self.make_mash_with_consistent_hash(obj)
114
+ m = Hashie::Mash.new(obj)
115
+ def m.hash
116
+ inspect.hash
117
+ end
118
+ return m
119
+ end
120
+
121
+ end
122
+
123
+ module Hashie
124
+ class Mash
125
+
126
+ # Converts all of the keys to strings, optionally formatting key name
127
+ def rubyify_keys!
128
+ keys.each{|k|
129
+ v = delete(k)
130
+ new_key = k.to_s.underscore
131
+ self[new_key] = v
132
+ v.rubyify_keys! if v.is_a?(Hash)
133
+ v.each{|p| p.rubyify_keys! if p.is_a?(Hash)} if v.is_a?(Array)
134
+ }
135
+ self
136
+ end
137
+
138
+ end
139
+ end
140
+
141
+ directory = File.expand_path(File.dirname(__FILE__))
142
+
143
+ require File.join(directory, "twitter", "oauth")
144
+ require File.join(directory, "twitter", "httpauth")
145
+ require File.join(directory, "twitter", "request")
146
+ require File.join(directory, "twitter", "base")
147
+ require File.join(directory, "twitter", "search")
148
+ require File.join(directory, "twitter", "trends")