jnunemaker-twitter 0.5.3 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/History CHANGED
@@ -1,3 +1,7 @@
1
+ 0.6.0 - April 11, 2009
2
+ * 1 feature addition
3
+ * Added http authentication back in. You can now use oauth or http auth as your client.
4
+
1
5
  0.5.3 - April 10, 2009
2
6
  * 1 minor fix
3
7
  * Twitter API assumed follow true whether true or false. Now only sending follow along to request if follow is true for calls to friendship_create.
data/README.rdoc CHANGED
@@ -1,9 +1,13 @@
1
1
  = twitter
2
2
 
3
- The ruby twitter gem. The gem heard round the world and famous on the streets. Haha.
3
+ The ruby twitter gem. The gem heard round the world and famous on the streets. Haha. This gem works with both oauth and http auth, if you care.
4
4
 
5
5
  For now this is just an API wrapper. The command line interface is temporarily dead until I have time to make it work with oauth. At that point, I'll make it a new gem twitter-cli or something and it will depend on this gem to work. That will keep the separation of the api wrapper and cli and fix a lot of dependency issues.
6
6
 
7
+ = examples
8
+
9
+ See the examples directory.
10
+
7
11
  == Copyright
8
12
 
9
13
  Copyright (c) 2009 John Nunemaker. See LICENSE for details.
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
- :minor: 5
4
- :patch: 3
3
+ :minor: 6
4
+ :patch: 0
@@ -0,0 +1,11 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'twitter')
2
+ require File.join(File.dirname(__FILE__), 'helpers', 'config_store')
3
+ require 'pp'
4
+
5
+ config = ConfigStore.new("#{ENV['HOME']}/.twitter")
6
+
7
+ httpauth = Twitter::HTTPAuth.new(config['email'], config['password'])
8
+ base = Twitter::Base.new(httpauth)
9
+
10
+ pp base.user_timeline
11
+ pp base.verify_credentials
data/lib/twitter/base.rb CHANGED
@@ -2,10 +2,12 @@ module Twitter
2
2
  class Base
3
3
  extend Forwardable
4
4
 
5
- def_delegators :@client, :get, :post
5
+ def_delegators :client, :get, :post
6
6
 
7
- def initialize(oauth)
8
- @client = oauth.access_token
7
+ attr_reader :client
8
+
9
+ def initialize(client)
10
+ @client = client
9
11
  end
10
12
 
11
13
  # Options: since_id, max_id, count, page, since
@@ -0,0 +1,26 @@
1
+ module Twitter
2
+ class HTTPAuth
3
+ include HTTParty
4
+ base_uri 'http://twitter.com'
5
+ format :plain
6
+
7
+ attr_reader :username, :password
8
+
9
+ def initialize(username, password)
10
+ @username, @password = username, password
11
+ end
12
+
13
+ def get(uri, headers={})
14
+ self.class.get(uri, :headers => headers, :basic_auth => basic_auth)
15
+ end
16
+
17
+ def post(uri, body={}, headers={})
18
+ self.class.post(uri, :body => body, :headers => headers, :basic_auth => basic_auth)
19
+ end
20
+
21
+ private
22
+ def basic_auth
23
+ @basic_auth ||= {:username => @username, :password => @password}
24
+ end
25
+ end
26
+ end
data/lib/twitter/oauth.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  module Twitter
2
2
  class OAuth
3
+ extend Forwardable
4
+ def_delegators :access_token, :get, :post
5
+
3
6
  attr_reader :ctoken, :csecret
4
7
 
5
8
  def initialize(ctoken, csecret)
@@ -2,20 +2,20 @@ module Twitter
2
2
  class Request
3
3
  extend Forwardable
4
4
 
5
- def self.get(base, path, options={})
6
- new(base, :get, path, options).perform
5
+ def self.get(client, path, options={})
6
+ new(client, :get, path, options).perform
7
7
  end
8
8
 
9
- def self.post(base, path, options={})
10
- new(base, :post, path, options).perform
9
+ def self.post(client, path, options={})
10
+ new(client, :post, path, options).perform
11
11
  end
12
12
 
