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 +4 -4
- data/README.md +13 -2
- data/lib/hatenablog/client.rb +12 -90
- data/lib/hatenablog/configuration.rb +9 -16
- data/lib/hatenablog/requester.rb +149 -0
- data/lib/hatenablog/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c7e933e59b738cfcda010915591ffe89e236651
|
4
|
+
data.tar.gz: 0947478b9a9a5e8d706f6d196d4755bbfd6988d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7715ef9b24771c3a73d4be1d93e9f8e873d909b0aa92442d7bbe4e706202c8b423287bbe479ba6ba899626f9fd75e11937a5c3ce33b1784bbd41a743ed7ad60
|
7
|
+
data.tar.gz: df97bcf0b81ec75e4ab068d09ce597eb273fa780f60fbbf1ee82568b4ae087c144a3c8a30024ba548b6b219a92edfc6dda365b71e2917a28f7906b0954ddbd2d
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
[](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
|
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|
|
data/lib/hatenablog/client.rb
CHANGED
@@ -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 :
|
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.
|
23
|
-
blog = Hatenablog::Client.new(config
|
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(
|
176
|
-
|
177
|
-
|
178
|
-
@
|
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
|
-
@
|
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
|
-
@
|
194
|
+
@requester.post(uri, entry_xml)
|
204
195
|
end
|
205
196
|
|
206
197
|
def put(entry_xml, uri)
|
207
|
-
@
|
198
|
+
@requester.put(uri, entry_xml)
|
208
199
|
end
|
209
200
|
|
210
201
|
def delete(uri)
|
211
|
-
@
|
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
|
-
|
7
|
-
|
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
|
13
|
+
def self.create(config_file)
|
15
14
|
config = YAML.load(ERB.new(File.read(config_file)).result)
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
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
|
data/lib/hatenablog/version.rb
CHANGED
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.
|
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-
|
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:
|