secobarbital-twitter 0.9.2.1

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.
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")