13
- attr_reader :base, :method, :path, :options
13
+ attr_reader :client, :method, :path, :options
14
14
 
15
- def_delegators :base, :get, :post
15
+ def_delegators :client, :get, :post
16
16
 
17
- def initialize(base, method, path, options={})
18
- @base, @method, @path, @options = base, method, path, options
17
+ def initialize(client, method, path, options={})
18
+ @client, @method, @path, @options = client, method, path, options
19
19
  end
20
20
 
21
21
  def uri
data/lib/twitter.rb CHANGED
@@ -35,6 +35,7 @@ directory = File.dirname(__FILE__)
35
35
  $:.unshift(directory) unless $:.include?(directory)
36
36
 
37
37
  require 'twitter/oauth'
38
+ require 'twitter/httpauth'
38
39
  require 'twitter/request'
39
40
  require 'twitter/base'
40
41
  require 'twitter/search'
data/test/test_helper.rb CHANGED
@@ -20,15 +20,17 @@ def fixture_file(filename)
20
20
  File.read(file_path)
21
21
  end
22
22
 
23
+ def twitter_url(url)
24
+ url =~ /^http/ ? url : "http://twitter.com:80#{url}"
25
+ end
26
+
23
27
  def stub_get(url, filename, status=nil)
24
- url = url =~ /^http/ ? url : "http://twitter.com:80#{url}"
25
-
26
28
  options = {:string => fixture_file(filename)}
27
29
  options.merge!({:status => status}) unless status.nil?
28
30
 
29
- FakeWeb.register_uri(:get, url, options)
31
+ FakeWeb.register_uri(:get, twitter_url(url), options)
30
32
  end
31
33
 
32
34
  def stub_post(url, filename)
33
- FakeWeb.register_uri(:post, "http://twitter.com:80#{url}", :string => fixture_file(filename))
35
+ FakeWeb.register_uri(:post, twitter_url(url), :string => fixture_file(filename))
34
36
  end
@@ -10,8 +10,9 @@ class BaseTest < Test::Unit::TestCase
10
10
  end
11
11
 
12
12
  context "initialize" do
13
- should "require an oauth object" do
14
- @twitter.instance_variable_get('@client').should == @access_token
13
+ should "require a client" do
14
+ @twitter.client.should respond_to(:get)
15
+ @twitter.client.should respond_to(:post)
15
16
  end
16
17
  end
17
18
 
@@ -0,0 +1,50 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class HTTPAuthTest < Test::Unit::TestCase
4
+ context "Creating new instance" do
5
+ should "should take user and password" do
6
+ twitter = Twitter::HTTPAuth.new('username', 'password')
7
+ twitter.username.should == 'username'
8
+ twitter.password.should == 'password'
9
+ end
10
+ end
11
+
12
+ context "Client methods" do
13
+ setup do
14
+ @twitter = Twitter::HTTPAuth.new('username', 'password')
15
+ end
16
+
17
+ should "be able to get" do
18
+ stub_get('http://twitter.com:80/statuses/user_timeline.json', 'user_timeline.json')
19
+ response = @twitter.get('/statuses/user_timeline.json')
20
+ response.should == fixture_file('user_timeline.json')
21
+ end
22
+
23
+ should "be able to get with headers" do
24
+ @twitter.class.expects(:get).with(
25
+ '/statuses/user_timeline.json', {
26
+ :basic_auth => {:username => 'username', :password => 'password'},
27
+ :headers => {'Foo' => 'Bar'}
28
+ }
29
+ ).returns(fixture_file('user_timeline.json'))
30
+ @twitter.get('/statuses/user_timeline.json', {'Foo' => 'Bar'})
31
+ end
32
+
33
+ should "be able to post" do
34
+ stub_post('http://twitter.com:80/statuses/update.json', 'status.json')
35
+ response = @twitter.post('/statuses/update.json', :text => 'My update.')
36
+ response.should == fixture_file('status.json')
37
+ end
38
+
39
+ should "be able to post with headers" do
40
+ @twitter.class.expects(:post).with(
41
+ '/statuses/update.json', {
42
+ :headers => {'Foo' => 'Bar'},
43
+ :body => {:text => 'My update.'},
44
+ :basic_auth => {:username => 'username', :password => 'password'}
45
+ }
46
+ ).returns(fixture_file('status.json'))
47
+ @twitter.post('/statuses/update.json', {:text => 'My update.'}, {'Foo' => 'Bar'})
48
+ end
49
+ end
50
+ end
@@ -52,4 +52,20 @@ class OAuthTest < Test::Unit::TestCase
52
52
  twitter.access_token.token.should == 'atoken'
