ws-aboutme 0.5.1

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/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 Aboutme webservice API client Development Team
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,30 @@
1
+ = WebService::Aboutme - Aboutme web service API client
2
+
3
+ == SYNOPSIS
4
+
5
+ require 'rubygems'
6
+ require 'webservice/aboutme'
7
+
8
+ client = WebService::Aboutme::API.new
9
+
10
+ # look up users with nickname 'aboutme'
11
+ response = client.search_user(:nickname => 'aboutme')
12
+ response.users.each do |user|
13
+ # display information of this user or something...
14
+ end
15
+
16
+ == NOTES
17
+
18
+ See http://webservice.nifty.com/aboutme/ for WebAPI documentation.
19
+
20
+ == Installation
21
+
22
+ sudo gem install ws-aboutme
23
+
24
+ == License
25
+
26
+ WebService::Aboutme is released under the MIT license.
27
+
28
+ == Authors
29
+
30
+ SAWADA Tadashi <moc.liamg.cesare+ws-aboutme@gmail.com>
data/Rakefile ADDED
@@ -0,0 +1,62 @@
1
+ # -*- mode: ruby; coding: utf-8 -*-
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+ require 'rake/clean'
6
+ require 'rake/packagetask'
7
+ require 'rake/gempackagetask'
8
+ require 'rake/rdoctask'
9
+ require 'rake/testtask'
10
+
11
+ dir = File.dirname(__FILE__)
12
+ $LOAD_PATH.unshift(File.join(dir, "lib"))
13
+
14
+ require 'webservice/aboutme/version'
15
+
16
+ spec = Gem::Specification.new do |s|
17
+ s.name = 'ws-aboutme'
18
+ s.version = WebService::Aboutme::Version.to_version
19
+ s.author = 'SAWADA Tadashi'
20
+ s.email = 'moc.liamg.cesare+ws-aboutme@gmail.com'
21
+ s.platform = Gem::Platform::RUBY
22
+ s.summary = 'API client Library for @nifty Aboutme web service'
23
+
24
+ files = FileList["{test,lib,examples,doc}/**/*"].exclude("doc/rdoc").to_a
25
+ files |= ['Rakefile', 'MIT-LICENSE']
26
+ s.files = files
27
+
28
+ s.require_path = 'lib'
29
+ s.has_rdoc = true
30
+ s.rdoc_options = ['--charset', 'UTF-8', '--main', 'README']
31
+ s.extra_rdoc_files = ['README']
32
+
33
+ s.required_ruby_version = ">= 1.8.2"
34
+ end
35
+
36
+ if $0 == __FILE__
37
+ Gem::manage_gems
38
+ Gem::Builder.new(spec).build
39
+ end
40
+
41
+ task :default => ['clean', 'clobber', 'test', 'rdoc', 'package']
42
+
43
+ Rake::GemPackageTask.new(spec) do |pkg|
44
+ pkg.need_tar_gz = true
45
+ pkg.need_tar_bz2 = true
46
+ pkg.need_zip = true
47
+ end
48
+
49
+
50
+ Rake::TestTask.new do |t|
51
+ t.libs << 'test'
52
+ t.test_files = FileList['test/tc_*.rb']
53
+ t.verbose = true
54
+ end
55
+
56
+
57
+ Rake::RDocTask.new('rdoc') do |t|
58
+ t.rdoc_dir = 'doc/rdoc'
59
+ t.rdoc_files.include('README', 'lib/**/*.rb')
60
+ t.main = 'README'
61
+ t.title = 'WebService::Aboutme Documentation'
62
+ end
@@ -0,0 +1,32 @@
1
+ #--
2
+ # Copyright (c) 2007 Aboutme webservice API client Development Team
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ module WebService # :nodoc:
25
+ module Aboutme # :nodoc:
26
+ end
27
+ end
28
+
29
+ $KCODE = 'u'
30
+ require 'jcode'
31
+
32
+ require 'webservice/aboutme/api'
@@ -0,0 +1,505 @@
1
+ require 'date'
2
+ require 'net/http'
3
+ require 'uri'
4
+ require 'rexml/document'
5
+
6
+ require 'webservice/aboutme/xmlobjectmapping'
7
+ require 'webservice/aboutme/version'
8
+
9
+ module WebService #:nodoc:
10
+ module Aboutme #:nodoc:
11
+
12
+ REQUEST_URI_BASE = URI.parse('http://api.aboutme.jp/api/v1/')
13
+
14
+ DEFAULT_OPEN_TIMEOUT = 10
15
+ DEFAULT_READ_TIMEOUT = 20
16
+
17
+ class API
18
+
19
+ attr_accessor :config
20
+
21
+ # Takes initialization parameters or a block to override default setttings.
22
+ # You can pass parameters like this,
23
+ # client = WebService::Aboutme::API.new(
24
+ # :open_timeout => 5,
25
+ # :read_timeout => 7,
26
+ # )
27
+ # or, override default parameters with a block,
28
+ # client = WebService::Aboutme::API.new do |c|
29
+ # c.open_timeout = 5
30
+ # c.read_timeout = 7
31
+ # end
32
+ #
33
+ # Or, just call new with no argument to create default instance.
34
+ # client = WebService::Aboutme::API.new
35
+ #
36
+ # See Config class for further information.
37
+ #
38
+ def initialize(args = {}, &block)
39
+ uri = REQUEST_URI_BASE
40
+ @config = Config.new do |c|
41
+ c.request_path_base = uri.path
42
+ c.request_domain = args[:request_domain] || REQUEST_URI_BASE.host
43
+ c.request_port = args[:request_port] || REQUEST_URI_BASE.port
44
+ c.open_timeout = args[:open_timeout] || DEFAULT_OPEN_TIMEOUT
45
+ c.read_timeout = args[:read_timeout] || DEFAULT_READ_TIMEOUT
46
+ c.user_agent = "Aboutme API client for Ruby ver-#{Version.to_version}"
47
+ end
48
+
49
+ if block_given?
50
+ block.call @config
51
+ end
52
+ end
53
+
54
+ def request(request_class, response_class, params = {})
55
+ req = request_class.new(@config)
56
+ response = req.request(params)
57
+ xml = REXML::Document.new(response.body)
58
+ response_class.unmarshal(xml.root)
59
+ end
60
+ private :request
61
+
62
+ # Takes numeric id and returns information of the user.
63
+ #
64
+ # response = client.show_user(1) # => #<ShowUserResponse>
65
+ # user = response.user
66
+ #
67
+ def show_user(id)
68
+ request(ShowUserRequest, ShowUserResponse, :id => id)
69
+ end
70
+
71
+ # Looks up and returns a list of users.
72
+ # Lookup key should be one of :nickname, :interest, :followers, or :contacts.
73
+ #
74
+ # response = client.search_user(:nickname => 'aboutme-user',
75
+ # :order => 'now_to_old,
76
+ # :hits => 20,
77
+ # :page => 1)
78
+ # response.users.each {|user| do_something }
79
+ #
80
+ def search_user(params = {})
81
+ request(SearchUserRequest, SearchUserResponse, params)
82
+ end
83
+
84
+ # Takes numeric id and returns information of the question.
85
+ #
86
+ # response = client.show_question(123) # => #<ShowQuestionResponse>
87
+ # question = response.question
88
+ #
89
+ def show_question(id)
90
+ request(ShowQuestionRequest, ShowQuestionResponse, :id => id)
91
+ end
92
+
93
+ # Looks up and returns a list of questions.
94
+ # Lookup key should be one of :owenr, :answerer, or :text.
95
+ #
96
+ # response = client.search_question(:owner => 'aboutme-user',
97
+ # :order => 'hot',
98
+ # :hits => 20,
99
+ # :page => 1)
100
+ # response.questions.each {|q| do_something }
101
+ #
102
+ def search_question(params)
103
+ request(SearchQuestionRequest, SearchQuestionResponse, params)
104
+ end
105
+
106
+ # Takes numeric id and returns information of the answer.
107
+ #
108
+ # response = client.show_question(987) # => #<ShowAnswerResponse>
109
+ # answer = response.answer
110
+ #
111
+ def show_answer(id)
112
+ request(ShowAnswerRequest, ShowAnswerResponse, :id => id)
113
+ end
114
+
115
+ # Looks up and returns a list of answers.
116
+ # Lookup key should be one of :user, :text, :gender, or :age,
117
+ # and :question is required.
118
+ #
119
+ # response = client.search_answer(:question => 987,
120
+ # :age => '30s',
121
+ # :order => 'new_to_old',
122
+ # :hits => 20,
123
+ # :page => 1)
124
+ # response.answers.each {|ans| do_something }
125
+ #
126
+ def search_answer(params)
127
+ request(SearchAnswerRequest, SearchAnswerResponse, params)
128
+ end
129
+
130
+ # Takes numeric question id and returns summary of answers for the question.
131
+ #
132
+ # response = client.show_answer_digest(987) # => #<ShowAnswerDigestResponse>
133
+ # response.digest.each {|d| do_something }
134
+ #
135
+ def show_answer_digest(id)
136
+ request(ShowAnswerDigestRequest, ShowAnswerDigestResponse, :id => id)
137
+ end
138
+ end
139
+
140
+ # The Config class contains information of the client configuration.
141
+ class Config
142
+ # base path of the request URI. You should not change this value.
143
+ attr_accessor :request_path_base
144
+
145
+ # domain name of the request URI.
146
+ attr_accessor :request_domain
147
+
148
+ # port number of the request URI.
149
+ attr_accessor :request_port
150
+
151
+ # connection timeout (in seconds).
152
+ attr_accessor :open_timeout
153
+
154
+ # IO read timeout (in seconds).
155
+ attr_accessor :read_timeout
156
+
157
+ # name of user-agent for the client.
158
+ attr_accessor :user_agent
159
+
160
+ def initialize(&block)
161
+ block.call(self)
162
+ end
163
+ end
164
+
165
+ class ValidationError < ArgumentError
166
+ end
167
+
168
+ class Request #:nodoc:
169
+
170
+ class << self
171
+ def validators(*methods)
172
+ self.class_eval do
173
+ unless defined? @param_validators
174
+ @param_validators = []
175
+ end
176
+ @param_validators += methods
177
+ end
178
+ end
179
+
180
+ def known_params(*keys)
181
+ self.class_eval do
182
+ unless defined? @known_parameters
183
+ @known_parameters = []
184
+ end
185
+ @known_parameters += keys
186
+ end
187
+ end
188
+ end
189
+
190
+
191
+ def initialize(config)
192
+ @config = config
193
+ end
194
+
195
+ def request(params = {})
196
+ validate(params)
197
+ path = create_request_path(params)
198
+ queries = collect_queries(params)
199
+ method = get_method
200
+ _request(path, method, queries)
201
+ end
202
+
203
+
204
+ private
205
+
206
+ def get_method
207
+ :get
208
+ end
209
+
210
+ def validate(params)
211
+ validators = self.class.class_eval { @param_validators }
212
+ return true if validators.nil?
213
+
214
+ errors = []
215
+ validators.each do |validator|
216
+ message = __send__ validator, params
217
+ errors << message if message
218
+ end
219
+
220
+ unless errors.empty?
221
+ raise ValidationError, errors.join("\n")
222
+ end
223
+ true
224
+ end
225
+
226
+ def collect_queries(params)
227
+ keys = self.class.class_eval { @known_parameters } || []
228
+
229
+ queries = {}
230
+ keys.each do |key|
231
+ if params.key? key
232
+ queries[key] = params[key]
233
+ end
234
+ end
235
+ queries
236
+ end
237
+
238
+ def _request(path, method = :get, params = {})
239
+ uri = create_request_uri(@config.request_path_base + path, params)
240
+ req = create_http_request(method, uri, params)
241
+ response = Net::HTTP.start(uri.host, uri.port) do |http|
242
+ http.open_timeout = @config.open_timeout
243
+ http.read_timeout = @config.read_timeout
244
+ http.request(req)
245
+ end
246
+
247
+ response
248
+ end
249
+
250
+ def create_http_request(method, uri, params)
251
+ initheader = {
252
+ 'User-Agent' => @config.user_agent
253
+ }
254
+
255
+ case method
256
+ when :get
257
+ Net::HTTP::Get.new(uri.request_uri)
258
+ when :post
259
+ req = Net::HTTP::Post.new(uri.path)
260
+ req.set_form_data(params)
261
+ req
262
+ end
263
+ end
264
+
265
+ def create_query_string(params = {})
266
+ queries = []
267
+ params.each_pair do |key, val|
268
+ queries << key.to_s + '=' + URI.encode(val.to_s)
269
+ end
270
+ queries.join('&')
271
+ end
272
+
273
+ def create_request_uri(request_path, params)
274
+ query = create_query_string(params)
275
+ URI::HTTP.build({ :host => @config.request_domain,
276
+ :port => @config.request_port,
277
+ :path => request_path,
278
+ :query => query,
279
+ })
280
+ end
281
+
282
+
283
+ def validate_id(params)
284
+ id = params[:id]
285
+ unless id
286
+ return "id missing."
287
+ end
288
+ end
289
+ end
290
+
291
+ class ShowUserRequest < Request #:nodoc:
292
+ validators :validate_id
293
+
294
+ def create_request_path(params)
295
+ id = params[:id]
296
+ "users/show/#{id}"
297
+ end
298
+ end
299
+
300
+ class SearchUserRequest < Request #:nodoc:
301
+ known_params :nickname, :interest, :followers, :contacts, :order, :hits, :page
302
+ def create_request_path(params)
303
+ "users/search"
304
+ end
305
+ end
306
+
307
+ class ShowQuestionRequest < Request #:nodoc:
308
+ validators :validate_id
309
+
310
+ def create_request_path(params)
311
+ id = params[:id]
312
+ "questions/show/#{id}"
313
+ end
314
+ end
315
+
316
+ class SearchQuestionRequest < Request #:nodoc:
317
+ known_params :owner, :answerer, :text, :order, :hits, :page
318
+
319
+ def create_request_path(params)
320
+ "questions/search"
321
+ end
322
+ end
323
+
324
+ class ShowAnswerRequest < Request #:nodoc:
325
+ validators :validate_id
326
+
327
+ def create_request_path(params)
328
+ id = params[:id]
329
+ "answers/show/#{id}"
330
+ end
331
+ end
332
+
333
+ class SearchAnswerRequest < Request #:nodoc:
334
+ known_params :question, :user, :text, :gender, :age, :order, :hits, :page
335
+
336
+ def create_request_path(params)
337
+ "answers/search"
338
+ end
339
+ end
340
+
341
+ class ShowAnswerDigestRequest < Request #:nodoc:
342
+ validators :validate_id
343
+
344
+ def create_request_path(params)
345
+ id = params[:id]
346
+ "answers/digest/#{id}"
347
+ end
348
+ end
349
+
350
+
351
+ class ResponseStatus < XmlObjectMapping::Base
352
+ attr_mapping :code, :type => :integer
353
+ attr_mapping :message
354
+ attr_mapping :language
355
+ end
356
+
357
+ class IconImages < XmlObjectMapping::Base
358
+ attr_mapping :icon
359
+ attr_mapping :small
360
+ attr_mapping :medium
361
+ attr_mapping :large
362
+ end
363
+
364
+ class Birthday < XmlObjectMapping::Base
365
+ attr_mapping :year, :type => :integer
366
+ attr_mapping :month, :type => :integer
367
+ attr_mapping :day, :type => :integer
368
+ end
369
+
370
+ class User < XmlObjectMapping::Base
371
+ attr_mapping :id, :type => :integer
372
+ attr_mapping :nickname
373
+ attr_mapping :url
374
+ attr_mapping :images, :type => IconImages
375
+ attr_mapping :gender
376
+ attr_mapping :birthday, :type => Birthday
377
+ attr_mapping :age, :type => :integer
378
+ attr_mapping :horoscope
379
+ attr_mapping :blood_type
380
+ attr_mapping :prefecture
381
+ attr_mapping :area
382
+ attr_mapping :introduction
383
+ attr_array :interests, :subnode => 'interest'
384
+ end
385
+
386
+ class Choice < XmlObjectMapping::Base
387
+ attr_mapping :priority, :type => :integer
388
+ attr_mapping :title
389
+ attr_mapping :answer_count, :type => :integer, :path => 'answers_count'
390
+ end
391
+
392
+ class Question < XmlObjectMapping::Base
393
+ attr_mapping :id, :type => :integer
394
+ attr_mapping :title
395
+ attr_mapping :url
396
+ attr_mapping :image
397
+ attr_mapping :creator, :type => User
398
+ attr_mapping :created_at, :type => :datetime
399
+ attr_array :choices, :type => Choice, :path => 'options', :subnode => 'option'
400
+ end
401
+
402
+ class Answer < XmlObjectMapping::Base
403
+ attr_mapping :id, :type => :integer
404
+ attr_mapping :title
405
+ attr_mapping :question_id, :type => :integer
406
+ attr_mapping :updated_at, :type => :datetime
407
+ attr_mapping :priority, :type => :integer
408
+ attr_mapping :answerer, :type => User
409
+ end
410
+
411
+ class AnswerDigest < XmlObjectMapping::Base
412
+ attr_mapping :id, :type => :integer
413
+ attr_mapping :count, :type => :integer, :path => 'answers_count'
414
+ attr_array :choices, :type => Choice, :path => 'options', :subnode => 'option'
415
+ end
416
+
417
+ class Summary < XmlObjectMapping::Base
418
+ attr_mapping :total, :type => :integer
419
+ attr_mapping :page, :type => :integer
420
+ attr_mapping :page_count, :type => :integer
421
+ end
422
+
423
+
424
+ class ResultBase < XmlObjectMapping::Base
425
+ attr_mapping :summary, :type => Summary
426
+ end
427
+
428
+ class SearchUserResult < ResultBase
429
+ attr_array :users, :type => User, :subnode => 'user'
430
+ end
431
+
432
+ class SearchQuestionResult < ResultBase
433
+ attr_array :questions, :type => Question, :subnode => 'question'
434
+ end
435
+
436
+ class SearchAnswerResult < ResultBase
437
+ attr_array :answers, :type => Answer, :subnode => 'answer'
438
+ end
439
+
440
+
441
+
442
+ class ResponseBase < XmlObjectMapping::Base
443
+ attr_mapping :status, :type => ResponseStatus
444
+ end
445
+
446
+ class ShowUserResponse < ResponseBase
447
+ attr_mapping :user, :type => User, :path => 'result', :subnode => 'user'
448
+ end
449
+
450
+ class SearchUserResponse < ResponseBase
451
+ attr_mapping :result, :type => SearchUserResult, :private => true
452
+ attr_accessor :summary
453
+ attr_accessor :users
454
+
455
+ private
456
+ def post_population
457
+ if @result
458
+ @summary = @result.summary
459
+ @users = @result.users
460
+ end
461
+ end
462
+ end
463
+
464
+ class ShowQuestionResponse < ResponseBase
465
+ attr_mapping :question, :type => Question, :path => 'result', :subnode => 'question'
466
+ end
467
+
468
+ class SearchQuestionResponse < ResponseBase
469
+ attr_mapping :result, :type => SearchQuestionResult, :private => true
470
+ attr_accessor :summary
471
+ attr_accessor :questions
472
+
473
+ private
474
+ def post_population
475
+ if @result
476
+ @summary = @result.summary
477
+ @questions = @result.questions
478
+ end
479
+ end
480
+ end
481
+
482
+ class ShowAnswerResponse < ResponseBase
483
+ attr_mapping :answer, :type => Answer, :path => 'result', :subnode => 'answer'
484
+ end
485
+
486
+ class SearchAnswerResponse < ResponseBase
487
+ attr_mapping :result, :type => SearchAnswerResult, :private => true
488
+ attr_accessor :summary
489
+ attr_accessor :answers
490
+
491
+ private
492
+ def post_population
493
+ if @result
494
+ @summary = @result.summary
495
+ @answers = @result.answers
496
+ end
497
+ end
498
+ end
499
+
500
+ class ShowAnswerDigestResponse < ResponseBase
501
+ attr_mapping :digest, :type => AnswerDigest, :path => 'result', :subnode => 'answers_digest'
502
+ end
503
+
504
+ end
505
+ end