birdgrinder 0.1.3.1 → 0.1.4.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/bin/birdgrinder CHANGED
@@ -26,5 +26,26 @@ BirdGrinder::Application.processing(ARGV) do |a|
26
26
  template 'hello_world_handler.erb', 'handlers/hello_world_handler.rb'
27
27
  template 'rakefile.erb', 'Rakefile'
28
28
  end
29
+
30
+ a.add("authorize", "Gets oauth access token information making it possible to use oauth authentication") do |options|
31
+ puts "First, you need to create a twitter application and get a consumer key and secret."
32
+ puts "To do this, visit http://twitter.com/apps/new"
33
+ system("open", "http://twitter.com/apps/new") if yes?("Are you running OSX and wish to open this url now?")
34
+ consumer_key, consumer_secret = "", ""
35
+ consumer_key = ask("What is your applications consumer key?", "") while consumer_key.blank?
36
+ consumer_secret = ask("What is your applications consumer secret?", "") while consumer_secret.blank?
37
+ BirdGrinder::Settings.oauth.consumer_key = consumer_key
38
+ BirdGrinder::Settings.oauth.consumer_secret = consumer_secret
39
+ oauth = BirdGrinder::Tweeter::OAuthAuthentication
40
+ rtoken = oauth.request_token
41
+ token, secret = rtoken.token, rtoken.secret
42
+ puts "To get a pin for your account, please visit: #{rtoken.authorize_url}"
43
+ system("open", rtoken.authorize_url) if yes?("Are you running OSX and wish to open this url now?")
44
+ value = ""
45
+ value = ask("What is the PIN twitter gave you?", "") while value.blank?
46
+ puts "Updating settings..."
47
+ oauth.retrieve_access_token!(token, secret, value)
48
+ puts "Done! - Your access token should now be stored"
49
+ end
29
50
 
30
51
  end
data/lib/bird_grinder.rb CHANGED
@@ -8,7 +8,7 @@ require 'em-http'
8
8
  module BirdGrinder
9
9
  include Perennial
10
10
 
11
- VERSION = [0, 1, 3, 1]
11
+ VERSION = [0, 1, 4, 0]
12
12
 
13
13
  def self.version(include_minor = false)
14
14
  VERSION[0, (include_minor ? 4 : 3)].join(".")
@@ -9,7 +9,7 @@ module BirdGrinder
9
9
  # @param [Symbol] the stream name, e.g. :filter / :sample
10
10
  def tweet_from_stream(name, &blk)
11
11
  on_event(:incoming_stream) do
12
- instance_eval(&blk) if options.streaming_source == name && options.stream_type == :tweet
12
+ instance_eval(&blk) if correct_stream?(name, :tweet)
13
13
  end
14
14
  end
15
15
 
@@ -17,7 +17,7 @@ module BirdGrinder
17
17
  # @param [Symbol] the stream name, e.g. :filter / :sample
18
18
  def delete_from_stream(name, &blk)
19
19
  on_event(:incoming_stream) do
20
- instance_eval(&blk) if options.streaming_source == name && options.stream_type == :delete
20
+ instance_eval(&blk) if correct_stream?(name, :delete)
21
21
  end
22
22
  end
23
23
 
@@ -25,7 +25,7 @@ module BirdGrinder
25
25
  # @param [Symbol] the stream name, e.g. :filter / :sample
26
26
  def rate_limit_from_stream(name, &blk)
27
27
  on_event(:incoming_stream) do
28
- instance_eval(&blk) if options.streaming_source == name && options.stream_type == :limit
28
+ instance_eval(&blk) if correct_stream?(name, :limit)
29
29
  end
30
30
  end
31
31
 
@@ -40,5 +40,11 @@ module BirdGrinder
40
40
 
41
41
  end
42
42
 
43
+ protected
44
+
45
+ def correct_stream?(name, type)
46
+ options.streaming_source == name && options.stream_type == type
47
+ end
48
+
43
49
  end
44
50
  end
@@ -20,13 +20,14 @@ module BirdGrinder
20
20
 
21
21
  require 'bird_grinder/tweeter/streaming'
22
22
  require 'bird_grinder/tweeter/search'