53
53
  twitter.access_token.secret.should == 'asecret'
54
54
  end
55
+
56
+ should "delegate get to access token" do
57
+ access_token = mock('access token')
58
+ twitter = Twitter::OAuth.new('token', 'secret')
59
+ twitter.stubs(:access_token).returns(access_token)
60
+ access_token.expects(:get).returns(nil)
61
+ twitter.get('/foo')
62
+ end
63
+
64
+ should "delegate post to access token" do
65
+ access_token = mock('access token')
66
+ twitter = Twitter::OAuth.new('token', 'secret')
67
+ twitter.stubs(:access_token).returns(access_token)
68
+ access_token.expects(:post).returns(nil)
69
+ twitter.post('/foo')
70
+ end
55
71
  end
@@ -3,12 +3,12 @@ require File.dirname(__FILE__) + '/../test_helper'
3
3
  class RequestTest < Test::Unit::TestCase
4
4
  context "new get request" do
5
5
  setup do
6
- @base = mock('twitter base')
7
- @request = Twitter::Request.new(@base, :get, '/statuses/user_timeline.json', {:query => {:since_id => 1234}})
6
+ @client = mock('twitter client')
7
+ @request = Twitter::Request.new(@client, :get, '/statuses/user_timeline.json', {:query => {:since_id => 1234}})
8
8
  end
9
9
 
10
- should "have base" do
11
- @request.base.should == @base
10
+ should "have client" do
11
+ @request.client.should == @client
12
12
  end
13
13
 
14
14
  should "have method" do
@@ -34,7 +34,7 @@ class RequestTest < Test::Unit::TestCase
34
34
  stubs(:code).returns('200')
35
35
  end
36
36
 
37
- @base.expects(:get).returns(response)
37
+ @client.expects(:get).returns(response)
38
38
  @object = @request.perform
39
39
  end
40
40
 
@@ -52,7 +52,7 @@ class RequestTest < Test::Unit::TestCase
52
52
  stubs(:code).returns('200')
53
53
  end
54
54
 
55
- @base.expects(:get).returns(response)
55
+ @client.expects(:get).returns(response)
56
56
  @object = @request.perform
57
57
  end
58
58
 
@@ -64,21 +64,21 @@ class RequestTest < Test::Unit::TestCase
64
64
 
65
65
  context "with no query string" do
66
66
  should "not have any query string" do
67
- request = Twitter::Request.new(@base, :get, '/statuses/user_timeline.json')
67
+ request = Twitter::Request.new(@client, :get, '/statuses/user_timeline.json')
68
68
  request.uri.should == '/statuses/user_timeline.json'
69
69
  end
70
70
  end
71
71
 
72
72
  context "with blank query string" do
73
73
  should "not have any query string" do
74
- request = Twitter::Request.new(@base, :get, '/statuses/user_timeline.json', :query => {})
74
+ request = Twitter::Request.new(@client, :get, '/statuses/user_timeline.json', :query => {})
75
75
  request.uri.should == '/statuses/user_timeline.json'
76
76
  end
77
77
  end
78
78
 
79
79
  should "have get shortcut to initialize and perform all in one" do
80
80
  Twitter::Request.any_instance.expects(:perform).returns(nil)
81
- Twitter::Request.get(@base, '/foo')
81
+ Twitter::Request.get(@client, '/foo')
82
82
  end
83
83
 
84
84
  should "allow setting query string and headers" do
@@ -87,15 +87,15 @@ class RequestTest < Test::Unit::TestCase
87
87
  stubs(:code).returns('200')
88
88
  end
