kiita 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format=d
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.3-p194@kiita --create
@@ -0,0 +1,3 @@
1
+ SimpleCov.start do
2
+ add_filter "spec/"
3
+ end
@@ -0,0 +1,5 @@
1
+ script: "bundle exec rspec spec/"
2
+
3
+ rvm:
4
+ - 1.9.2
5
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kiita.gemspec
4
+ gemspec
5
+
6
+ gem 'pry'
7
+ gem 'simplecov'
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Yuki Nishijima
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,129 @@
1
+ # Kiita
2
+
3
+ Yet Another Qiita API Wrapper.
4
+
5
+ [![Build Status](https://secure.travis-ci.org/yuki24/kiita.png)](http://travis-ci.org/yuki24/kiita) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/yuki24/kiita)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'kiita'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ ```sh
18
+ $ bundle
19
+ ```
20
+
21
+ Or install it yourself as:
22
+
23
+ ```sh
24
+ $ gem install kiita
25
+ ```
26
+
27
+ # Usage
28
+
29
+ ## Public APIs
30
+
31
+ ### See rate_limit
32
+
33
+ ```ruby
34
+ rate = Kiita::API.rate_limit
35
+
36
+ rate["remaning"] # => 148
37
+ rate["limit"] # => 150
38
+ ```
39
+
40
+ ### Get an authentication token
41
+
42
+ ```ruby
43
+ auth = Kiita::API.authenticate("user", "password")
44
+
45
+ auth["url_name"] # => "user"
46
+ auth["token"] # => "a875scr65rc86a5s��"
47
+ ```
48
+
49
+ ### Get a user's information
50
+
51
+ ```ruby
52
+ user = Kiita::API.user("yuki24")
53
+
54
+ user.class # => Kiita:;User
55
+ user.name # => "Yuki Nishijima"
56
+ user.location # => "Tokyo, Japan"
57
+ user.description # => "I'm a guy."
58
+ ```
59
+
60
+ ### Get a user's posts
61
+
62
+ ```ruby
63
+ posts = Kiita::API.user("yuki24").posts
64
+ post = posts.first
65
+
66
+ post.class # => Kiita::Post
67
+ post.title # => "I'm a title!"
68
+ post.body # => "I'm a body!"
69
+ ```
70
+
71
+ ## APIs that require authentication
72
+
73
+ First create an object with the token like this:
74
+
75
+ ```ruby
76
+ user = Kiita::API.new(token: "a875scr65rc86a5s")
77
+ ```
78
+
79
+ then you can do the followings.
80
+
81
+ ### Get my information
82
+
83
+ ```ruby
84
+ user.me # => your information
85
+ ```
86
+
87
+ ### Get your stocks
88
+
89
+ ```ruby
90
+ user.stocks # collection of the posts that you stocked before.
91
+ ```
92
+
93
+ ### Stock a post
94
+
95
+ ```ruby
96
+ user.stock!("e6654a3b258b7c6b7d1") # => true if success
97
+ ```
98
+
99
+ ### Unstock a post
100
+
101
+ ```ruby
102
+ user.unstock!("e6654a3b258b7c6b7d1") # => true if success
103
+ ```
104
+
105
+ ## Configuration
106
+
107
+ Kiita currently doesn't allow to configure anything. But in the near future, it will support some confgurations like timeout and keep alive.
108
+
109
+ ## Support
110
+
111
+ * Ruby 1.9.2, 1.9.3
112
+
113
+ Note that *Ruby 1.8.7 is NOT supported*.
114
+
115
+ ## TODO
116
+
117
+ 1. Implementation of the APIs that use POST, PUT or DELETE
118
+ 2. Writing up rdoc as well as this README
119
+
120
+ ## Contributing
121
+
122
+ 1. Fork it
123
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
124
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
125
+ 4. Push to the branch (`git push origin my-new-feature`)
126
+ 5. Create new Pull Request
127
+
128
+ ## Copyright
129
+ Copyright (c) 2012 Yuki Nishijima. See LICENSE.md for further details.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'kiita/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "kiita"
8
+ gem.version = Kiita::VERSION
9
+ gem.authors = ["Yuki Nishijima"]
10
+ gem.email = ["mail@yukinishijima.net"]
11
+ gem.description = %q{Kiita is yet another Qiita API wrapper.}
12
+ gem.summary = %q{Yet Another Qiita API Wrapper}
13
+ gem.homepage = "https://github.com/yuki24/kiita"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency 'httpclient'
21
+ gem.add_dependency 'oj'
22
+ gem.add_dependency 'activesupport', '>= 3.0.0'
23
+
24
+ gem.add_development_dependency 'rspec'
25
+ gem.add_development_dependency 'vcr'
26
+ gem.add_development_dependency 'webmock'
27
+ end
@@ -0,0 +1,26 @@
1
+ require 'active_support/all'
2
+ require 'httpclient'
3
+ require 'oj'
4
+
5
+ require 'kiita/errors'
6
+ require 'kiita/api'
7
+ require 'kiita/version'
8
+
9
+ module Kiita
10
+
11
+ # Default API endpoint
12
+ mattr_accessor :api_endpoint
13
+ @@api_endpoint = "https://qiita.com/api/v1"
14
+
15
+ # Connect timeout in sec.
16
+ mattr_accessor :timeout
17
+ @@timeout = 30
18
+
19
+ # Reuse the same connection within this timeout in sec. from last used.
20
+ mattr_accessor :keep_alive
21
+ @@keep_alive = 0
22
+
23
+ def self.connection
24
+ @connection ||= HTTPClient.new
25
+ end
26
+ end
@@ -0,0 +1,118 @@
1
+ require 'kiita/model'
2
+ require 'kiita/user'
3
+ require 'kiita/tag'
4
+ require 'kiita/post'
5
+
6
+ module Kiita
7
+ class API
8
+ extend Kiita::Errors::HandlerMethods
9
+ attr_reader :token
10
+
11
+ def initialize(options = {})
12
+ @token = options[:token]
13
+ end
14
+
15
+ def me
16
+ Kiita::User.new(get("/user"))
17
+ end
18
+
19
+ def search(keyword, options = {})
20
+ get("/search", options.merge!(q: keyword)).map{|post| Kiita::Post.new(post) }
21
+ end
22
+
23
+ def stocks(options = {})
24
+ get("/stocks", options).map{|post| Kiita::Post.new(post) }
25
+ end
26
+
27
+ def stock!(uuid)
28
+ (response = put("/items/#{uuid}/stock")).nil? ? true : response
29
+ end
30
+
31
+ def unstock!(uuid)
32
+ (response = delete("/items/#{uuid}/stock")).nil? ? true : response
33
+ end
34
+
35
+ def self.rate_limit
36
+ get("/rate_limit")
37
+ end
38
+
39
+ def self.authenticate(url_name, password)
40
+ post("/auth", url_name: url_name, password: password)
41
+ end
42
+
43
+ def self.user(url_name)
44
+ Kiita::User.lazy_load(url_name)
45
+ end
46
+
47
+ def self.item(uuid)
48
+ Kiita::Post.lazy_load(uuid)
49
+ end
50
+
51
+ def self.items(options = {})
52
+ Kiita::Post.all(options)
53
+ end
54
+
55
+ def self.search(keyword, options = {})
56
+ Kiita::Post.search(keyword, options)
57
+ end
58
+
59
+ def self.tag(url_name)
60
+ Kiita::Tag.new(url_name)
61
+ end
62
+
63
+ def self.tags(options = {})
64
+ Kiita::Tag.all(options)
65
+ end
66
+
67
+ def get(path, options = {})
68
+ self.class.get(path_with_credentials(path), options.merge!(token: token))
69
+ end
70
+
71
+ def post(path, options = {})
72
+ self.class.post(path_with_credentials(path), options)
73
+ end
74
+
75
+ def put(path, options = {})
76
+ self.class.put(path_with_credentials(path), options)
77
+ end
78
+
79
+ def delete(path, options = {})
80
+ self.class.delete(path_with_credentials(path), options)
81
+ end
82
+
83
+ def self.get(path, options = {})
84
+ handle_response(connection.get(qiita_url(path), options))
85
+ end
86
+
87
+ def self.post(path, options = {})
88
+ handle_response(connection.post(qiita_url(path), options))
89
+ end
90
+
91
+ def self.put(path, options = {})
92
+ handle_response(connection.put(qiita_url(path), options))
93
+ end
94
+
95
+ def self.delete(path, options = {})
96
+ handle_response(connection.delete(qiita_url(path), options))
97
+ end
98
+
99
+ private
100
+
101
+ def path_with_credentials(path)
102
+ token ? (path + "?token=#{token}") : path
103
+ end
104
+
105
+ def self.connection
106
+ Kiita.connection
107
+ end
108
+
109
+ def self.qiita_url(path)
110
+ Kiita.api_endpoint + path
111
+ end
112
+
113
+ def self.handle_response(response)
114
+ on_complete(response)
115
+ Oj.load(response.body.empty? ? "null" : response.body)
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,43 @@
1
+ module Kiita
2
+ class Error < StandardError; end
3
+ class BadRequest < Error; end # 400
4
+ class Unauthorized < Error; end # 401
5
+ class Forbidden < Error; end # 403
6
+ class NotFound < Error; end # 404
7
+ class InternalServerError < Error; end # 500
8
+
9
+ module Errors
10
+ module HandlerMethods
11
+ def on_complete(response)
12
+ case response.status
13
+ when 400
14
+ raise Kiita::BadRequest, error_message(response)
15
+ when 401
16
+ raise Kiita::Unauthorized, error_message(response)
17
+ when 403
18
+ raise Kiita::Forbidden, error_message(response)
19
+ when 404
20
+ raise Kiita::NotFound, error_message(response)
21
+ # when 406
22
+ # raise Kiita::NotAcceptable, error_message(response)
23
+ # when 422
24
+ # raise Kiita::UnprocessableEntity, error_message(response)
25
+ when 500
26
+ raise Kiita::InternalServerError, error_message(response)
27
+ # when 503
28
+ # raise Kiita::ServiceUnavailable, error_message(response)
29
+ end
30
+ end
31
+ private :on_complete
32
+
33
+ def error_message(response)
34
+ if response.body.empty?
35
+ "#{response.http_header.request_method} #{response.http_header.request_uri.to_s}: #{response.status}"
36
+ else
37
+ Oj.load(response.body)["error"]
38
+ end
39
+ end
40
+ private :error_message
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,33 @@
1
+ module Kiita::Model
2
+ extend ActiveSupport::Concern
3
+
4
+ def initialize(options = {})
5
+ set_raw_attributes(options.slice(*attributes)) if options.slice(*attributes).present?
6
+ end
7
+
8
+ def raw_attributes
9
+ @raw_attributes ||= set_raw_attributes(raw_data)
10
+ end
11
+
12
+ protected
13
+
14
+ def set_raw_attributes(attrs)
15
+ @raw_attributes = attrs.tap do |raw_data|
16
+ raw_data.each{|key, value| instance_eval("@#{key}= value") }
17
+ end
18
+ end
19
+
20
+ module ClassMethods
21
+ def define_attributes(attrs, getter_method)
22
+ attrs.each do |attribute_name|
23
+ class_eval <<-RUBY
24
+ def #{attribute_name}
25
+ @#{attribute_name} ||= raw_attributes["#{attribute_name}"]
26
+ end
27
+ RUBY
28
+ end
29
+
30
+ define_method(:raw_data, &getter_method)
31
+ end
32
+ end
33
+ end