jnunemaker-twitter 0.5.3 → 0.6.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/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