hatenablog 0.3.0 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1784b95efbc79289c1fcaefa30ae898223454a17
4
- data.tar.gz: 0a57f752ea79980d82cd6fd4d11f020cabcfed24
3
+ metadata.gz: 6c7e933e59b738cfcda010915591ffe89e236651
4
+ data.tar.gz: 0947478b9a9a5e8d706f6d196d4755bbfd6988d3
5
5
  SHA512:
6
- metadata.gz: 7a7e3181855b17a2aa47863c0279eb661f816bc242e90426feb3a67fde522d35c6c8674005be320e4932e1d7230a83255f79de0b899c9204196e9091e9b7d012
7
- data.tar.gz: d2e5ba03fb472e2e2bae2628c9ea46f0c9a805105849ca10b2d56911235859fd829d1e0940feedf5203c8c86ae6a8760ab75c1878d020ee8cf82fc608705dc6b
6
+ metadata.gz: a7715ef9b24771c3a73d4be1d93e9f8e873d909b0aa92442d7bbe4e706202c8b423287bbe479ba6ba899626f9fd75e11937a5c3ce33b1784bbd41a743ed7ad60
7
+ data.tar.gz: df97bcf0b81ec75e4ab068d09ce597eb273fa780f60fbbf1ee82568b4ae087c144a3c8a30024ba548b6b219a92edfc6dda365b71e2917a28f7906b0954ddbd2d
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  [![Test Coverage](https://codeclimate.com/github/kymmt90/hatenablog/badges/coverage.svg)](https://codeclimate.com/github/kymmt90/hatenablog/coverage)
6
6
 
7
7
  A library for Hatenablog AtomPub API.
8
- This gem supports following operations using OAuth authorization:
8
+ This gem supports following operations using OAuth or Basic authorization:
9
9
 
10
10
  - Get blog feeds, entries and categories
11
11
  - Post blog entries
@@ -70,12 +70,23 @@ user_id: <%= ENV['USER_ID'] %>
70
70
  blog_id: <%= ENV['BLOG_ID'] %>
71
71
  ```
72
72
 
73
+ ### (OPTIONAL) Get Basic Authentication credentials
74
+ If you want to use Basic Authentication, visit `http://blog.hatena.ne.jp/#{user_id}/#{blog_id}/config/detail`
75
+ and check your API key (APIキー) and set up `config.yml` like the following.
76
+
77
+ ```yml
78
+ auth_type: basic
79
+ api_key: <%= ENV['API_KEY'] %>
80
+ user_id: <%= ENV['USER_ID'] %>
81
+ blog_id: <%= ENV['BLOG_ID'] %>
82
+ ```
83
+
73
84
  ## Usage
74
85
 
75
86
  ```ruby
76
87
  require 'hatenablog'
77
88
 
78
- # Read the OAuth configuration from 'config.yml'
89
+ # Read the configuration from 'config.yml'
79
90
  Hatenablog::Client.create do |blog|
80
91
  # Get each entry's content
81
92
  blog.entries.each do |entry|
@@ -1,9 +1,8 @@
1
- require 'oauth'
2
-
3
1
  require 'hatenablog/category'
4
2
  require 'hatenablog/entry'
5
3
  require 'hatenablog/feed'
6
4
  require 'hatenablog/configuration'
5
+ require 'hatenablog/requester'
7
6
 
8
7
  module Hatenablog
9
8
  class Client
@@ -13,16 +12,14 @@ module Hatenablog
13
12
  MEMBER_URI = "https://blog.hatena.ne.jp/%s/%s/atom/entry/%s".freeze
14
13
  CATEGORY_URI = "https://blog.hatena.ne.jp/%s/%s/atom/category".freeze
15
14
 
16
- attr_writer :access_token
15
+ attr_writer :requester
17
16
 
18
17
  # Create a new hatenablog AtomPub client from a configuration file.
19
18
  # @param [String] config_file configuration file path
20
19
  # @return [Hatenablog::Client] created hatenablog client
21
20
  def self.create(config_file = DEFAULT_CONFIG_PATH)
22
- config = Configuration.new(config_file)
23
- blog = Hatenablog::Client.new(config.consumer_key, config.consumer_secret,
24
- config.access_token, config.access_token_secret,
25
- config.user_id, config.blog_id)
21
+ config = Configuration.create(config_file)
22
+ blog = Hatenablog::Client.new(config)
26
23
  return blog unless block_given?
27
24
  yield blog
28
25
  end
@@ -172,20 +169,14 @@ module Hatenablog
172
169
 
173
170
  private
174
171
 
175
- def initialize(consumer_key, consumer_secret, access_token, access_token_secret,
176
- user_id, blog_id)
177
- consumer = OAuth::Consumer.new(consumer_key, consumer_secret)
178
- @access_token = OAuthAccessToken.new(OAuth::AccessToken.new(consumer,
179
- access_token,
180
- access_token_secret))
181
-
182
- @user_id = user_id
183
- @blog_id = blog_id
172
+ def initialize(config)
173
+ @requester = Requester.create(config)
174
+ @user_id = config.user_id
175
+ @blog_id = config.blog_id
184
176
  end
185
177
 
186
-
187
178
  def get(uri)
188
- @access_token.get(uri)
179
+ @requester.get(uri)
189
180
  end
190
181
 
191
182
  def get_collection(uri = collection_uri)
@@ -200,84 +191,15 @@ module Hatenablog
200
191
  end
201
192
 
202
193
  def post(entry_xml, uri = collection_uri)
203
- @access_token.post(uri, entry_xml)
194
+ @requester.post(uri, entry_xml)
204
195
  end
205
196
 
206
197
  def put(entry_xml, uri)
207
- @access_token.put(uri, entry_xml)
198
+ @requester.put(uri, entry_xml)
208
199
  end
209
200
 
210
201
  def delete(uri)
211
- @access_token.delete(uri)
202
+ @requester.delete(uri)
212
203
  end
213
204
  end
214
-
215
- class OAuthAccessToken
216
-
217
- # Create a new OAuth 1.0a access token.
218
- # @param [OAuth::AccessToken] access_token access token object
219
- def initialize(access_token)
220
- @access_token = access_token
221
- end
222
-
223
- # HTTP GET method
224
- # @param [string] uri target URI
225
- # @return [Net::HTTPResponse] HTTP response
226
- def get(uri)
227
- begin
228
- response = @access_token.get(uri)
229
- rescue => problem
230
- raise OAuthError, 'Fail to GET: ' + problem.to_s
231
- end
232
- response
233
- end
234
-
235
- # HTTP POST method
236
- # @param [string] uri target URI
237
- # @param [string] body HTTP request body
238
- # @param [string] headers HTTP request headers
239
- # @return [Net::HTTPResponse] HTTP response
240
- def post(uri,
241
- body = '',
242
- headers = { 'Content-Type' => 'application/atom+xml; type=entry' } )
243
- begin
244
- response = @access_token.post(uri, body, headers)
245
- rescue => problem
246
- raise OAuthError, 'Fail to POST: ' + problem.to_s
247
- end
248
- response
249
- end
250
-
251
- # HTTP PUT method
252
- # @param [string] uri target URI
253
- # @param [string] body HTTP request body
254
- # @param [string] headers HTTP request headers
255
- # @return [Net::HTTPResponse] HTTP response
256
- def put(uri,
257
- body = '',
258
- headers = { 'Content-Type' => 'application/atom+xml; type=entry' } )
259
- begin
260
- response = @access_token.put(uri, body, headers)
261
- rescue => problem
262
- raise OAuthError, 'Fail to PUT: ' + problem.to_s
263
- end
264
- response
265
- end
266
-
267
- # HTTP DELETE method
268
- # @param [string] uri target URI
269
- # @param [string] headers HTTP request headers
270
- # @return [Net::HTTPResponse] HTTP response
271
- def delete(uri,
272
- headers = { 'Content-Type' => 'application/atom+xml; type=entry' })
273
- begin
274
- response = @access_token.delete(uri, headers)
275
- rescue => problem
276
- raise OAuthError, 'Fail to DELETE: ' + problem.to_s
277
- end
278
- response
279
- end
280
- end
281
-
282
- class OAuthError < StandardError; end
283
205
  end
@@ -1,30 +1,23 @@
1
1
  require 'erb'
2
2
  require 'yaml'
3
+ require 'ostruct'
3
4
 
4
5
  module Hatenablog
5
- class Configuration
6
- # For OAuth authorization.
7
- attr_reader :consumer_key, :consumer_secret, :access_token, :access_token_secret
8
-
9
- attr_reader :user_id, :blog_id
6
+ class Configuration < OpenStruct
7
+ OAUTH_KEYS = %w(consumer_key consumer_secret access_token access_token_secret user_id blog_id)
8
+ BASIC_KEYS = %w(api_key user_id blog_id)
10
9
 
11
10
  # Create a new configuration.
12
11
  # @param [String] config_file configuration file path
13
12
  # @return [Hatenablog::Configuration]
14
- def initialize(config_file)
13
+ def self.create(config_file)
15
14
  config = YAML.load(ERB.new(File.read(config_file)).result)
16
- unless config.has_key?('consumer_key') && config.has_key?('consumer_secret') &&
17
- config.has_key?('access_token') && config.has_key?('access_token_secret') &&
18
- config.has_key?('user_id') && config.has_key?('blog_id')
19
- raise ConfigurationError, 'the configure file is incorrect'
15
+ keys = config['auth_type'] == 'basic' ? BASIC_KEYS : OAUTH_KEYS
16
+ unless (lacking_keys = keys.select {|key| !config.has_key? key}).empty?
17
+ raise ConfigurationError, "Following keys are not setup. #{lacking_keys}"
20
18
  end
21
19
 
22
- @consumer_key = config['consumer_key']
23
- @consumer_secret = config['consumer_secret']
24
- @access_token = config['access_token']
25
- @access_token_secret = config['access_token_secret']
26
- @user_id = config['user_id']
27
- @blog_id = config['blog_id']
20
+ new(config)
28
21
  end
29
22
  end
30
23
 
@@ -0,0 +1,149 @@
1
+ require 'net/http'
2
+ require 'oauth'
3
+
4
+ module Hatenablog
5
+ module Requester
6
+ class RequestError < StandardError; end
7
+
8
+ def self.create(config)
9
+ if config.auth_type == 'basic'
10
+ Requester::Basic.new(config.user_id, config.api_key)
11
+ else
12
+ consumer = ::OAuth::Consumer.new(config.consumer_key, config.consumer_secret)
13
+ Requester::OAuth.new(::OAuth::AccessToken.new(consumer, config.access_token, config.access_token_secret))
14
+ end
15
+ end
16
+
17
+ class OAuth
18
+ # Create a new OAuth 1.0a access token.
19
+ # @param [OAuth::AccessToken] access_token access token object
20
+ def initialize(access_token)
21
+ @access_token = access_token
22
+ end
23
+
24
+ # HTTP GET method
25
+ # @param [string] uri target URI
26
+ # @return [Net::HTTPResponse] HTTP response
27
+ def get(uri)
28
+ begin
29
+ response = @access_token.get(uri)
30
+ rescue => problem
31
+ raise RequestError, 'Fail to GET: ' + problem.to_s
32
+ end
33
+ response
34
+ end
35
+
36
+ # HTTP POST method
37
+ # @param [string] uri target URI
38
+ # @param [string] body HTTP request body
39
+ # @param [string] headers HTTP request headers
40
+ # @return [Net::HTTPResponse] HTTP response
41
+ def post(uri,
42
+ body = '',
43
+ headers = { 'Content-Type' => 'application/atom+xml; type=entry' } )
44
+ begin
45
+ response = @access_token.post(uri, body, headers)
46
+ rescue => problem
47
+ raise RequestError, 'Fail to POST: ' + problem.to_s
48
+ end
49
+ response
50
+ end
51
+
52
+ # HTTP PUT method
53
+ # @param [string] uri target URI
54
+ # @param [string] body HTTP request body
55
+ # @param [string] headers HTTP request headers
56
+ # @return [Net::HTTPResponse] HTTP response
57
+ def put(uri,
58
+ body = '',
59
+ headers = { 'Content-Type' => 'application/atom+xml; type=entry' } )
60
+ begin
61
+ response = @access_token.put(uri, body, headers)
62
+ rescue => problem
63
+ raise RequestError, 'Fail to PUT: ' + problem.to_s
64
+ end
65
+ response
66
+ end
67
+
68
+ # HTTP DELETE method
69
+ # @param [string] uri target URI
70
+ # @param [string] headers HTTP request headers
71
+ # @return [Net::HTTPResponse] HTTP response
72
+ def delete(uri,
73
+ headers = { 'Content-Type' => 'application/atom+xml; type=entry' })
74
+ begin
75
+ response = @access_token.delete(uri, headers)
76
+ rescue => problem
77
+ raise RequestError, 'Fail to DELETE: ' + problem.to_s
78
+ end
79
+ response
80
+ end
81
+ end
82
+
83
+ class Basic
84
+ METHODS = {
85
+ get: Net::HTTP::Get,
86
+ post: Net::HTTP::Post,
87
+ put: Net::HTTP::Put,
88
+ delete: Net::HTTP::Delete
89
+ }
90
+
91
+ # Create a new Basic authentication requester.
92
+ # @params [string] user_id Hatena user ID
93
+ # @params [string] api_key Hatena API key
94
+ def initialize(user_id, api_key)
95
+ @user_id = user_id
96
+ @api_key = api_key
97
+ end
98
+
99
+ # HTTP GET method
100
+ # @param [string] uri target URI
101
+ # @return [Net::HTTPResponse] HTTP response
102
+ def get(uri)
103
+ request(uri, :get)
104
+ end
105
+
106
+ # HTTP POST method
107
+ # @param [string] uri target URI
108
+ # @param [string] body HTTP request body
109
+ # @param [string] headers HTTP request headers
110
+ # @return [Net::HTTPResponse] HTTP response
111
+ def post(uri, body, headers = nil)
112
+ request(uri, :post, body: body, headers: headers)
113
+ end
114
+
115
+ # HTTP PUT method
116
+ # @param [string] uri target URI
117
+ # @param [string] body HTTP request body
118
+ # @param [string] headers HTTP request headers
119
+ # @return [Net::HTTPResponse] HTTP response
120
+ def put(uri, body, headers = nil )
121
+ request(uri, :put, body: body, headers: headers)
122
+ end
123
+
124
+ # HTTP DELETE method
125
+ # @param [string] uri target URI
126
+ # @param [string] headers HTTP request headers
127
+ # @return [Net::HTTPResponse] HTTP response
128
+ def delete(uri, headers = nil)
129
+ request(uri, :delete, headers: headers)
130
+ end
131
+
132
+ private
133
+ def request(uri, method, body: nil, headers: nil)
134
+ uri = URI(uri)
135
+ req = METHODS[method].new(uri, headers)
136
+ req.basic_auth @user_id, @api_key
137
+ if body
138
+ req.body = body
139
+ req.content_type = 'application/atom+xml; type=entry'
140
+ end
141
+
142
+ http = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.port == 443)
143
+ http.request(req)
144
+ rescue => problem
145
+ raise RequestError, "Fail to #{method.upcase}: " + problem.to_s
146
+ end
147
+ end
148
+ end
149
+ end
@@ -1,3 +1,3 @@
1
1
  module Hatenablog
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hatenablog
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kohei Yamamoto
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-08-16 00:00:00.000000000 Z
11
+ date: 2016-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -146,6 +146,7 @@ files:
146
146
  - lib/hatenablog/configuration.rb
147
147
  - lib/hatenablog/entry.rb
148
148
  - lib/hatenablog/feed.rb
149
+ - lib/hatenablog/requester.rb
149
150
  - lib/hatenablog/version.rb
150
151
  homepage: https://github.com/kymmt90/hatenablog
151
152
  licenses: