rubytter 1.3.2 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/VERSION +1 -1
  2. data/lib/rubytter.rb +80 -74
  3. data/spec/rubytter_spec.rb +40 -29
  4. metadata +16 -5
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.3.2
1
+ 1.4.0
data/lib/rubytter.rb CHANGED
@@ -13,9 +13,6 @@ require 'rubytter/oauth_rubytter'
13
13
  class Rubytter
14
14
  VERSION = File.read(File.join(File.dirname(__FILE__), '../VERSION')).strip
15
15
 
16
- HOST = 'api.twitter.com'
17
- SEARCH_HOST = 'search.twitter.com'
18
-
19
16
  class APIError < StandardError
20
17
  attr_reader :response
21
18
  def initialize(msg, response = nil)
@@ -25,7 +22,7 @@ class Rubytter
25
22
  end
26
23
 
27
24
  attr_reader :login
28
- attr_accessor :header
25
+ attr_accessor :host, :header, :path_prefix
29
26
 
30
27
  def initialize(login = nil, password = nil, options = {})
31
28
  @login = login
@@ -34,75 +31,77 @@ class Rubytter
34
31
  end
35
32
 
36
33
  def setup(options)
34
+ @host = options[:host] || 'api.twitter.com'
37
35
  @header = {'User-Agent' => "Rubytter/#{VERSION} (http://github.com/jugyo/rubytter)"}
38
36
  @header.merge!(options[:header]) if options[:header]
39
37
  @app_name = options[:app_name]
40
38
  @connection = Connection.new(options)
41
39
  @connection_for_search = Connection.new(options.merge({:enable_ssl => false}))
40
+ @path_prefix = options[:path_prefix] || '/1'
42
41
  end
43
42
 
44
43
  def self.api_settings
45
44
  # method name path for API http method
46
45
  "
