tweedle 0.1.0

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/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rdoc_options ADDED
@@ -0,0 +1,16 @@
1
+ --- !ruby/object:RDoc::Options
2
+ encoding: UTF-8
3
+ static_path: []
4
+ rdoc_include:
5
+ - .
6
+ charset: UTF-8
7
+ exclude: ["test"]
8
+ hyperlink_all: false
9
+ line_numbers: true
10
+ main_page: README.rdoc
11
+ markup: tomdoc
12
+ show_hash: false
13
+ tab_width: 8
14
+ title: Tweedle
15
+ visibility: :protected
16
+ webcvs:
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - ruby-head
6
+ - jruby-19mode
7
+ - rbx-19mode
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source :rubygems
2
+
3
+ group :development do
4
+ gem "rake"
5
+ end
6
+
7
+ group :test do
8
+ gem "minitest", "~> 2.12.1"
9
+ gem "mocha", "~> 0.11.2"
10
+ gem "simplecov", "~> 0.6.2"
11
+ gem "fakeweb", "~> 1.3.0"
12
+ end
13
+
14
+ # Specify your gem's dependencies in tweedle.gemspec
15
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Tobias Svensson
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,137 @@
1
+ = Tweedle
2
+
3
+ Lightweight wrapper for the Twitter Streaming API.
4
+
5
+ ---
6
+
7
+ Tweedle is a lightweight wrapper for the
8
+ {Twitter Streaming API}[https://dev.twitter.com/docs/streaming-api],
9
+ written out of the need for a library that does not depend on
10
+ {EventMachine}[http://rubyeventmachine.com/].
11
+
12
+ The library currently only supports the regular
13
+ {Streaming API Methods}[https://dev.twitter.com/docs/streaming-api/methods].
14
+ {User Streams}[https://dev.twitter.com/docs/streaming-api/user-streams] and
15
+ {Site Streams}[https://dev.twitter.com/docs/streaming-api/site-streams] are
16
+ currently not implemented.
17
+
18
+ == Installation
19
+
20
+ The best way to install Tweedle is with RubyGems:
21
+
22
+ $ [sudo] gem install tweedle
23
+
24
+ Or add it to your Gemfile:
25
+
26
+ gem 'foo'
27
+
28
+ And then execute:
29
+
30
+ $ bundle install
31
+
32
+ If you're installing from source, you can use Bundler to pick up all the gems,
33
+ including those required for running the tests and creating coverage reports:
34
+
35
+ $ bundle install
36
+
37
+ Consult the online documentation for more information on
38
+ {Bundler}[http://gembundler.com/]
39
+
40
+ == Dependencies
41
+
42
+ The goal is to keep Tweedle's dependencies to a minimum. However, in
43
+ order to keep the source as simple as possible, it requires the
44
+ following gems:
45
+
46
+ * {OAuth}[http://github.com/pelle/oauth] to authenticate with Twitter
47
+ and sign the requests.
48
+ * {multi_json}[http://github.com/intridea/multi_json] to parse the
49
+ response bodies.
50
+
51
+ == Getting started
52
+
53
+ First, setup the library to use the desired OAuth credentials:
54
+
55
+ Tweedle.configure do |config|
56
+ config.consumer_key = "the_consumer_key"
57
+ config.consumer_secret = "the_consumer_secret"
58
+ config.oauth_token = "the_oauth_token"
59
+ config.oauth_secret = "the_oauth_secret"
60
+ end
61
+
62
+ Then, create a client:
63
+
64
+ client = Tweedle.new
65
+
66
+ Try things out by streaming Twitter's sample stream:
67
+
68
+ client.statuses.sample do |tweet|
69
+ next unless text = tweet[:text]
70
+ puts "#{tweet[:user][:screen_name]}: #{text}"
71
+ end
72
+
73
+ HTTP parameters are supported, too:
74
+
75
+ client.statuses.sample(stall_warnings: true, count: 1000) do |tweet|
76
+ next unless text = tweet[:text]
77
+ puts "#{tweet[:user][:screen_name]}: #{text}"
78
+ end
79
+
80
+ And the wrapper for the filter stream uses POST requsts, as
81
+ recommended by Twitter:
82
+
83
+ predicates = {
84
+ locations: [-122.75, 36.8, -121.75, 37.8, -74,40, -73,41],
85
+ track: ["ruby", "tweedle"]
86
+ }
87
+
88
+ client.statuses.filter(stall_warnings: true, predicates: predicates) do |tweet|
89
+ next unless text = tweet[:text]
90
+ puts "#{tweet[:user][:screen_name]}: #{text}"
91
+ end
92
+
93
+ The full API documentation is available
94
+ {online}[http://rdoc.info/github/tobiassvn/tweedle/master/frames].
95
+
96
+ == Contributing
97
+
98
+ If you'd like to contribute to Tweedle, start by forking the repo on GitHub:
99
+
100
+ {http://github.com/tobiassvn/tweedle}[http://github.com/tobiassvn/tweedle]
101
+
102
+ To get all of the dependencies, install the gem first. The best way to
103
+ getyour changes merged back into core is as follows:
104
+
105
+ * Clone down your fork.
106
+ * Create a thoughtfully named topic branch to contain your change.
107
+ * Hack away.
108
+ * Add tests and make sure everything still passes by running rake.
109
+ * If you are adding new functionality, document it in the README.
110
+ * If you add new attributes, classes, constants or methods, document
111
+ in the {TomDoc}[http://tomdoc.org/] format.
112
+ * Do not change the version number, I will do that on my end.
113
+ * If necessary, rebase your commits into logical chunks, without errors
114
+ * Push the branch up to GitHub
115
+ * Send a pull request to the tobiassvn/tweedle project.
116
+
117
+ == License
118
+
119
+ Copyright (c) 2012 Tobias Svensson.
120
+
121
+ Permission is hereby granted, free of charge, to any person obtaining a copy
122
+ of this software and associated documentation files (the "Software"), to deal
123
+ in the Software without restriction, including without limitation the rights
124
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
125
+ copies of the Software, and to permit persons to whom the Software is
126
+ furnished to do so, subject to the following conditions:
127
+
128
+ The above copyright notice and this permission notice shall be included in
129
+ all copies or substantial portions of the Software.
130
+
131
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
132
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
133
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
134
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
135
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
136
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
137
+ THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.pattern = "test/test_*.rb"
7
+ end
8
+
9
+ task :default => :test
@@ -0,0 +1,18 @@
1
+ require "tweedle"
2
+
3
+ Tweedle.configure do |config|
4
+ config.consumer_key = "the_consumer_key"
5
+ config.consumer_secret = "the_consumer_secret"
6
+ config.oauth_token = "the_oauth_token"
7
+ config.oauth_secret = "the_oauth_secret"
8
+ end
9
+
10
+ predicates = {
11
+ locations: [-122.75, 36.8, -121.75, 37.8, -74,40, -73,41],
12
+ track: ["ruby", "tweedle"]
13
+ }
14
+
15
+ Tweedle.new.statuses.filter(predicates: predicates) do |tweet|
16
+ next unless text = tweet[:text]
17
+ puts "#{tweet[:user][:screen_name]}: #{text}"
18
+ end
@@ -0,0 +1,13 @@
1
+ require "tweedle"
2
+
3
+ Tweedle.configure do |config|
4
+ config.consumer_key = "the_consumer_key"
5
+ config.consumer_secret = "the_consumer_secret"
6
+ config.oauth_token = "the_oauth_token"
7
+ config.oauth_secret = "the_oauth_secret"
8
+ end
9
+
10
+ Tweedle.new.statuses.sample do |tweet|
11
+ next unless text = tweet[:text]
12
+ puts "#{tweet[:user][:screen_name]}: #{text}"
13
+ end
@@ -0,0 +1,268 @@
1
+ module Tweedle
2
+ # Public: The Tweedle::Client class wraps methods for accessing
3
+ # sections of the Twitter streaming API and handles all client ->
4
+ # server requests.
5
+ class Client
6
+ # Public: The configuration used by the Tweedle::Client instance.
7
+ attr_reader :config
8
+
9
+ # Initializes a new Tweedle::Client.
10
+ #
11
+ # config - Options object for the Tweedle client. By default uses
12
+ # the global Tweedle configuarion (default: Tweedle.config).
13
+ #
14
+ # Examples
15
+ #
16
+ # Tweedle::Client.new
17
+ # # => Tweedle::Client
18
+ #
19
+ # Tweedle::Client.new(config_object)
20
+ # # => Tweedle::Client
21
+ #
22
+ # Returns a Tweedle::Client instance.
23
+ def initialize(config = Tweedle.config)
24
+ @config = config
25
+ end
26
+
27
+ # Returns a new Tweedle::Statuses instance associated with the
28
+ # client.
29
+ #
30
+ # Examples
31
+ #
32
+ # client = Tweedle.new
33
+ # client.statuses
34
+ # # => Tweedle::Statuses
35
+ #
36
+ # Returns a Tweedle::Statuses instance.
37
+ def statuses
38
+ Tweedle::Statuses.new(self)
39
+ end
40
+
41
+ # Internal: Sends a GET request to the given stream.
42
+ #
43
+ # uri - A String containing the request URI.
44
+ # block - Optional block to yield the response body to.
45
+ # params - Optional request parameters (default: empty Hash)
46
+ #
47
+ # Examples
48
+ #
49
+ # get(URI.parse("http://www.google.com/") do |body|
50
+ # puts body
51
+ # end
52
+ #
53
+ # Returns nothing.
54
+ # Raises Tweedle::ConnectionError if the server response is not an
55
+ # Net::HTTPSuccess.
56
+ def get(uri, params = {}, &block)
57
+ uri = build_uri(uri, params)
58
+ http = build_http(uri)
59
+ request = build_get_request(uri, http, params)
60
+
61
+ begin
62
+ http.request(request) { |response| handle_response(response, &block) }
63
+ rescue *[Timeout::Error, Errno::ECONNRESET, EOFError]
64
+ retry # reconnect
65
+ ensure
66
+ http.finish
67
+ end
68
+ end
69
+
70
+ # Internal: Sends a POST request to the given stream.
71
+ #
72
+ # uri - A String containing the request URI.
73
+ # block - Optional block to yield the response body to.
74
+ # post_data - Object responding to #to_s containing the data for
75
+ # the POST request
76
+ # params - Optional request parameters (default: empty Hash)
77
+ #
78
+ # Examples
79
+ #
80
+ # post(URI.parse("http://www.google.com/", "follow=12") do |body|
81
+ # puts body
82
+ # end
83
+ #
84
+ # Returns nothing.
85
+ # Raises Tweedle::ConnectionError if the server response is not an
86
+ # Net::HTTPSuccess.
87
+ def post(uri, post_data, params = {}, &block)
88
+ uri = build_uri(uri, params)
89
+ http = build_http(uri)
90
+ request = build_post_request(uri, http, post_data, params)
91
+
92
+ begin
93
+ http.request(request) { |response| handle_response(response, &block) }
94
+ rescue *[Timeout::Error, Errno::ECONNRESET, EOFError]
95
+ retry # reconnect
96
+ ensure
97
+ http.finish
98
+ end
99
+ end
100
+
101
+ private
102
+
103
+ # Private: Reads the streaming body of a given HTTP response and
104
+ # yields a parsed JSON object to the given block for each received chunk.
105
+ #
106
+ # response - A Net::HTTPResponse object.
107
+ #
108
+ # Examples
109
+ #
110
+ # handle_response(response_object) do |body|
111
+ # puts body
112
+ # end
113
+ #
114
+ # Returns nothing.
115
+ # Raises Tweedle::ConnectionError if the server response is not an
116
+ # Net::HTTPSuccess.
117
+ def handle_response(response)
118
+ unless response.kind_of?(Net::HTTPSuccess)
119
+ msg = "#{response.code}: #{response.message}\n#{response.body}"
120
+ raise Tweedle::ConnectionError.new(msg)
121
+ end
122
+
123
+ response.read_body do |body|
124
+ begin
125
+ yield MultiJson.load(body, symbolize_keys: true) if block_given?
126
+ rescue
127
+ # Wrap this to not die on keep alive data sent by the
128
+ # Streaming API.
129
+ end
130
+ end
131
+ end
132
+
133
+ # Private: Returns the OAuth consumer object.
134
+ #
135
+ # Examples
136
+ #
137
+ # consumer
138
+ # # => Oauth::Consumer
139
+ #
140
+ # Returns a OAuth::Consumer instance.
141
+ def consumer
142
+ @consumer ||= OAuth::Consumer.new(@config.consumer_key,
143
+ @config.consumer_secret)
144
+ end
145
+
146
+ # Private: Returns the OAuth access token.
147
+ #
148
+ # Examples
149
+ #
150
+ # access_token
151
+ # # => Oauth::Token
152
+ #
153
+ # Returns a OAuth::Token instance.
154
+ def access_token
155
+ @access_token ||= OAuth::Token.new(@config.oauth_token,
156
+ @config.oauth_secret)
157
+ end
158
+
159
+ # Private: Builds a new HTTP client object with SSL enabled for the given URI.
160
+ #
161
+ # uri - A URI instance.
162
+ #
163
+ # Examples
164
+ #
165
+ # build_http URI.parse("http://www.google.com/")
166
+ # # => Net::HTTP
167
+ #
168
+ # Returns a Net::HTTP instance.
169
+ def build_http(uri)
170
+ Net::HTTP.new(uri.host, uri.port).tap do |http|
171
+ http.use_ssl = true
172
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
173
+ http.start
174
+ end
175
+ end
176
+
177
+ # Private: Builds a Net::HTTP::Get request objext for the given
178
+ # URI and performs an OAuth sign using the given Net::HTTP instance.
179
+ #
180
+ # uri - A String containing the request URI.
181
+ # http - A Net:HTTP instance.
182
+ # params - Optional request parameters (default: empty Hash).
183
+ #
184
+ # Examples
185
+ #
186
+ # uri = URI.parse("http://www.google.com/")
187
+ # build_get_request(uri, build_http(uri))
188
+ # # => Net::HTTP::Get
189
+ #
190
+ # Returns a Net::HTTP::Get instance.
191
+ def build_get_request(uri, http, params = {})
192
+ Net::HTTP::Get.new(uri.request_uri).tap do |request|
193
+ request.oauth!(http, consumer, access_token)
194
+ end
195
+ end
196
+
197
+ # Private: Builds a Net::HTTP::Post request objext for the given
198
+ # URI and performs an OAuth sign using the given Net::HTTP instance.
199
+ #
200
+ # uri - A String containing the request URI.
201
+ # http - A Net:HTTP instance.
202
+ # post_data - Object containing the POST data (converted using #encode_params)
203
+ # params - Optional request parameters (default: empty Hash).
204
+ #
205
+ # Examples
206
+ #
207
+ # uri = URI.parse("http://www.google.com/")
208
+ # build_post_request(uri, "follow=12",build_http(uri))
209
+ # # => Net::HTTP::Post
210
+ #
211
+ # Returns a Net::HTTP::Post instance.
212
+ def build_post_request(uri, http, post_data, params = {})
213
+ Net::HTTP::Post.new(uri.request_uri).tap do |request|
214
+ request["content-type"] = "application/x-www-form-urlencoded"
215
+ request.body = encode_params(post_data)
216
+ request.oauth!(http, consumer, access_token)
217
+ end
218
+ end
219
+
220
+ # Private: Builds a URI object for a given URI String and a
221
+ # parameter hash.
222
+ #
223
+ # uri - String containing the request URI.
224
+ # params - Optional request parameters to encode.
225
+ #
226
+ # Examples
227
+ #
228
+ # build_uri("http://www.google.com/search", q: "test search")
229
+ # # => #<URI::HTTP URL:http://www.google.com/search?q=test+search>
230
+ #
231
+ # Returns a URI instance.
232
+ def build_uri(uri, params)
233
+ full_path = params.empty? ? uri : "#{uri}?#{encode_params(params)}"
234
+ URI.parse(full_path)
235
+ end
236
+
237
+ # Private: Encodes a parameter hash.
238
+ #
239
+ # params - The parameter hash to encode.
240
+ #
241
+ # Examples
242
+ #
243
+ # encode_params(foo: "bar")
244
+ # # => "foo=bar"
245
+ #
246
+ # encode_params(foo: "bar", baz: 42)
247
+ # # => "foo=bar&baz=42"
248
+ #
249
+ # encode_params(follow: [1, 2, 3], baz: 42)
250
+ # # => "follow=1,2,3&baz=42"
251
+ #
252
+ # encode_params(q: "test search")
253
+ # # => "q=test+search"
254
+ #
255
+ # Returns a String.
256
+ def encode_params(params)
257
+ params.map do |key, value|
258
+ escaped = if value.kind_of?(Array)
259
+ value.map { |val| CGI::escape(val.to_s) }.join(",")
260
+ else
261
+ CGI::escape(value.to_s)
262
+ end
263
+ "#{key}=#{escaped}"
264
+ end.join("&")
265
+ end
266
+ end
267
+ end
268
+
@@ -0,0 +1,6 @@
1
+ module Tweedle
2
+ # Public: A ConnectionError is raised by all Tweedle methods if the
3
+ # server does not response with an HTTP success.
4
+ class ConnectionError < StandardError
5
+ end
6
+ end
@@ -0,0 +1,160 @@
1
+ module Tweedle
2
+ # Public: Wraps all generic {Twitter Streaming API methods}[https://dev.twitter.com/docs/streaming-api/methods].
3
+ class Statuses
4
+ # Public: The Twitter Stream server used by Tweedle::Statuses.
5
+ SERVER = "https://stream.twitter.com"
6
+
7
+ # Public: The Tweedle::Client used by the Tweedle::Statuses instance.
8
+ attr_reader :client
9
+
10
+ # Initializes a new Tweedle::Statuses instance.
11
+ #
12
+ # client - The Tweedle::Client used by the instance.
13
+ #
14
+ # Examples
15
+ #
16
+ # Tweedle::Statuses.new
17
+ # # => Tweedle::Statuses
18
+ #
19
+ # Tweedle::Statuses.new(client_instance)
20
+ # # => Tweedle::Statuses
21
+ #
22
+ # Returns a Tweedle::Statuses instance.
23
+ def initialize(client)
24
+ @client = client
25
+ end
26
+
27
+ # Returns all statuses containing http: and https:. The links
28
+ # stream is not a generally available resource.
29
+ #
30
+ # params - Hash containing request parameters (default: empty Hash).
31
+ #
32
+ # Examples
33
+ #
34
+ # links(stall_warnings: true) do |body|
35
+ # next unless text = tweet[:text]
36
+ # puts "#{tweet[:user][:screen_name]}: #{text}"
37
+ # end
38
+ #
39
+ # Returns nothing.
40
+ # Raises Tweedle::ConnectionError if the server response is not an
41
+ # Net::HTTPSuccess.
42
+ def links(params = {})
43
+ get("/1/statuses/links.json", params) do |body|
44
+ yield body if block_given?
45
+ end
46
+ end
47
+
48
+ # Returns a random sample of all public statuses.
49
+ #
50
+ # params - Hash containing request parameters (default: empty Hash).
51
+ #
52
+ # Examples
53
+ #
54
+ # sample(stall_warnings: true) do |body|
55
+ # next unless text = tweet[:text]
56
+ # puts "#{tweet[:user][:screen_name]}: #{text}"
57
+ # end
58
+ #
59
+ # Returns nothing.
60
+ # Raises Tweedle::ConnectionError if the server response is not an
61
+ # Net::HTTPSuccess.
62
+ def sample(params = {})
63
+ get("/1/statuses/sample.json", params) do |body|
64
+ yield body if block_given?
65
+ end
66
+ end
67
+
68
+ # Returns all public statuses. The Firehose is not a generally
69
+ # available resource.
70
+ #
71
+ # params - Hash containing request parameters (default: empty Hash).
72
+ #
73
+ # Examples
74
+ #
75
+ # firehose(stall_warnings: true) do |body|
76
+ # next unless text = tweet[:text]
77
+ # puts "#{tweet[:user][:screen_name]}: #{text}"
78
+ # end
79
+ #
80
+ # Returns nothing.
81
+ # Raises Tweedle::ConnectionError if the server response is not an
82
+ # Net::HTTPSuccess.
83
+ def firehose(params = {})
84
+ get("/1/statuses/firehose.json", params) do |body|
85
+ yield body if block_given?
86
+ end
87
+ end
88
+
89
+ # Returns all retweets. The retweet stream is not a generally
90
+ # available resource.
91
+ #
92
+ # params - Hash containing request parameters (default: empty Hash).
93
+ #
94
+ # Examples
95
+ #
96
+ # retweet(stall_warnings: true) do |body|
97
+ # next unless text = tweet[:text]
98
+ # puts "#{tweet[:user][:screen_name]}: #{text}"
99
+ # end
100
+ #
101
+ # Returns nothing.
102
+ # Raises Tweedle::ConnectionError if the server response is not an
103
+ # Net::HTTPSuccess.
104
+ def retweet(params = {})
105
+ get("/1/statuses/retweet.json", params) do |body|
106
+ yield body if block_given?
107
+ end
108
+ end
109
+
110
+ # Returns public statuses that match one or more filter
111
+ # predicates. At least one predicate parameter, follow,
112
+ # locations, or track must be specified. Multiple parameters
113
+ # may be specified.
114
+ #
115
+ # The default access level allows up to 400 track keywords, 5,000
116
+ # follow userids and 25 0.1-360 degree location boxes.
117
+ #
118
+ # This method uses a POST request to submit the filter predicates
119
+ # to the Twitter Streaming API.
120
+ #
121
+ # params - Hash containing the request parameters and filter predicates.
122
+ #
123
+ # Examples:
124
+ #
125
+ # predicates = {
126
+ # locations: [-122.75, 36.8, -121.75, 37.8, -74,40, -73,41],
127
+ # track: ["ruby", "tweedle"]
128
+ # }
129
+ #
130
+ # filter(predicates: predicates) do |body|
131
+ # next unless text = tweet[:text]
132
+ # puts "#{tweet[:user][:screen_name]}: #{text}"
133
+ # end
134
+ #
135
+ # filter(predicates: predicates, count: 100, stall_warnings: true) do |body|
136
+ # next unless text = tweet[:text]
137
+ # puts "#{tweet[:user][:screen_name]}: #{text}"
138
+ # end
139
+ #
140
+ # Returns nothing.
141
+ # Raises Tweedle::ConnectionError if the server response is not an
142
+ # Net::HTTPSuccess.
143
+ def filter(params)
144
+ predicates = params.delete(:predicates)
145
+ post("/1/statuses/filter.json", predicates, params) do |body|
146
+ yield body if block_given?
147
+ end
148
+ end
149
+
150
+ private
151
+
152
+ def post(path, post_data, params, &block)
153
+ @client.post(SERVER + path, post_data, params, &block)
154
+ end
155
+
156
+ def get(path, params, &block)
157
+ @client.get(SERVER + path, params, &block)
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,4 @@
1
+ module Tweedle
2
+ # Public: The current Tweedle version.
3
+ VERSION = "0.1.0"
4
+ end
data/lib/tweedle.rb ADDED
@@ -0,0 +1,58 @@
1
+ # gems
2
+ require "multi_json"
3
+ require "oauth"
4
+
5
+ # stdlib
6
+ require "ostruct"
7
+ require "cgi"
8
+
9
+ # internal
10
+ require "tweedle/version"
11
+ require "tweedle/client"
12
+ require "tweedle/statuses"
13
+ require "tweedle/errors"
14
+
15
+ # Public: The Tweedle namespace.
16
+ module Tweedle
17
+ class << self
18
+ # Public: Holds the global Tweedle configuration OpenStruct object.
19
+ attr_accessor :config
20
+
21
+ # Yields the global configuration OpenStruct object to the passed
22
+ # block. Will assign a new OpenStruct object if none has been set.
23
+ #
24
+ # Examples
25
+ #
26
+ # Tweedle.configure do |config|
27
+ # config.consumer_key = "the_consumer_key"
28
+ # config.consumer_secret = "the_consumer_secret"
29
+ # config.oauth_token = "the_oauth_token"
30
+ # config.oauth_secret = "the_oauth_secret"
31
+ # end
32
+ #
33
+ # Returns nothing.
34
+ def configure
35
+ @config ||= OpenStruct.new
36
+ yield @config if block_given?
37
+ end
38
+
39
+ # Initializes a new Tweedle::Client.
40
+ #
41
+ # config - Options object for the Tweedle client. By default uses
42
+ # the global Tweedle configuarion (default: Tweedle.config).
43
+ #
44
+ # Examples
45
+ #
46
+ # Tweedle.new
47
+ # # => Tweedle::Client
48
+ #
49
+ # Tweedle.new(config_object)
50
+ # # => Tweedle::Client
51
+ #
52
+ # Returns a Tweedle::Client instance.
53
+ def new(config = Tweedle.config)
54
+ Tweedle::Client.new(config)
55
+ end
56
+ end
57
+ end
58
+
data/test/helper.rb ADDED
@@ -0,0 +1,19 @@
1
+ if ENV['COVERAGE'] && (RUBY_ENGINE == "ruby")
2
+ require 'simplecov'
3
+ SimpleCov.start { add_filter "/test/" }
4
+ end
5
+
6
+ require 'minitest/autorun'
7
+ require "mocha"
8
+ require "fakeweb"
9
+ require "tweedle"
10
+
11
+ FakeWeb.allow_net_connect = false
12
+
13
+ Tweedle.configure do |config|
14
+ config.consumer_key = "abc"
15
+ config.consumer_secret = "def"
16
+ config.oauth_token = "ghi"
17
+ config.oauth_secret = "jkl"
18
+ end
19
+
@@ -0,0 +1,136 @@
1
+ require_relative "helper"
2
+
3
+ class TestClient < MiniTest::Unit::TestCase
4
+ def setup
5
+ @uri = "https://www.google.com"
6
+
7
+ FakeWeb.register_uri :get,
8
+ @uri,
9
+ body: "[ \"ok\" ]"
10
+
11
+ FakeWeb.register_uri :get,
12
+ @uri + "?foo=bar",
13
+ body: "[ \"foo=bar\" ]"
14
+
15
+ FakeWeb.register_uri :get,
16
+ @uri + "?foo=bar,baz",
17
+ body: "[ \"foo=bar,baz\" ]"
18
+
19
+ FakeWeb.register_uri :get,
20
+ @uri + "?foo=bar&baz=42",
21
+ body: "[ \"foo=bar&baz=42\" ]"
22
+
23
+ FakeWeb.register_uri :post,
24
+ @uri,
25
+ body: "[ \"post\" ]"
26
+
27
+ FakeWeb.register_uri :post,
28
+ @uri + "?bar=baz",
29
+ body: "[ \"post bar=baz\" ]"
30
+
31
+ FakeWeb.register_uri :post,
32
+ @uri + "?bar=baz,42",
33
+ body: "[ \"post bar=baz,42\" ]"
34
+
35
+ FakeWeb.register_uri :post,
36
+ @uri + "?bar=baz&ok=42",
37
+ body: "[ \"post bar=baz&ok=42\" ]"
38
+
39
+ @invalid = "https://www.invalid.com"
40
+
41
+ FakeWeb.register_uri :get,
42
+ @invalid,
43
+ body: "[ \"error\" ]",
44
+ status: ["404", "Not Found"]
45
+
46
+ FakeWeb.register_uri :post,
47
+ @invalid,
48
+ body: "[ \"error\" ]",
49
+ status: ["404", "Not Found"]
50
+ end
51
+
52
+ def teardown
53
+ FakeWeb.clean_registry
54
+ end
55
+
56
+ def test_config
57
+ assert_equal :foo, Tweedle::Client.new(:foo).config
58
+ end
59
+
60
+ def test_default_config
61
+ assert_equal Tweedle.config, Tweedle::Client.new.config
62
+ end
63
+
64
+ def test_statuses
65
+ client = Tweedle.new
66
+ statuses = client.statuses
67
+ assert_instance_of Tweedle::Statuses, statuses
68
+ assert_equal client, statuses.client
69
+ end
70
+
71
+ def test_get
72
+ Tweedle.new.get(@uri) { |body| assert_equal ["ok"], body }
73
+ end
74
+
75
+ def test_post
76
+ Tweedle.new.post(@uri, foo: "bar") do |body|
77
+ assert_equal ["post"], body
78
+ end
79
+ assert_equal "foo=bar", FakeWeb.last_request.body
80
+
81
+ Tweedle.new.post(@uri, foo: ["bar", "baz"]) do |body|
82
+ assert_equal ["post"], body
83
+ end
84
+ assert_equal "foo=bar,baz", FakeWeb.last_request.body
85
+
86
+ Tweedle.new.post(@uri, foo: "bar", baz: 42) do |body|
87
+ assert_equal ["post"], body
88
+ end
89
+ assert_equal "foo=bar&baz=42", FakeWeb.last_request.body
90
+ end
91
+
92
+ def test_get_with_params
93
+ Tweedle.new.get(@uri, foo: "bar") do |body|
94
+ assert_equal ["foo=bar"], body
95
+ end
96
+
97
+ Tweedle.new.get(@uri, foo: ["bar", "baz"]) do |body|
98
+ assert_equal ["foo=bar,baz"], body
99
+ end
100
+
101
+ Tweedle.new.get(@uri, foo: "bar", baz: 42) do |body|
102
+ assert_equal ["foo=bar&baz=42"], body
103
+ end
104
+ end
105
+
106
+
107
+ def test_post_with_params
108
+ Tweedle.new.post(@uri, { foo: "bar" }, { bar: "baz" }) do |body|
109
+ assert_equal ["post bar=baz"], body
110
+ end
111
+ assert_equal "foo=bar", FakeWeb.last_request.body
112
+
113
+ Tweedle.new.post(@uri, { foo: "bar" }, { bar: ["baz", 42] }) do |body|
114
+ assert_equal ["post bar=baz,42"], body
115
+ end
116
+ assert_equal "foo=bar", FakeWeb.last_request.body
117
+
118
+ Tweedle.new.post(@uri, { foo: "bar" }, { bar: "baz", ok: 42 }) do |body|
119
+ assert_equal ["post bar=baz&ok=42"], body
120
+ end
121
+ assert_equal "foo=bar", FakeWeb.last_request.body
122
+ end
123
+
124
+ def test_get_with_invalid_response
125
+ assert_raises(Tweedle::ConnectionError) do
126
+ Tweedle.new.get(@invalid)
127
+ end
128
+ end
129
+
130
+ def test_post_with_invalid_response
131
+ assert_raises(Tweedle::ConnectionError) do
132
+ Tweedle.new.post(@invalid, foo: "bar")
133
+ end
134
+ end
135
+ end
136
+
@@ -0,0 +1,147 @@
1
+ require_relative "helper"
2
+
3
+ class TestStatuses < MiniTest::Unit::TestCase
4
+ def statuses
5
+ Tweedle.new.statuses
6
+ end
7
+
8
+ def setup
9
+ %w(firehose retweet links sample).each do |req|
10
+ FakeWeb.register_uri :get,
11
+ Tweedle::Statuses::SERVER + "/1/statuses/#{req}.json",
12
+ body: "[\"ok\"]"
13
+
14
+ FakeWeb.register_uri :get,
15
+ Tweedle::Statuses::SERVER + "/1/statuses/#{req}.json?count=100",
16
+ body: "[\"single\"]"
17
+
18
+ FakeWeb.register_uri :get,
19
+ Tweedle::Statuses::SERVER + "/1/statuses/#{req}.json?count=100,200",
20
+ body: "[\"array\"]"
21
+
22
+ FakeWeb.register_uri :get,
23
+ Tweedle::Statuses::SERVER + "/1/statuses/#{req}.json?count=1&foo=true",
24
+ body: "[\"multi\"]"
25
+ end
26
+
27
+ FakeWeb.register_uri :post,
28
+ Tweedle::Statuses::SERVER + "/1/statuses/filter.json",
29
+ body: "[\"post\"]"
30
+
31
+ FakeWeb.register_uri :post,
32
+ Tweedle::Statuses::SERVER + "/1/statuses/filter.json?foo=42,43&bar=true",
33
+ body: "[\"post with params\"]"
34
+ end
35
+
36
+ def teardown
37
+ FakeWeb.clean_registry
38
+ end
39
+
40
+ def test_filter
41
+ predicates = {
42
+ locations: [-122.75, 36.8, -121.75, 37.8],
43
+ track: ["ruby", "tweedle"]
44
+ }
45
+
46
+ statuses.filter(predicates: predicates) do |body|
47
+ assert_equal ["post"], body
48
+ end
49
+
50
+ assert_equal "locations=-122.75,36.8,-121.75,37.8&track=ruby,tweedle",
51
+ FakeWeb.last_request.body
52
+ end
53
+
54
+ def test_filter_with_params
55
+ predicates = {
56
+ locations: [-122.75, 36.8, -121.75, 37.8],
57
+ track: ["ruby", "tweedle"]
58
+ }
59
+
60
+ statuses.filter(predicates: predicates, foo: [42, 43], bar: true) do |body|
61
+ assert_equal ["post with params"], body
62
+ end
63
+
64
+ assert_equal "locations=-122.75,36.8,-121.75,37.8&track=ruby,tweedle",
65
+ FakeWeb.last_request.body
66
+ end
67
+
68
+ def test_firehose
69
+ statuses.firehose do |body|
70
+ assert_equal ["ok"], body
71
+ end
72
+ end
73
+
74
+ def test_firehose_with_params
75
+ statuses.firehose(count: 100) do |body|
76
+ assert_equal ["single"], body
77
+ end
78
+
79
+ statuses.firehose(count: [100, 200]) do |body|
80
+ assert_equal ["array"], body
81
+ end
82
+
83
+ statuses.firehose(count: 1, foo: true) do |body|
84
+ assert_equal ["multi"], body
85
+ end
86
+ end
87
+
88
+ def test_retweet
89
+ statuses.retweet do |body|
90
+ assert_equal ["ok"], body
91
+ end
92
+ end
93
+
94
+ def test_retweet_with_params
95
+ statuses.retweet(count: 100) do |body|
96
+ assert_equal ["single"], body
97
+ end
98
+
99
+ statuses.retweet(count: [100, 200]) do |body|
100
+ assert_equal ["array"], body
101
+ end
102
+
103
+ statuses.retweet(count: 1, foo: true) do |body|
104
+ assert_equal ["multi"], body
105
+ end
106
+ end
107
+
108
+ def test_links
109
+ statuses.links do |body|
110
+ assert_equal ["ok"], body
111
+ end
112
+ end
113
+
114
+ def test_links_with_params
115
+ statuses.links(count: 100) do |body|
116
+ assert_equal ["single"], body
117
+ end
118
+
119
+ statuses.links(count: [100, 200]) do |body|
120
+ assert_equal ["array"], body
121
+ end
122
+
123
+ statuses.links(count: 1, foo: true) do |body|
124
+ assert_equal ["multi"], body
125
+ end
126
+ end
127
+
128
+ def test_sample
129
+ statuses.sample do |body|
130
+ assert_equal ["ok"], body
131
+ end
132
+ end
133
+
134
+ def test_sample_with_params
135
+ statuses.sample(count: 100) do |body|
136
+ assert_equal ["single"], body
137
+ end
138
+
139
+ statuses.sample(count: [100, 200]) do |body|
140
+ assert_equal ["array"], body
141
+ end
142
+
143
+ statuses.sample(count: 1, foo: true) do |body|
144
+ assert_equal ["multi"], body
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,26 @@
1
+ require_relative "helper"
2
+
3
+ class TestTweedle < MiniTest::Unit::TestCase
4
+ def setup
5
+ @old_config = Tweedle.config
6
+ end
7
+
8
+ def teardown
9
+ Tweedle.config = @old_config
10
+ end
11
+
12
+ def test_new
13
+ assert_instance_of Tweedle::Client, Tweedle.new
14
+ end
15
+
16
+ def test_new_passes_arguments
17
+ Tweedle::Client.expects(:new).with(:foo)
18
+ Tweedle.new(:foo)
19
+ end
20
+
21
+ def test_configure
22
+ Tweedle.configure { |config| config.foo = :bar }
23
+ assert_equal :bar, Tweedle.config.foo
24
+ end
25
+ end
26
+
data/tweedle.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/tweedle/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Tobias Svensson"]
6
+ gem.email = ["tob@tobiassvensson.co.uk"]
7
+ gem.description = %q{Lightweight wrapper for the Twitter Streaming API}
8
+ gem.summary = gem.description
9
+ gem.homepage = "http://github.com/tobiassvn/tweedle"
10
+
11
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.name = "tweedle"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Tweedle::VERSION
17
+
18
+ gem.add_dependency "multi_json", "~> 1.3.2"
19
+ gem.add_dependency "oauth", "~> 0.4.6"
20
+ gem.add_dependency "jruby-openssl", "~> 0.7.6.1" if RUBY_PLATFORM =~ /java/
21
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tweedle
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tobias Svensson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: multi_json
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.3.2
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.3.2
30
+ - !ruby/object:Gem::Dependency
31
+ name: oauth
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.4.6
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.4.6
46
+ description: Lightweight wrapper for the Twitter Streaming API
47
+ email:
48
+ - tob@tobiassvensson.co.uk
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - .rdoc_options
55
+ - .travis.yml
56
+ - Gemfile
57
+ - LICENSE
58
+ - README.rdoc
59
+ - Rakefile
60
+ - examples/statuses.filter.rb
61
+ - examples/statuses.sample.rb
62
+ - lib/tweedle.rb
63
+ - lib/tweedle/client.rb
64
+ - lib/tweedle/errors.rb
65
+ - lib/tweedle/statuses.rb
66
+ - lib/tweedle/version.rb
67
+ - test/helper.rb
68
+ - test/test_client.rb
69
+ - test/test_statuses.rb
70
+ - test/test_tweedle.rb
71
+ - tweedle.gemspec
72
+ homepage: http://github.com/tobiassvn/tweedle
73
+ licenses: []
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ segments:
85
+ - 0
86
+ hash: 2043315067158047274
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ segments:
94
+ - 0
95
+ hash: 2043315067158047274
96
+ requirements: []
97
+ rubyforge_project:
98
+ rubygems_version: 1.8.23
99
+ signing_key:
100
+ specification_version: 3
101
+ summary: Lightweight wrapper for the Twitter Streaming API
102
+ test_files:
103
+ - test/helper.rb
104
+ - test/test_client.rb
105
+ - test/test_statuses.rb
106
+ - test/test_tweedle.rb