23
+ require 'bird_grinder/tweeter/abstract_authorization'
24
+ require 'bird_grinder/tweeter/basic_authorization'
25
+ require 'bird_grinder/tweeter/oauth_authorization'
23
26
 
24
27
  VALID_FETCHES = [:direct_messages, :mentions]
25
28
 
26
29
  cattr_accessor :api_base_url
27
30
  self.api_base_url = "http://twitter.com/"
28
-
29
- attr_reader :auth_credentials
30
31
 
31
32
  # Initializes the tweeter with a given delegate. It will use
32
33
  # username and password from your settings file for authorization
@@ -35,7 +36,6 @@ module BirdGrinder
35
36
  # @param [Delegate] delegate the delegate class
36
37
  def initialize(delegate)
37
38
  check_auth!
38
- @auth_credentials = [BirdGrinder::Settings.username, BirdGrinder::Settings.password]
39
39
  delegate_to delegate
40
40
  end
41
41
 
@@ -58,7 +58,7 @@ module BirdGrinder
58
58
  user = user.to_s.strip
59
59
  logger.info "Following '#{user}'"
60
60
  post("friendships/create.json", opts.merge(:screen_name => user)) do
61
- delegate.receive_message(:outgoing_follow, {:user => user}.to_nash)
61
+ delegate.receive_message(:outgoing_follow, N(:user => user))
62
62
  end
63
63
  end
64
64
 
@@ -70,7 +70,7 @@ module BirdGrinder
70
70
  user = user.to_s.strip
71
71
  logger.info "Unfollowing '#{user}'"
72
72
  post("friendships/destroy.json", opts.merge(:screen_name => user)) do
73
- delegate.receive_message(:outgoing_unfollow, {:user => user}.to_nash)
73
+ delegate.receive_message(:outgoing_unfollow, N(:user => user))
74
74
  end
75
75
  end
76
76
 
@@ -95,8 +95,8 @@ module BirdGrinder
95
95
  text = text.to_s.strip
96
96
  user = user.to_s.strip
97
97
  logger.debug "DM'ing #{user}: #{text}"
98
- post("direct_messages/new.json", opts.merge(:user => user, :text => text)) do
99
- delegate.receive_message(:outgoing_direct_message, {:user => user, :text => text}.to_nash)
98
+ post("direct_messages/new.json", opts.merge(:user => user, :text => text)) do |json|
99
+ delegate.receive_message(:outgoing_direct_message, status_to_args(json, :direct_message))
100
100
  end
101
101
  end
102
102
 
@@ -182,13 +182,18 @@ module BirdGrinder
182
182
  end
183
183
  else
184
184
  logger.info "Getting all followers for #{id}"
185
- get_followers(id, opts.merge(:cursor => -1), {
185
+ get_followers(id, opts.merge(:cursor => -1), N({
186
186
  :user_id => id,
187
187
  :all => true,
188
188
  :ids => []
189
- }.to_nash)
189
+ }))
190
190
  end
191
191
  end
192
+
193
+ # @todo Use correct authorization method
194
+ def authorization_method
195
+ @authorization_method ||= (OAuthAuthorization.enabled? ? OAuthAuthorization : BasicAuthorization).new
196
+ end
192
197
 
193
198
  protected
194
199
 
@@ -214,10 +219,9 @@ module BirdGrinder
214
219
  end
215
220
 
216
221
  def get(path, params = {}, &blk)
217
- http = request(path).get({
218
- :head => {'Authorization' => @auth_credentials},
219
- :query => params.stringify_keys
220
- })
222
+ req = request(path)
223
+ http = req.get(:query => params)
224
+ authorization_method.add_header_to(http)
221
225
  add_response_callback(http, blk)
222
226
  http
223
227
  end
@@ -225,13 +229,12 @@ module BirdGrinder
225
229
  def post(path, params = {}, &blk)
226
230
  real_params = {}
227
231
  params.each_pair { |k,v| real_params[CGI.escape(k.to_s)] = CGI.escape(v) }