47
- update_status /1/statuses/update post
48
- remove_status /1/statuses/destroy/%s delete
49
- public_timeline /1/statuses/public_timeline
50
- home_timeline /1/statuses/home_timeline
51
- friends_timeline /1/statuses/friends_timeline
52
- replies /1/statuses/replies
53
- mentions /1/statuses/mentions
54
- user_timeline /1/statuses/user_timeline/%s
55
- show /1/statuses/show/%s
56
- friends /1/statuses/friends/%s
57
- followers /1/statuses/followers/%s
58
- retweet /1/statuses/retweet/%s post
59
- retweets /1/statuses/retweets/%s
60
- retweeted_by_me /1/statuses/retweeted_by_me
61
- retweeted_to_me /1/statuses/retweeted_to_me
62
- retweets_of_me /1/statuses/retweets_of_me
63
- user /1/users/show/%s
64
- direct_messages /1/direct_messages
65
- sent_direct_messages /1/direct_messages/sent
66
- send_direct_message /1/direct_messages/new post
67
- remove_direct_message /1/direct_messages/destroy/%s delete
68
- follow /1/friendships/create/%s post
69
- leave /1/friendships/destroy/%s delete
70
- friendship_exists /1/friendships/exists
71
- followers_ids /1/followers/ids/%s
72
- friends_ids /1/friends/ids/%s
73
- favorites /1/favorites/%s
74
- favorite /1/favorites/create/%s post
75
- remove_favorite /1/favorites/destroy/%s delete
76
- verify_credentials /1/account/verify_credentials get
77
- end_session /1/account/end_session post
78
- update_delivery_device /1/account/update_delivery_device post
79
- update_profile_colors /1/account/update_profile_colors post
80
- limit_status /1/account/rate_limit_status
81
- update_profile /1/account/update_profile post
82
- enable_notification /1/notifications/follow/%s post
83
- disable_notification /1/notifications/leave/%s post
84
- block /1/blocks/create/%s post
85
- unblock /1/blocks/destroy/%s delete
86
- block_exists /1/blocks/exists/%s get
87
- blocking /1/blocks/blocking get
88
- blocking_ids /1/blocks/blocking/ids get
89
- saved_searches /1/saved_searches get
90
- saved_search /1/saved_searches/show/%s get
91
- create_saved_search /1/saved_searches/create post
92
- remove_saved_search /1/saved_searches/destroy/%s delete
93
- create_list /1/:user/lists post
94
- update_list /1/:user/lists/%s put
95
- delete_list /1/:user/lists/%s delete
96
- lists /1/%s/lists
97
- lists_followers /1/%s/lists/memberships
98
- list_statuses /1/%s/lists/%s/statuses
99
- list /1/%s/lists/%s
100
- list_members /1/%s/%s/members
101
- add_member_to_list /1/:user/%s/members post
102
- remove_member_from_list /1/:user/%s/members delete
103
- list_following /1/%s/%s/subscribers
104
- follow_list /1/%s/%s/subscribers post
105
- remove_list /1/%s/%s/subscribers delete
46
+ update_status /statuses/update post
47
+ remove_status /statuses/destroy/%s delete
48
+ public_timeline /statuses/public_timeline
49
+ home_timeline /statuses/home_timeline
50
+ friends_timeline /statuses/friends_timeline
51
+ replies /statuses/replies
52
+ mentions /statuses/mentions
53
+ user_timeline /statuses/user_timeline/%s
54
+ show /statuses/show/%s
55
+ friends /statuses/friends/%s
56
+ followers /statuses/followers/%s
57
+ retweet /statuses/retweet/%s post
58
+ retweets /statuses/retweets/%s
59
+ retweeted_by_me /statuses/retweeted_by_me
60
+ retweeted_to_me /statuses/retweeted_to_me
61
+ retweets_of_me /statuses/retweets_of_me
62
+ user /users/show/%s
63
+ direct_messages /direct_messages
64
+ sent_direct_messages /direct_messages/sent
65
+ send_direct_message /direct_messages/new post
66
+ remove_direct_message /direct_messages/destroy/%s delete
67
+ follow /friendships/create/%s post
68
+ leave /friendships/destroy/%s delete
69
+ friendship_exists /friendships/exists
70
+ followers_ids /followers/ids/%s
71
+ friends_ids /friends/ids/%s
72
+ favorites /favorites/%s
73
+ favorite /favorites/create/%s post
74
+ remove_favorite /favorites/destroy/%s delete
75
+ verify_credentials /account/verify_credentials get
76
+ end_session /account/end_session post
77
+ update_delivery_device /account/update_delivery_device post
78
+ update_profile_colors /account/update_profile_colors post
79
+ limit_status /account/rate_limit_status
80
+ update_profile /account/update_profile post
81
+ enable_notification /notifications/follow/%s post
82
+ disable_notification /notifications/leave/%s post
83
+ block /blocks/create/%s post
84
+ unblock /blocks/destroy/%s delete
85
+ block_exists /blocks/exists/%s get
86
+ blocking /blocks/blocking get
87
+ blocking_ids /blocks/blocking/ids get
88
+ saved_searches /saved_searches get
89
+ saved_search /saved_searches/show/%s get
90
+ create_saved_search /saved_searches/create post
91
+ remove_saved_search /saved_searches/destroy/%s delete
92
+ create_list /:user/lists post
93
+ update_list /:user/lists/%s put
94
+ delete_list /:user/lists/%s delete
95
+ lists /%s/lists
96
+ lists_followers /%s/lists/memberships
97
+ list_statuses /%s/lists/%s/statuses
98
+ list /%s/lists/%s
99
+ list_members /%s/%s/members
100
+ add_member_to_list /:user/%s/members post
101
+ remove_member_from_list /:user/%s/members delete
102
+ list_following /%s/%s/subscribers
103
+ follow_list /%s/%s/subscribers post
104
+ remove_list /%s/%s/subscribers delete
106
105
  ".strip.split("\n").map{|line| line.strip.split(/\s+/)}
107
106
  end
108
107
 
@@ -168,31 +167,31 @@ class Rubytter
168
167
  path += '.json'
169
168
  param_str = '?' + to_param_str(params)