89
89
 
90
- @base.expects(:get).with('/statuses/friends_timeline.json?since_id=1234', {'Foo' => 'Bar'}).returns(response)
91
- Twitter::Request.get(@base, '/statuses/friends_timeline.json?since_id=1234', :headers => {'Foo' => 'Bar'})
90
+ @client.expects(:get).with('/statuses/friends_timeline.json?since_id=1234', {'Foo' => 'Bar'}).returns(response)
91
+ Twitter::Request.get(@client, '/statuses/friends_timeline.json?since_id=1234', :headers => {'Foo' => 'Bar'})
92
92
  end
93
93
  end
94
94
 
95
95
  context "new post request" do
96
96
  setup do
97
- @base = mock('twitter base')
98
- @request = Twitter::Request.new(@base, :post, '/statuses/update.json', {:body => {:status => 'Woohoo!'}})
97
+ @client = mock('twitter client')
98
+ @request = Twitter::Request.new(@client, :post, '/statuses/update.json', {:body => {:status => 'Woohoo!'}})
99
99
  end
100
100
 
101
101
  should "allow setting body and headers" do
@@ -104,8 +104,8 @@ class RequestTest < Test::Unit::TestCase
104
104
  stubs(:code).returns('200')
105
105
  end
106
106
 
107
- @base.expects(:post).with('/statuses/update.json', {:status => 'Woohoo!'}, {'Foo' => 'Bar'}).returns(response)
108
- Twitter::Request.post(@base, '/statuses/update.json', :body => {:status => 'Woohoo!'}, :headers => {'Foo' => 'Bar'})
107
+ @client.expects(:post).with('/statuses/update.json', {:status => 'Woohoo!'}, {'Foo' => 'Bar'}).returns(response)
108
+ Twitter::Request.post(@client, '/statuses/update.json', :body => {:status => 'Woohoo!'}, :headers => {'Foo' => 'Bar'})
109
109
  end
110
110
 
111
111
  context "performing request" do
@@ -115,7 +115,7 @@ class RequestTest < Test::Unit::TestCase
115
115
  stubs(:code).returns('200')
116
116
  end
117
117
 
118
- @base.expects(:post).returns(response)
118
+ @client.expects(:post).returns(response)
119
119
  @object = @request.perform
120
120
  end
121
121
 
@@ -126,7 +126,7 @@ class RequestTest < Test::Unit::TestCase
126
126
 
127
127
  should "have post shortcut to initialize and perform all in one" do
128
128
  Twitter::Request.any_instance.expects(:perform).returns(nil)
129
- Twitter::Request.post(@base, '/foo')
129
+ Twitter::Request.post(@client, '/foo')
130
130
  end
131
131
  end
132
132
 
@@ -134,69 +134,69 @@ class RequestTest < Test::Unit::TestCase
134
134
  setup do
135
135
  oauth = Twitter::OAuth.new('token', 'secret')
136
136
  oauth.authorize_from_access('atoken', 'asecret')
137
- @base = Twitter::Base.new(oauth)
137
+ @client = Twitter::Base.new(oauth)
138
138
  end
139
139
 
140
140
  should "not raise error for 200" do
141
141
  stub_get('http://twitter.com:80/foo', '', ['200'])
142
142
  lambda {
143
- Twitter::Request.get(@base, '/foo')
143
+ Twitter::Request.get(@client, '/foo')
144
144
  }.should_not raise_error
145
145
  end
146
146
 
147
147
  should "not raise error for 304" do
148
148
  stub_get('http://twitter.com:80/foo', '', ['304'])
149
149
  lambda {
150
- Twitter::Request.get(@base, '/foo')
150
+ Twitter::Request.get(@client, '/foo')
151
151
  }.should_not raise_error
152
152
  end
153
153
 
154
154
  should "raise RateLimitExceeded for 400" do
155
155
  stub_get('http://twitter.com:80/foo', 'rate_limit_exceeded.json', ['400'])
156
156
  lambda {
157
- Twitter::Request.get(@base, '/foo')
157
+ Twitter::Request.get(@client, '/foo')
158
158
  }.should raise_error(Twitter::RateLimitExceeded)
