birdgrinder 0.1.3.1 → 0.1.4.0

Sign up to get free protection for your applications and to get access to all the features.
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