170
169
  path = path + param_str unless param_str.empty?
171
- req = create_request(Net::HTTP::Get.new(path))
172
- structize(http_request(HOST, req))
170
+ req = create_request(Net::HTTP::Get.new(path_prefix + path))
171
+ structize(http_request(@host, req))
173
172
  end
174
173
 
175
174
  def post(path, params = {})
176
175
  path += '.json'
177
176
  param_str = to_param_str(params)
178
- req = create_request(Net::HTTP::Post.new(path))
179
- structize(http_request(HOST, req, param_str))
177
+ req = create_request(Net::HTTP::Post.new(path_prefix + path))
178
+ structize(http_request(@host, req, param_str))
180
179
  end
181
180
 
182
181
  def delete(path, params = {})
183
182
  path += '.json'
184
183
  param_str = to_param_str(params)
185
- req = create_request(Net::HTTP::Delete.new(path))
186
- structize(http_request(HOST, req, param_str))
184
+ req = create_request(Net::HTTP::Delete.new(path_prefix + path))
185
+ structize(http_request(@host, req, param_str))
187
186
  end
188
187
 
189
188
  def search(query, params = {})
190
189
  path = '/search.json'
191
190
  param_str = '?' + to_param_str(params.merge({:q => query}))
192
191
  path = path + param_str unless param_str.empty?
193
- req = create_request(Net::HTTP::Get.new(path), false)
192
+ req = create_request(Net::HTTP::Get.new(path_prefix + path), false)
194
193
 