159
159
  end
160
160
 
161
161
  should "raise Unauthorized for 401" do
162
162
  stub_get('http://twitter.com:80/foo', '', ['401'])
163
163
  lambda {
164
- Twitter::Request.get(@base, '/foo')
164
+ Twitter::Request.get(@client, '/foo')
165
165
  }.should raise_error(Twitter::Unauthorized)
166
166
  end
167
167
 
168
168
  should "raise General for 403" do
169
169
  stub_get('http://twitter.com:80/foo', '', ['403'])
170
170
  lambda {
171
- Twitter::Request.get(@base, '/foo')
171
+ Twitter::Request.get(@client, '/foo')
172
172
  }.should raise_error(Twitter::General)
173
173
  end
174
174
 
175
175
  should "raise NotFound for 404" do
176
176
  stub_get('http://twitter.com:80/foo', '', ['404'])
177
177
  lambda {
178
- Twitter::Request.get(@base, '/foo')
178
+ Twitter::Request.get(@client, '/foo')
179
179
  }.should raise_error(Twitter::NotFound)
180
180
  end
181
181
 
182
182
  should "raise InformTwitter for 500" do
183
183
  stub_get('http://twitter.com:80/foo', '', ['500'])
184
184
  lambda {
185
- Twitter::Request.get(@base, '/foo')
185
+ Twitter::Request.get(@client, '/foo')
186
186
  }.should raise_error(Twitter::InformTwitter)
187
187
  end
188
188
 
189
189
  should "raise Unavailable for 502" do
190
190
  stub_get('http://twitter.com:80/foo', '', ['502'])
191
191
  lambda {
192
- Twitter::Request.get(@base, '/foo')
192
+ Twitter::Request.get(@client, '/foo')
193
193
  }.should raise_error(Twitter::Unavailable)
194
194
  end
195
195
 
196
196
  should "raise Unavailable for 503" do
197
197
  stub_get('http://twitter.com:80/foo', '', ['503'])
198
198
  lambda {
199
- Twitter::Request.get(@base, '/foo')
199
+ Twitter::Request.get(@client, '/foo')
200
200
  }.should raise_error(Twitter::Unavailable)
201
201
  end
202
202
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jnunemaker-twitter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Nunemaker
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-10 00:00:00 -07:00
12
+ date: 2009-04-11 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -110,11 +110,13 @@ files:
110
110
  - examples/connect.rb
111
111
  - examples/friendship_existance.rb
112
112
  - examples/helpers/config_store.rb
113
+ - examples/httpauth.rb
113
114
  - examples/search.rb
114
115
  - examples/timeline.rb
115
116
  - examples/update.rb
116
117
  - lib/twitter.rb
117
118
  - lib/twitter/base.rb
119
+ - lib/twitter/httpauth.rb
118
120
  - lib/twitter/oauth.rb
119
121
  - lib/twitter/request.rb
120
122
  - lib/twitter/search.rb
@@ -128,6 +130,7 @@ files:
128
130
  - test/fixtures/user_timeline.json
129
131
  - test/test_helper.rb
130
132
  - test/twitter/base_test.rb
133
+ - test/twitter/httpauth_test.rb
131
134
  - test/twitter/oauth_test.rb
132
135
  - test/twitter/request_test.rb
133
136
  - test/twitter/search_test.rb
@@ -161,6 +164,7 @@ summary: wrapper for the twitter api (oauth only)
161
164
  test_files:
162
165
  - test/test_helper.rb
163
166
  - test/twitter/base_test.rb
167
+ - test/twitter/httpauth_test.rb
164
168
  - test/twitter/oauth_test.rb
165
169
  - test/twitter/request_test.rb
166
170
  - test/twitter/search_test.rb
@@ -168,6 +172,7 @@ test_files:
168
172
  - examples/connect.rb
169
173
  - examples/friendship_existance.rb
170
174
  - examples/helpers/config_store.rb
175
+ - examples/httpauth.rb
171
176
  - examples/search.rb
172
177
  - examples/timeline.rb
173
178
  - examples/update.rb