228
- http = request(path).post({
229
- :head => {
230
- 'Authorization' => @auth_credentials,
231
- 'Content-Type' => 'application/x-www-form-urlencoded'
232
- },
232
+ req = request(path)
233
+ http = req.post({
234
+ :head => {'Content-Type' => 'application/x-www-form-urlencoded'},
233
235
  :body => real_params
234
236
  })
237
+ authorization_method.add_header_to(http)
235
238
  add_response_callback(http, blk)
236
239
  http
237
240
  end
@@ -276,9 +279,8 @@ module BirdGrinder
276
279
  end
277
280
 
278
281
  def check_auth!
279
- if BirdGrinder::Settings["username"].blank? || BirdGrinder::Settings["username"].blank?
280
- raise BirdGrinder::MissingAuthDetails, "Missing twitter username or password."
281
- end
282
+ return if BirdGrinder::Settings.username? && BirdGrinder::Settings.password?
283
+ raise BirdGrinder::MissingAuthDetails, "Missing twitter username or password."
282
284
  end
283
285
 
284
286
  end
@@ -0,0 +1,19 @@
1
+ module BirdGrinder
2
+ class Tweeter
3
+ class AbstractAuthorization
4
+
5
+ is :loggable
6
+
7
+ def add_header_to(http)
8
+ headers = (http.options[:head] ||= {})
9
+ headers['Authorization'] = self.header_for(http)
10
+ end
11
+
12
+ def header_for(http)
13
+ raise NotImplementedError
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+
@@ -0,0 +1,23 @@
1
+ module BirdGrinder
2
+ class Tweeter
3
+ class BasicAuthorization < AbstractAuthorization
4
+
5
+ def initialize
6
+ @basic_auth_credentials = [BirdGrinder::Settings.username, BirdGrinder::Settings.password]
7
+ end
8
+
9
+ attr_reader :basic_auth_credentials
10
+
11
+ # Authenticats a given request using Basic authorization.
12
+ def header_for(http)
13
+ @basic_auth_credentials
14
+ end
15
+
16
+ protected
17
+
18
+ def generate_header!
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,54 @@
1
+ require 'oauth'
2
+ require 'em-http-oauth-request'
3
+
4
+ module BirdGrinder
5
+ class Tweeter
6
+ class OAuthAuthorization< AbstractAuthorization
7
+
8
+ # Authenticates a given request.
9
+ def header_for(request)
10
+ OAuth::Client::Helper.new(request, {
11
+ :token => self.class.oauth_access_token,
12
+ :consumer => self.class.oauth_consumer
13
+ }).header
14
+ end
15
+
16
+ def self.enabled?
17
+ oauth = BirdGrinder::Settings.oauth
18
+ oauth.present? && [:consumer_key, :consumer_secret, :access_token_token, :access_token_secret].all? { |k| oauth[k].present? }
19
+ end
20
+
21
+ # From the twitter gem, with modification
22
+ def self.retrieve_access_token!(raw_request_token, request_secret, pin)
23
+ request_token = OAuth::RequestToken.new(self.oauth_consumer, raw_request_token, request_secret)
24
+ access_token = request_token.get_access_token(:oauth_verifier => pin)
25
+ original_settings = BirdGrinder::Settings.oauth.to_hash
26
+ original_settings.merge! :access_token_token => access_token.token,
27
+ :access_token_secret => access_token.secret
28
+ BirdGrinder::Settings.update! :oauth => original_settings.stringify_keys
29
+ end
30
+
31
+ def self.request_token
32
+ @request_token ||= self.oauth_consumer.get_request_token
33
+ end
34
+
35
+ protected
36
+
37
+ def self.oauth_consumer
38
+ @oauth_consumer ||= begin
39
+ settings = BirdGrinder::Settings.oauth
40
+ site = Tweeter.api_base_url.gsub(/\/$/, '')
41
+ OAuth::Consumer.new(settings.consumer_key, settings.consumer_secret, :site => site)
42
+ end
43
+ end
44
+
45
+ def self.oauth_access_token
46
+ @oauth_access_token ||= begin
47
+ settings = BirdGrinder::Settings.oauth
48
+ OAuth::AccessToken.new(self.oauth_consumer, settings.access_token_token, settings.access_token_secret)
49
+ end
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -40,19 +40,20 @@ module BirdGrinder
40
40
  # Start processing the filter stream with a given follow
41
41
  # argument.
42
42
  #
43
- # @param [Array] args what to follow, joined with ","
43
+ # @param [Array] args what to follow, joined with "," followed by opts
44
44
  def follow(*args)
45
45
  opts = args.extract_options!
46
- opts[:follow] = args.join(",")
46
+ opts[:follow] = args.flatten.join(",")
47
47
  opts[:path] = :filter
48
48
  stream(:follow, opts)
49
49
  end
50
50
 
51
51
  # Starts tracking a specific query.
52
52
  #
53
- # @param [Hash] opts extra options for the query
54
- def track(query, opts = {})
55
- opts[:track] = query
53
+ # @param [Array] args what to track, joined with "," followed by opts
54
+ def track(*args)
55
+ opts = args.extract_options!
56
+ opts[:track] = args.flatten.join(",")
56
57
  opts[:path] = :filter
57
58
  stream(:track, opts)
58
59
  end
@@ -45,7 +45,8 @@ module BirdGrinder
45
45
  logger.debug "Preparing to start stream"
46
46
  @stream_processor = nil
47
47
  type = request_method
48
- http = EventMachine::HttpRequest.new(full_url).send(type, http_options(type))
48
+ http = EventMachine::HttpRequest.new(full_url).send(type, http_options(type, request))
49
+ authorization_method.add_header_to(http)
49
50
  # Handle failures correctly so we can back off
50
51
  @current_request = http
51
52
  http.errback { fail!(:network)}
@@ -100,21 +101,22 @@ module BirdGrinder
100
101
  # what method is used to send the request. It's important that
101
102
  # this is used for credentials as well as making sure there is
102
103
  # no timeout on the connection
103
- def default_request_options
104
- {:head => {'Authorization' => @parent.auth_credentials}, :timeout => 0}
104
+ def default_request_options(r)
105
+ {:timeout => 0, :head => {}}
105
106
  end
106
107
 
107
108
  # Returns normalized http options for the current request, built
108
109
  # on top of default_request_options and a few other details.
109
110
  #
110
111
  # @param [Symbol] type the type of request - :post or :get
111
- def http_options(type)
112
+ # @param [EventMachine::HttpRequest] the request itself
113
+ def http_options(type, request)
112
114
  base = self.default_request_options
113
115
  if @options.present?
114
116
  if type == :get
115
117
  base[:query] = @options
116
118
  else
117
- base[:head].merge! 'Content-Type' => "application/x-www-form-urlencoded"
119
+ base[:head]['Content-Type'] = "application/x-www-form-urlencoded"
118
120
  base[:body] = body = {}
119
121
  @options.each_pair { |k,v| body[CGI.escape(k.to_s)] = CGI.escape(v) }
120
122
  end
@@ -136,6 +138,10 @@ module BirdGrinder
136
138
  @full_url ||= (Streaming.streaming_base_url / Streaming.api_version.to_s / "statuses" / "#{@path}.json")
137
139
  end
138
140
 
141
+ def authorization_method
142
+ @authorization_method ||= BasicAuthorization.new
143
+ end
144
+
139
145
  end
140
146
  end
141
147
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: birdgrinder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3.1
4
+ version: 0.1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Darcy Laycock
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-08 00:00:00 +08:00
12
+ date: 2009-12-29 00:00:00 +08:00
13
13
  default_executable: birdgrinder
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -52,6 +52,26 @@ dependencies:
52
52
  - !ruby/object:Gem::Version
53
53
  version: 0.1.8
54
54
  version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: moneta
57
+ type: :runtime
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: 0.6.0
64
+ version:
65
+ - !ruby/object:Gem::Dependency
66
+ name: em-http-oauth-request
67
+ type: :runtime
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: 0.1.0
74
+ version:
55
75
  description:
56
76
  email: sutto@sutto.net
57
77
  executables:
@@ -71,6 +91,9 @@ files:
71
91
  - lib/bird_grinder/loader.rb
72
92
  - lib/bird_grinder/queue_processor.rb
73
93
  - lib/bird_grinder/stream_handler.rb
94
+ - lib/bird_grinder/tweeter/abstract_authorization.rb
95
+ - lib/bird_grinder/tweeter/basic_authorization.rb
96
+ - lib/bird_grinder/tweeter/oauth_authorization.rb
74
97
  - lib/bird_grinder/tweeter/search.rb
75
98
  - lib/bird_grinder/tweeter/stream_processor.rb
76
99
  - lib/bird_grinder/tweeter/streaming.rb