195
- json_data = http_request(SEARCH_HOST, req, nil, @connection_for_search)
194
+ json_data = http_request("#{@host}", req, nil, @connection_for_search)
196
195
  structize(
197
196
  json_data['results'].map do |result|
198
197
  search_result_to_hash(result)
@@ -201,11 +200,11 @@ class Rubytter
201
200
  end
202
201
 
203
202
  def search_user(query, params = {})
204
- path = '/1/users/search.json'
203
+ path = '/users/search.json'
205
204
  param_str = '?' + to_param_str(params.merge({:q => query}))
206
205
  path = path + param_str unless param_str.empty?
207
- req = create_request(Net::HTTP::Get.new(path))
208
- structize(http_request(HOST, req))
206
+ req = create_request(Net::HTTP::Get.new(path_prefix + path))
207
+ structize(http_request(@host, req))
209
208
  end
210
209
 
211
210
  def search_result_to_hash(json)
@@ -260,6 +259,13 @@ class Rubytter
260
259
  self[:id]
261
260
  end
262
261
 
262
+ def to_hash(obj = self)
263
+ obj.inject({}) {|memo, (key, value)|
264
+ memo[key] = (value.kind_of? obj.class) ? to_hash(value) : value
265
+ memo
266
+ }
267
+ end
268
+
263
269
  def method_missing(name, *args)
264
270
  self[name]
265
271
  end
@@ -20,87 +20,87 @@ class Rubytter
20
20
 
21
21
  it 'should get or post' do
22
22
  # TODO: split specs
23
- @rubytter.should_receive(:get).with('/1/statuses/replies', {})
23
+ @rubytter.should_receive(:get).with('/statuses/replies', {})
24
24
  @rubytter.replies
25
25
 
26
- @rubytter.should_receive(:get).with('/1/statuses/replies', {:page => 2})
26
+ @rubytter.should_receive(:get).with('/statuses/replies', {:page => 2})
27
27
  @rubytter.replies(:page => 2)
28
28
 
29
- @rubytter.should_receive(:get).with('/1/statuses/user_timeline/1', {})
29
+ @rubytter.should_receive(:get).with('/statuses/user_timeline/1', {})
30
30
  @rubytter.user_timeline(1)
31
31
 
32
- @rubytter.should_receive(:get).with('/1/users/show/1', {})
32
+ @rubytter.should_receive(:get).with('/users/show/1', {})
33
33
  @rubytter.user(1)
34
34
 
35
- @rubytter.should_receive(:delete).with('/1/statuses/destroy/1', {})
35
+ @rubytter.should_receive(:delete).with('/statuses/destroy/1', {})
36
36
  @rubytter.remove_status(1)
37
37
  end
38
38
 
39
39
  # direct_messages
40
40
 
41
41
  it 'should respond to direct_messages' do
42
- @rubytter.should_receive(:get).with('/1/direct_messages', {})
42
+ @rubytter.should_receive(:get).with('/direct_messages', {})
43
43
  @rubytter.direct_messages()
44
44
  end
45
45
 
46
46
  it 'should respond to sent_direct_messages' do
47
- @rubytter.should_receive(:get).with('/1/direct_messages/sent', {})
47
+ @rubytter.should_receive(:get).with('/direct_messages/sent', {})
48
48
  @rubytter.sent_direct_messages()
49
49
  end
50
50
 
51
51
  it 'should respond to send_direct_message' do
52
- @rubytter.should_receive(:post).with('/1/direct_messages/new', {})
52
+ @rubytter.should_receive(:post).with('/direct_messages/new', {})
53
53
  @rubytter.send_direct_message()
54
54
  end
55
55
 
56
56
  it 'should respond to destroy_direct_message' do
57
- @rubytter.should_receive(:delete).with('/1/direct_messages/destroy/1', {})
57
+ @rubytter.should_receive(:delete).with('/direct_messages/destroy/1', {})
58
58
  @rubytter.remove_direct_message(1)
59
59
  end
60
60
 
61
61
  it 'should respond to direct_message' do
62
- @rubytter.should_receive(:post).with('/1/direct_messages/new', {:user => 'test', :text => 'aaaaaaaaaaaaa'})
62
+ @rubytter.should_receive(:post).with('/direct_messages/new', {:user => 'test', :text => 'aaaaaaaaaaaaa'})
63
63
  @rubytter.direct_message('test', 'aaaaaaaaaaaaa')
64
64
  end
65
65
 
66
66
  # statuses
67
67
 
68
68
  it 'should respond to update' do
69
- @rubytter.should_receive(:post).with('/1/statuses/update', {:status => 'test'})
69
+ @rubytter.should_receive(:post).with('/statuses/update', {:status => 'test'})
70
70
  @rubytter.update('test')
71
71
  end
72
72
 
73
73
  it 'should respond to update_status' do
74
- @rubytter.should_receive(:post).with('/1/statuses/update', {:status => 'test'})
74
+ @rubytter.should_receive(:post).with('/statuses/update', {:status => 'test'})
75
75
  @rubytter.update_status(:status => 'test')
76
76
  end
77
77
 
78
78
  # friendship
79
79
 
80
80
  it 'should respond to follow' do
81
- @rubytter.should_receive(:post).with('/1/friendships/create/test', {})
81
+ @rubytter.should_receive(:post).with('/friendships/create/test', {})
82
82
  @rubytter.follow('test')
83
83
  end
84
84
 
85
85
  it 'should respond to leave' do
86
- @rubytter.should_receive(:delete).with('/1/friendships/destroy/test', {})
86
+ @rubytter.should_receive(:delete).with('/friendships/destroy/test', {})
87
87
  @rubytter.leave('test')
88
88
  end
89
89
 
90
90
  it 'should respond to friendship_exists' do
91
- @rubytter.should_receive(:get).with('/1/friendships/exists', {:user_a => 'a', :user_b => 'b'})
91
+ @rubytter.should_receive(:get).with('/friendships/exists', {:user_a => 'a', :user_b => 'b'})
92
92
  @rubytter.friendship_exists(:user_a => 'a', :user_b => 'b')
93
93
  end
94
94
 
95
95
  # Social Graph Methods
96
96
 
97
97
  it 'should respond to followers_ids' do
98
- @rubytter.should_receive(:get).with('/1/friends/ids/test', {})
98
+ @rubytter.should_receive(:get).with('/friends/ids/test', {})
99
99
  @rubytter.friends_ids('test')
100
100
  end
101
101
 
102
102
  it 'should respond to followers_ids' do
103
- @rubytter.should_receive(:get).with('/1/followers/ids/test', {})
103
+ @rubytter.should_receive(:get).with('/followers/ids/test', {})
104
104
  @rubytter.followers_ids('test')
105
105
  end
106
106
 
@@ -111,8 +111,8 @@ class Rubytter
111
111
 
112
112
  it 'should respond to search (1)' do
113
113
  @rubytter.should_receive(:http_request) do |host, req, param_str|
114
- req.path.should == '/search.json?q=test'
115
- host.should == 'search.twitter.com'
114
+ req.path.should == '/1/search.json?q=test'
115
+ host.should == 'api.twitter.com'
116
116
  {'results' => []}
117
117
  end
118
118
  @rubytter.search('test')
@@ -193,6 +193,17 @@ class Rubytter
193
193
  struct.regex.should == nil
194
194
  end
195
195
 
196
+ it 'should convert to hash using to_hash' do
197
+ hash = {
198
+ :a => 'a',
199
+ 'b' => 1,
200
+ :c => {:a => 1, :b => 2}
201
+ }
202
+ struct = @rubytter.structize(hash)
203
+ new_hash = struct.to_hash
204
+ new_hash.should == {:a=>"a", :b=>1, :c=>{:a=>1, :b=>2}}
205
+ end
206
+
196
207
  it 'should create struct from json(Array)' do
197
208
  data = [
198
209
  {"status" => {"text" => "foo", "user" => {"screen_name" => "jugyo_foo"}}},
@@ -316,32 +327,32 @@ class Rubytter
316
327
  end
317
328
 
318
329
  it 'should POST /:user/list to create list' do
319
- @rubytter.should_receive(:post).with("/1/test/lists", {:name=>"foo"})
330
+ @rubytter.should_receive(:post).with("/test/lists", {:name=>"foo"})
320
331
  @rubytter.create_list('foo')
321
332
  end
322
333
 
323
334
  it 'should PUT /:user/list to update list' do
324
- @rubytter.should_receive(:put).with("/1/test/lists/foo", {})
335
+ @rubytter.should_receive(:put).with("/test/lists/foo", {})
325
336
  @rubytter.update_list('foo')
326
337
  end
327
338
 
328
339
  it 'should DELETE /:user/list to delete list' do
329
- @rubytter.should_receive(:delete).with("/1/test/lists/foo", {})
340
+ @rubytter.should_receive(:delete).with("/test/lists/foo", {})
330
341
  @rubytter.delete_list('foo')
331
342
  end
332
343
 
333
344
  it 'should GET lists for specified user' do
334
- @rubytter.should_receive(:get).with("/1/jugyo/lists", {})
345
+ @rubytter.should_receive(:get).with("/jugyo/lists", {})
335
346
  @rubytter.lists('jugyo')
336
347
  end
337
348
 
338
349
  it 'should add member to list' do
339
- @rubytter.should_receive(:post).with("/1/test/foo/members", {:id=>"jugyo"})
350
+ @rubytter.should_receive(:post).with("/test/foo/members", {:id=>"jugyo"})
340
351
  @rubytter.add_member_to_list('foo', 'jugyo')
341
352
  end
342
353
 
343
354
  it 'should remove member to list' do
344
- @rubytter.should_receive(:delete).with("/1/test/foo/members", {:id=>"jugyo"})
355
+ @rubytter.should_receive(:delete).with("/test/foo/members", {:id=>"jugyo"})
345
356
  @rubytter.remove_member_from_list('foo', 'jugyo')
346
357
  end
347
358
 
@@ -352,7 +363,7 @@ class Rubytter
352
363
  rubytter = OAuthRubytter.new(access_token)
353
364
  response = simple_mock(:body => '{}', :code => '200')
354
365
  access_token.should_receive(:post).with(
355
- "/1/statuses/update.json",
366
+ "/statuses/update.json",
356
367
  {'status' => 'test'},
357
368
  {"User-Agent"=>"Rubytter/#{Rubytter::VERSION} (http://github.com/jugyo/rubytter)"}
358
369
  ).and_return(response)
@@ -364,7 +375,7 @@ class Rubytter
364
375
  rubytter = OAuthRubytter.new(access_token)
365
376
  response = simple_mock(:body => '{}', :code => '200')
366
377
  access_token.should_receive(:get).with(
367
- '/1/statuses/friends_timeline.json',
378
+ '/statuses/friends_timeline.json',
368
379
  {"User-Agent"=>"Rubytter/#{Rubytter::VERSION} (http://github.com/jugyo/rubytter)"}
369
380
  ).and_return(response)
370
381
  rubytter.friends_timeline
@@ -375,7 +386,7 @@ class Rubytter
375
386
  rubytter = OAuthRubytter.new(access_token)
376
387
  response = simple_mock(:body => '{}', :code => '200')
377
388
  access_token.should_receive(:get).with(
378
- '/1/statuses/friends_timeline.json?page=2',
389
+ '/statuses/friends_timeline.json?page=2',
379
390
  {"User-Agent"=>"Rubytter/#{Rubytter::VERSION} (http://github.com/jugyo/rubytter)"}
380
391
  ).and_return(response)
381
392
  rubytter.friends_timeline(:page => 2)
@@ -403,7 +414,7 @@ class Rubytter
403
414
  connection_for_search.enable_ssl.should == false
404
415
 
405
416
  @ssl_rubytter.should_receive(:http_request).
406
- with('search.twitter.com', anything, nil, connection_for_search).
417
+ with('api.twitter.com', anything, nil, connection_for_search).
407
418
  and_return({'results' => []})
408
419
  @ssl_rubytter.search('rubytter')
409
420
  end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubytter
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 7
4
5
  prerelease: false
5
6
  segments:
6
7
  - 1
7
- - 3
8
- - 2
9
- version: 1.3.2
8
+ - 4
9
+ - 0
10
+ version: 1.4.0
10
11
  platform: ruby
11
12
  authors:
12
13
  - jugyo
@@ -14,16 +15,18 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-05-13 00:00:00 +09:00
18
+ date: 2010-06-22 00:00:00 +09:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: json
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ">="
26
28
  - !ruby/object:Gem::Version
29
+ hash: 21
27
30
  segments:
28
31
  - 1
29
32
  - 1
@@ -35,9 +38,11 @@ dependencies:
35
38
  name: oauth
36
39
  prerelease: false
37
40
  requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
38
42
  requirements:
39
43
  - - ">="
40
44
  - !ruby/object:Gem::Version
45
+ hash: 31
41
46
  segments:
42
47
  - 0
43
48
  - 3
@@ -49,9 +54,11 @@ dependencies:
49
54
  name: rspec
50
55
  prerelease: false
51
56
  requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
52
58
  requirements:
53
59
  - - ">="
54
60
  - !ruby/object:Gem::Version
61
+ hash: 3
55
62
  segments:
56
63
  - 0
57
64
  version: "0"
@@ -102,23 +109,27 @@ rdoc_options:
102
109
  require_paths:
103
110
  - lib
104
111
  required_ruby_version: !ruby/object:Gem::Requirement
112
+ none: false
105
113
  requirements:
106
114
  - - ">="
107
115
  - !ruby/object:Gem::Version
116
+ hash: 3
108
117
  segments:
109
118
  - 0
110
119
  version: "0"
111
120
  required_rubygems_version: !ruby/object:Gem::Requirement
121
+ none: false
112
122
  requirements:
113
123
  - - ">="
114
124
  - !ruby/object:Gem::Version
125
+ hash: 3
115
126
  segments:
116
127
  - 0
117
128
  version: "0"
118
129
  requirements: []
119
130
 
120
131
  rubyforge_project: rubytter
121
- rubygems_version: 1.3.6
132
+ rubygems_version: 1.3.7
122
133
  signing_key:
123
134
  specification_version: 3
124
135
  summary: Simple twitter client.