hatenablog 0.6.0 → 0.9.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/.github/workflows/build.yml +40 -22
- data/.gitignore +1 -0
- data/CHANGELOG.md +27 -0
- data/Gemfile +4 -1
- data/README.md +26 -16
- data/Rakefile +1 -0
- data/Steepfile +11 -0
- data/exe/{get_access_token → get_hatena_oauth_access_token} +0 -0
- data/hatenablog.gemspec +1 -1
- data/lib/hatenablog/category.rb +3 -2
- data/lib/hatenablog/client.rb +37 -9
- data/lib/hatenablog/configuration.rb +2 -0
- data/lib/hatenablog/entry.rb +19 -3
- data/lib/hatenablog/feed.rb +2 -1
- data/lib/hatenablog/requester.rb +12 -7
- data/lib/hatenablog/version.rb +1 -1
- data/rbs_collection.lock.yaml +36 -0
- data/rbs_collection.yaml +36 -0
- data/sig/hatenablog.rbs +249 -0
- metadata +14 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d9278d2c56596a6d4022836122cd11258376b5d5761e5b0685ca63fa1df55648
|
4
|
+
data.tar.gz: daf90442052c2b216d46ffdf759406c373967832edf66ef1b4c289e78f968b4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40a08dbb7cfe60613caff523b02ed759e4ce0ce556919561bd6b720c208dbde5fe6ac9a3cbbddadf79586f4a576435b44383bdcd24707a3013768fba476c8027
|
7
|
+
data.tar.gz: d694f725a5a5d35ed3c5272f3aa82a32d0ef0473adffd88a9baaae7bfa2f0c21349f9523d9ee71291c14bae6a2702e2b44b10349a55eb7bb52d799c51fefe84a
|
data/.github/workflows/build.yml
CHANGED
@@ -1,31 +1,49 @@
|
|
1
1
|
name: build
|
2
2
|
|
3
|
-
on:
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- master
|
7
|
+
pull_request:
|
4
8
|
|
5
9
|
jobs:
|
6
10
|
build:
|
7
11
|
runs-on: ubuntu-latest
|
8
12
|
strategy:
|
9
13
|
matrix:
|
10
|
-
ruby: ['2.
|
14
|
+
ruby: ['2.6', '2.7', '3.0', '3.1.0-preview1']
|
15
|
+
include:
|
16
|
+
- ruby: '3.0'
|
17
|
+
report-coverage: true
|
11
18
|
steps:
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
19
|
+
- uses: actions/checkout@v2
|
20
|
+
- uses: ruby/setup-ruby@v1
|
21
|
+
with:
|
22
|
+
ruby-version: ${{ matrix.ruby }}
|
23
|
+
- run: gem install bundler
|
24
|
+
- run: bundle install -j4
|
25
|
+
- name: Run tests and report test coverage
|
26
|
+
if: matrix.report-coverage
|
27
|
+
uses: paambaati/codeclimate-action@v2.7.5
|
28
|
+
env:
|
29
|
+
CC_TEST_REPORTER_ID: 309cf0784d00d2a6009566d28be111a8a0280cdeb2da280225eedf577b16beb5
|
30
|
+
with:
|
31
|
+
coverageCommand: bundle exec rake
|
32
|
+
coverageLocations: ${{github.workspace}}/coverage/coverage.json:simplecov
|
33
|
+
- name: Run tests
|
34
|
+
if: "!matrix.report-coverage"
|
35
|
+
env:
|
36
|
+
TZ: Asia/Tokyo
|
37
|
+
run: bundle exec rake
|
38
|
+
steep:
|
39
|
+
runs-on: ubuntu-latest
|
40
|
+
steps:
|
41
|
+
- uses: actions/checkout@v2
|
42
|
+
with:
|
43
|
+
submodules: 'true'
|
44
|
+
- uses: ruby/setup-ruby@v1
|
45
|
+
with:
|
46
|
+
ruby-version: '3.0'
|
47
|
+
- run: bundle install -j4
|
48
|
+
- run: rbs collection install
|
49
|
+
- run: bundle exec steep check
|
data/.gitignore
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
|
+
|
7
|
+
## Unreleased
|
8
|
+
|
9
|
+
## 0.9.0 - 2022-04-11
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- [feat: Add `updated` parameter to post_entry](https://github.com/kymmt90/hatenablog/pull/29)
|
14
|
+
|
15
|
+
## 0.8.0 - 2021-11-20
|
16
|
+
|
17
|
+
### Added
|
18
|
+
|
19
|
+
- [Create the signature with RBS](https://github.com/kymmt90/hatenablog/pull/24)
|
20
|
+
- This is experimental
|
21
|
+
|
22
|
+
### Changed
|
23
|
+
|
24
|
+
- [Change the executable name to more specific one](https://github.com/kymmt90/hatenablog/pull/26)
|
25
|
+
- From `get_access_token` to `get_hatena_oauth_access_token`
|
26
|
+
- [Use only supported Rubies in 2021-11](https://github.com/kymmt90/hatenablog/pull/27)
|
27
|
+
- Drop Ruby 2.4 and 2.5 and add Ruby 3.1.0-preview1
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -19,15 +19,21 @@ This gem supports following operations through OAuth 1.0a or Basic authenticatio
|
|
19
19
|
|
20
20
|
Add this line to your application's Gemfile:
|
21
21
|
|
22
|
-
|
22
|
+
```
|
23
|
+
gem 'hatenablog'
|
24
|
+
```
|
23
25
|
|
24
26
|
And then execute:
|
25
27
|
|
26
|
-
|
28
|
+
```
|
29
|
+
$ bundle
|
30
|
+
```
|
27
31
|
|
28
32
|
Or install it yourself as:
|
29
33
|
|
30
|
-
|
34
|
+
```
|
35
|
+
$ gem install hatenablog
|
36
|
+
```
|
31
37
|
|
32
38
|
### Get OAuth credentials
|
33
39
|
|
@@ -41,11 +47,13 @@ Access [Hatena application registoration page](http://developer.hatena.ne.jp/) a
|
|
41
47
|
|
42
48
|
Execute this command:
|
43
49
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
50
|
+
```
|
51
|
+
$ get_hatena_oauth_access_token <your consumer key> <your consumer secret>
|
52
|
+
Visit this website and get the PIN: https://www.hatena.com/oauth/authorize?oauth_token=XXXXXXXXXXXXXXXXXXXX
|
53
|
+
Enter the PIN: <your PIN> [Enter]
|
54
|
+
Access token: <your access token>
|
55
|
+
Access token secret: <your access token secret>
|
56
|
+
```
|
49
57
|
|
50
58
|
#### 3. [Optional] Set up the YAML configuration file
|
51
59
|
|
@@ -164,7 +172,7 @@ feed.uri
|
|
164
172
|
feed.next_uri # The next feed URI
|
165
173
|
feed.title
|
166
174
|
feed.author_name
|
167
|
-
feed.
|
175
|
+
feed.updated # Updated datetime
|
168
176
|
|
169
177
|
feed.entries # entries in the feed
|
170
178
|
feed.each_entry do |entry|
|
@@ -186,18 +194,20 @@ entry = client.post_entry(
|
|
186
194
|
'Example Title', # title
|
187
195
|
'This is the **example** entry.', # content
|
188
196
|
['Ruby', 'Rails'], # categories
|
189
|
-
'yes'
|
197
|
+
'yes', # draft
|
198
|
+
'2022-04-11T15:43:20+09:00' # updated
|
190
199
|
)
|
191
200
|
entry.id
|
192
201
|
entry.uri
|
193
202
|
entry.edit_uri
|
194
203
|
entry.author_name
|
195
|
-
entry.title
|
196
|
-
entry.content
|
197
|
-
entry.
|
198
|
-
entry.draft
|
199
|
-
entry.
|
200
|
-
entry.
|
204
|
+
entry.title #=> 'Example Title'
|
205
|
+
entry.content #=> 'This is the **example** entry.'
|
206
|
+
entry.formatted_content #=> '<p>This is the <strong>example</strong> entry.</p>'
|
207
|
+
entry.draft #=> 'yes'
|
208
|
+
entry.draft? #=> true
|
209
|
+
entry.categories #=> ['Ruby', 'Rails']
|
210
|
+
entry.updated # Updated datetime
|
201
211
|
|
202
212
|
client.update_entry(
|
203
213
|
entry.id,
|
data/Rakefile
CHANGED
data/Steepfile
ADDED
File without changes
|
data/hatenablog.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
-
spec.required_ruby_version = '>= 2.
|
22
|
+
spec.required_ruby_version = '>= 2.3'
|
23
23
|
|
24
24
|
spec.add_development_dependency "bundler"
|
25
25
|
spec.add_development_dependency "rake"
|
data/lib/hatenablog/category.rb
CHANGED
@@ -16,9 +16,10 @@ module Hatenablog
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def each(&block)
|
19
|
-
return enum_for
|
19
|
+
return enum_for unless block_given?
|
20
20
|
|
21
21
|
@categories.each do |category|
|
22
|
+
# @type var block: ^(String) -> void
|
22
23
|
block.call(category)
|
23
24
|
end
|
24
25
|
end
|
@@ -38,7 +39,7 @@ module Hatenablog
|
|
38
39
|
end
|
39
40
|
|
40
41
|
def parse_document
|
41
|
-
@categories = @document.css('atom|category').inject(
|
42
|
+
@categories = @document.css('atom|category').inject(Array.new) do |categories, category|
|
42
43
|
categories << category['term'].to_s
|
43
44
|
end
|
44
45
|
|
data/lib/hatenablog/client.rb
CHANGED
@@ -12,6 +12,7 @@ module Hatenablog
|
|
12
12
|
MEMBER_URI = "https://blog.hatena.ne.jp/%s/%s/atom/entry/%s".freeze
|
13
13
|
CATEGORY_URI = "https://blog.hatena.ne.jp/%s/%s/atom/category".freeze
|
14
14
|
|
15
|
+
# @dynamic requester=
|
15
16
|
attr_writer :requester
|
16
17
|
|
17
18
|
# Create a new hatenablog AtomPub client from a configuration file.
|
@@ -24,9 +25,9 @@ module Hatenablog
|
|
24
25
|
yield blog
|
25
26
|
end
|
26
27
|
|
27
|
-
def initialize(config =
|
28
|
+
def initialize(config = Configuration.new)
|
28
29
|
if block_given?
|
29
|
-
yield config
|
30
|
+
yield config
|
30
31
|
config.check_valid_or_raise
|
31
32
|
end
|
32
33
|
@requester = Requester.create(config)
|
@@ -59,7 +60,7 @@ module Hatenablog
|
|
59
60
|
# Get all blog entries.
|
60
61
|
# @return [Hatenablog::Entries] enumerator of blog entries
|
61
62
|
def all_entries
|
62
|
-
Entries.new(self,
|
63
|
+
Entries.new(self, 0, :all)
|
63
64
|
end
|
64
65
|
|
65
66
|
# Get the next feed of the given feed.
|
@@ -92,9 +93,10 @@ module Hatenablog
|
|
92
93
|
# @param [String] content entry content
|
93
94
|
# @param [Array] categories entry categories
|
94
95
|
# @param [String] draft this entry is draft if 'yes', otherwise it is not draft
|
96
|
+
# @param [String] updated entry updated datetime (ISO 8601)
|
95
97
|
# @return [Hatenablog::BlogEntry] posted entry
|
96
|
-
def post_entry(title = '', content = '', categories = [], draft = 'no')
|
97
|
-
entry_xml = entry_xml(title, content, categories, draft)
|
98
|
+
def post_entry(title = '', content = '', categories = [], draft = 'no', updated = '')
|
99
|
+
entry_xml = entry_xml(title, content, categories, draft, updated)
|
98
100
|
response = post(entry_xml)
|
99
101
|
Entry.load_xml(response.body)
|
100
102
|
end
|
@@ -161,7 +163,7 @@ module Hatenablog
|
|
161
163
|
xml.name author_name
|
162
164
|
end
|
163
165
|
xml.content(content, type: 'text/x-markdown')
|
164
|
-
xml.updated updated
|
166
|
+
xml.updated updated if updated && !updated.empty?
|
165
167
|
categories.each do |category|
|
166
168
|
xml.category(term: category)
|
167
169
|
end
|
@@ -207,19 +209,45 @@ module Hatenablog
|
|
207
209
|
class Entries
|
208
210
|
include Enumerable
|
209
211
|
|
210
|
-
def initialize(client, page = 0)
|
212
|
+
def initialize(client, page = 0, fetch = :partial)
|
211
213
|
@client = client
|
212
214
|
@page = page
|
215
|
+
@fetch = fetch
|
213
216
|
end
|
214
217
|
|
215
218
|
def each(&block)
|
216
|
-
return enum_for
|
219
|
+
return enum_for unless block_given?
|
220
|
+
|
221
|
+
# @type var block: ^(Entry) -> void
|
222
|
+
if @fetch == :all
|
223
|
+
each_all(&block)
|
224
|
+
else
|
225
|
+
each_partial(&block)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
private
|
230
|
+
|
231
|
+
def each_all(&block)
|
232
|
+
feed = nil
|
233
|
+
|
234
|
+
while feed = @client.next_feed(feed)
|
235
|
+
feed.entries.each { |entry| block.call(entry) }
|
236
|
+
end
|
237
|
+
|
238
|
+
self
|
239
|
+
end
|
240
|
+
|
241
|
+
def each_partial(&block)
|
242
|
+
feed = nil
|
217
243
|
|
218
244
|
current_page = 0
|
219
|
-
|
245
|
+
while current_page <= @page && feed = @client.next_feed(feed)
|
220
246
|
feed.entries.each { |entry| block.call(entry) }
|
221
247
|
current_page += 1
|
222
248
|
end
|
249
|
+
|
250
|
+
self
|
223
251
|
end
|
224
252
|
end
|
225
253
|
end
|
@@ -4,6 +4,8 @@ require 'ostruct'
|
|
4
4
|
|
5
5
|
module Hatenablog
|
6
6
|
class Configuration < OpenStruct
|
7
|
+
# @dynamic auth_type, consumer_key, consumer_secret, access_token, access_token_secret, api_key, user_id, blog_id
|
8
|
+
|
7
9
|
OAUTH_KEYS = %i(consumer_key consumer_secret access_token access_token_secret user_id blog_id)
|
8
10
|
BASIC_KEYS = %i(api_key user_id blog_id)
|
9
11
|
|
data/lib/hatenablog/entry.rb
CHANGED
@@ -3,6 +3,9 @@ require 'time'
|
|
3
3
|
|
4
4
|
module Hatenablog
|
5
5
|
module AfterHook
|
6
|
+
# @dynamic uri=, edit_uri=, author_name=, title=, content=, updated=, draft=, categories=
|
7
|
+
# @dynamic instance_methods, alias_method, define_method
|
8
|
+
|
6
9
|
# Register a hooking method for given methods.
|
7
10
|
# The hook method is executed after calling given methods.
|
8
11
|
# @param [Symbol] hooking method name
|
@@ -17,6 +20,7 @@ module Hatenablog
|
|
17
20
|
alias_method origin_method, method
|
18
21
|
|
19
22
|
define_method(method) do |*args, &block|
|
23
|
+
# @type var block: ^(*untyped) -> untyped
|
20
24
|
result = send(origin_method, *args, &block)
|
21
25
|
send(hook)
|
22
26
|
result
|
@@ -28,8 +32,13 @@ module Hatenablog
|
|
28
32
|
class Entry
|
29
33
|
extend AfterHook
|
30
34
|
|
35
|
+
# @dynamic uri, uri=, author_name, author_name=, title, title=, content, content=, draft, draft=
|
31
36
|
attr_accessor :uri, :author_name, :title, :content, :draft
|
32
|
-
|
37
|
+
|
38
|
+
# @dynamic edit_uri, id, updated
|
39
|
+
attr_reader :edit_uri, :id, :updated
|
40
|
+
|
41
|
+
# @dynamic categories=
|
33
42
|
attr_writer :categories
|
34
43
|
|
35
44
|
def updated=(date)
|
@@ -89,6 +98,11 @@ module Hatenablog
|
|
89
98
|
@document.to_s.gsub(/\"/, "'")
|
90
99
|
end
|
91
100
|
|
101
|
+
# @return [String]
|
102
|
+
def formatted_content
|
103
|
+
@formatted_content
|
104
|
+
end
|
105
|
+
|
92
106
|
def self.build_xml(uri, edit_uri, author_name, title, content, draft, categories, updated)
|
93
107
|
builder = Nokogiri::XML::Builder.new(encoding: 'utf-8') do |xml|
|
94
108
|
xml.entry('xmlns' => 'http://www.w3.org/2005/Atom',
|
@@ -130,6 +144,8 @@ module Hatenablog
|
|
130
144
|
@author_name = @document.at_css('author name').content
|
131
145
|
@title = @document.at_css('title').content
|
132
146
|
@content = @document.at_css('content').content
|
147
|
+
@formatted_content = @document.xpath('//hatena:formatted-content', hatena: 'http://www.hatena.ne.jp/info/xmlns#')[0]
|
148
|
+
@formatted_content = @formatted_content.content if @formatted_content
|
133
149
|
@draft = @document.at_css('entry app|control app|draft').content
|
134
150
|
@categories = parse_categories
|
135
151
|
if @document.at_css('entry updated')
|
@@ -140,7 +156,7 @@ module Hatenablog
|
|
140
156
|
end
|
141
157
|
|
142
158
|
def parse_categories
|
143
|
-
categories = @document.css('category').inject(
|
159
|
+
categories = @document.css('category').inject(Array.new) do |categories, category|
|
144
160
|
categories << category['term'].to_s
|
145
161
|
end
|
146
162
|
categories
|
@@ -155,7 +171,7 @@ module Hatenablog
|
|
155
171
|
@document.at_css('entry app|control app|draft').content = @draft
|
156
172
|
|
157
173
|
unless @updated.nil? || @document.at_css('entry updated').nil?
|
158
|
-
@document.at_css('entry updated').content = @updated
|
174
|
+
@document.at_css('entry updated').content = @updated&.iso8601
|
159
175
|
end
|
160
176
|
|
161
177
|
unless @categories.nil?
|
data/lib/hatenablog/feed.rb
CHANGED
@@ -5,6 +5,7 @@ require 'hatenablog/entry'
|
|
5
5
|
|
6
6
|
module Hatenablog
|
7
7
|
class Feed
|
8
|
+
# @dynamic uri, next_uri, title, author_name, updated
|
8
9
|
attr_reader :uri, :next_uri, :title, :author_name, :updated
|
9
10
|
|
10
11
|
# Create a new blog feed from a XML string.
|
@@ -53,7 +54,7 @@ module Hatenablog
|
|
53
54
|
end
|
54
55
|
|
55
56
|
def parse_entry
|
56
|
-
@entries = @document.css('feed > entry').inject(
|
57
|
+
@entries = @document.css('feed > entry').inject(Array.new) do |entries, entry|
|
57
58
|
# add namespace 'app' to recognize XML correctly
|
58
59
|
entry['xmlns:app'] = 'http://www.w3.org/2007/app'
|
59
60
|
entries << Hatenablog::Entry.load_xml(entry.to_s)
|
data/lib/hatenablog/requester.rb
CHANGED
@@ -96,7 +96,7 @@ module Hatenablog
|
|
96
96
|
# @param [string] body HTTP request body
|
97
97
|
# @param [string] headers HTTP request headers
|
98
98
|
# @return [Net::HTTPResponse] HTTP response
|
99
|
-
def post(uri, body, headers =
|
99
|
+
def post(uri, body, headers = {})
|
100
100
|
request(uri, :post, body: body, headers: headers)
|
101
101
|
end
|
102
102
|
|
@@ -105,7 +105,7 @@ module Hatenablog
|
|
105
105
|
# @param [string] body HTTP request body
|
106
106
|
# @param [string] headers HTTP request headers
|
107
107
|
# @return [Net::HTTPResponse] HTTP response
|
108
|
-
def put(uri, body, headers =
|
108
|
+
def put(uri, body, headers = {})
|
109
109
|
request(uri, :put, body: body, headers: headers)
|
110
110
|
end
|
111
111
|
|
@@ -113,22 +113,27 @@ module Hatenablog
|
|
113
113
|
# @param [string] uri target URI
|
114
114
|
# @param [string] headers HTTP request headers
|
115
115
|
# @return [Net::HTTPResponse] HTTP response
|
116
|
-
def delete(uri, headers =
|
116
|
+
def delete(uri, headers = {})
|
117
117
|
request(uri, :delete, headers: headers)
|
118
118
|
end
|
119
119
|
|
120
120
|
private
|
121
|
-
|
121
|
+
|
122
|
+
def request(uri, method, body: nil, headers: {})
|
122
123
|
uri = URI(uri)
|
123
|
-
req = METHODS[method].new(uri, headers)
|
124
|
+
req = METHODS[method].new(uri.to_s, headers)
|
124
125
|
req.basic_auth @user_id, @api_key
|
125
126
|
if body
|
126
127
|
req.body = body
|
127
128
|
req.content_type = ATOM_CONTENT_TYPE
|
128
129
|
end
|
129
130
|
|
130
|
-
http = Net::HTTP.
|
131
|
-
http.
|
131
|
+
http = Net::HTTP.new(uri.hostname, uri.port)
|
132
|
+
http.use_ssl = uri.port == 443
|
133
|
+
http.start do |conn|
|
134
|
+
conn.request(req)
|
135
|
+
end
|
136
|
+
|
132
137
|
rescue => problem
|
133
138
|
raise RequestError, "Fail to #{method.upcase}: " + problem.to_s
|
134
139
|
end
|
data/lib/hatenablog/version.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
---
|
2
|
+
sources:
|
3
|
+
- name: ruby/gem_rbs_collection
|
4
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
5
|
+
revision: main
|
6
|
+
repo_dir: gems
|
7
|
+
path: ".gem_rbs_collection"
|
8
|
+
gems:
|
9
|
+
- name: erb
|
10
|
+
version: '0'
|
11
|
+
source:
|
12
|
+
type: stdlib
|
13
|
+
- name: net-http
|
14
|
+
version: '0'
|
15
|
+
source:
|
16
|
+
type: stdlib
|
17
|
+
- name: set
|
18
|
+
version: '0'
|
19
|
+
source:
|
20
|
+
type: stdlib
|
21
|
+
- name: time
|
22
|
+
version: '0'
|
23
|
+
source:
|
24
|
+
type: stdlib
|
25
|
+
- name: uri
|
26
|
+
version: '0'
|
27
|
+
source:
|
28
|
+
type: stdlib
|
29
|
+
- name: nokogiri
|
30
|
+
version: '1.11'
|
31
|
+
source:
|
32
|
+
type: git
|
33
|
+
name: ruby/gem_rbs_collection
|
34
|
+
revision: 88e86e0b67262f9ab6244a356e81dd9ca8c55b37
|
35
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
36
|
+
repo_dir: gems
|
data/rbs_collection.yaml
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# Download sources
|
2
|
+
sources:
|
3
|
+
- name: ruby/gem_rbs_collection
|
4
|
+
remote: https://github.com/ruby/gem_rbs_collection.git
|
5
|
+
revision: main
|
6
|
+
repo_dir: gems
|
7
|
+
|
8
|
+
# A directory to install the downloaded RBSs
|
9
|
+
path: .gem_rbs_collection
|
10
|
+
|
11
|
+
gems:
|
12
|
+
# stdlibs
|
13
|
+
- name: erb
|
14
|
+
- name: net-http
|
15
|
+
- name: set
|
16
|
+
- name: time
|
17
|
+
- name: uri
|
18
|
+
|
19
|
+
# gems
|
20
|
+
- name: nokogiri
|
21
|
+
|
22
|
+
# not used
|
23
|
+
- name: activesupport
|
24
|
+
ignore: true
|
25
|
+
- name: ast
|
26
|
+
ignore: true
|
27
|
+
- name: listen
|
28
|
+
ignore: true
|
29
|
+
- name: parallel
|
30
|
+
ignore: true
|
31
|
+
- name: rainbow
|
32
|
+
ignore: true
|
33
|
+
- name: rbs
|
34
|
+
ignore: true
|
35
|
+
- name: steep
|
36
|
+
ignore: true
|
data/sig/hatenablog.rbs
ADDED
@@ -0,0 +1,249 @@
|
|
1
|
+
module Hatenablog
|
2
|
+
VERSION: String
|
3
|
+
|
4
|
+
class Category
|
5
|
+
@document: Nokogiri::XML::Document
|
6
|
+
@categories: Array[String]
|
7
|
+
@fixed: String
|
8
|
+
|
9
|
+
def self.load_xml: (String xml) -> Category
|
10
|
+
|
11
|
+
def categories: () -> Array[String]
|
12
|
+
def each: () -> Enumerator[untyped, self]
|
13
|
+
| () { (String) -> void } -> Array[String]
|
14
|
+
def fixed?: () -> bool
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def initialize: (String xml) -> void
|
19
|
+
def parse_document: () -> void
|
20
|
+
end
|
21
|
+
|
22
|
+
class Client
|
23
|
+
DEFAULT_CONFIG_PATH: String
|
24
|
+
COLLECTION_URI: String
|
25
|
+
MEMBER_URI: String
|
26
|
+
CATEGORY_URI: String
|
27
|
+
|
28
|
+
@user_id: String
|
29
|
+
@blog_id: String
|
30
|
+
|
31
|
+
attr_writer requester: Requester::Basic | Requester::OAuth
|
32
|
+
|
33
|
+
def self.create: (?String config_file) -> Client
|
34
|
+
| (?String config_file) { (Client) -> void } -> void
|
35
|
+
|
36
|
+
def initialize: (?Configuration config) ?{ (Configuration) -> void } -> void
|
37
|
+
def title: () -> String
|
38
|
+
def author_name: () -> String
|
39
|
+
def entries: (?Integer page) -> Entries
|
40
|
+
def all_entries: () -> Entries
|
41
|
+
def next_feed: (?Feed? feed) -> Feed?
|
42
|
+
def categories: () -> Array[String]
|
43
|
+
def get_entry: (String entry_id) -> Entry
|
44
|
+
def post_entry: (?String title, ?String content, ?Array[String] categories, ?String draft) -> Entry
|
45
|
+
def update_entry: (String entry_id, ?String title, ?String content, ?Array[String] categories, ?String draft, ?String updated) -> Entry
|
46
|
+
def delete_entry: (String entry_id) -> void
|
47
|
+
def collection_uri: (?String user_id, ?String blog_id) -> String
|
48
|
+
def member_uri: (String entry_id, ?String user_id, ?String blog_id) -> String
|
49
|
+
def category_doc_uri: (?String user_id, ?String blog_id) -> String
|
50
|
+
def entry_xml: (?String title, ?String content, ?Array[String] categories, ?String draft, ?String updated, ?String author_name) -> String
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def get: (String uri) -> Net::HTTPResponse
|
55
|
+
def get_collection: (?String uri) -> Net::HTTPResponse
|
56
|
+
def get_category_doc: () -> Net::HTTPResponse
|
57
|
+
def post: (String entry_xml, ?String uri) -> Net::HTTPResponse
|
58
|
+
def put: (String entry_xml, String uri) -> Net::HTTPResponse
|
59
|
+
def delete: (String uri) -> Net::HTTPResponse
|
60
|
+
end
|
61
|
+
|
62
|
+
class Entries
|
63
|
+
include Enumerable[Entry]
|
64
|
+
|
65
|
+
@client: Client
|
66
|
+
@page: Integer
|
67
|
+
@fetch: :partial | :all
|
68
|
+
|
69
|
+
def initialize: (Client client, ?Integer page, ?(:partial | :all) fetch) -> void
|
70
|
+
def each: () -> Enumerator[untyped, self]
|
71
|
+
| () { (Entry) -> void } -> Entries
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def each_all: () { (Entry) -> void } -> Entries
|
76
|
+
def each_partial: () { (Entry) -> void } -> Entries
|
77
|
+
end
|
78
|
+
|
79
|
+
class Configuration < OpenStruct
|
80
|
+
OAUTH_KEYS: [:consumer_key, :consumer_secret, :access_token, :access_token_secret, :user_id, :blog_id]
|
81
|
+
BASIC_KEYS: [:api_key, :user_id, :blog_id]
|
82
|
+
|
83
|
+
def self.create: (String) -> Configuration
|
84
|
+
def check_valid_or_raise: () -> Configuration
|
85
|
+
|
86
|
+
# attribute accessors allowed to define dynamically
|
87
|
+
def consumer_key: () -> untyped # String?
|
88
|
+
def consumer_secret: () -> untyped # String?
|
89
|
+
def access_token: () -> untyped # String?
|
90
|
+
def access_token_secret: () -> untyped # String?
|
91
|
+
def user_id: () -> String
|
92
|
+
def blog_id: () -> String
|
93
|
+
def api_key: () -> untyped # String?
|
94
|
+
def auth_type: () -> untyped # String?
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def lacking_keys: () -> (Array[:consumer_key | :consumer_secret | :access_token | :access_token_secret | :user_id | :blog_id | :api_key | :user_id | :blog_id])
|
99
|
+
end
|
100
|
+
|
101
|
+
class ConfigurationError < StandardError
|
102
|
+
end
|
103
|
+
|
104
|
+
module AfterHook
|
105
|
+
def after_hook: (Symbol hook, *Symbol methods) -> Array[Symbol]
|
106
|
+
|
107
|
+
# methods hooked dynamically
|
108
|
+
def uri=: (String uri) -> untyped
|
109
|
+
def edit_uri=: (String uri) -> untyped
|
110
|
+
def author_name=: (String author_name) -> untyped
|
111
|
+
def title=: (String title) -> untyped
|
112
|
+
def content=: (String content) -> untyped
|
113
|
+
def updated=: (String date) -> untyped
|
114
|
+
def draft=: (String draft) -> untyped
|
115
|
+
def categories=: (Array[String] categories) -> untyped
|
116
|
+
|
117
|
+
# workaround for using `Module` instance methods in `after_hook`
|
118
|
+
def alias_method: (::Symbol | ::String new_name, ::Symbol | ::String old_name) -> ::Symbol
|
119
|
+
def define_method: (Symbol | String arg0, ?Proc | Method | UnboundMethod arg1) -> Symbol
|
120
|
+
| (Symbol | String arg0) { () -> untyped } -> Symbol
|
121
|
+
def instance_methods: (?boolish include_super) -> ::Array[Symbol]
|
122
|
+
end
|
123
|
+
|
124
|
+
class Entry
|
125
|
+
extend AfterHook
|
126
|
+
|
127
|
+
@document: Nokogiri::XML::Document
|
128
|
+
@formatted_content: untyped
|
129
|
+
|
130
|
+
attr_accessor uri: String
|
131
|
+
attr_accessor author_name: String
|
132
|
+
attr_accessor title: String
|
133
|
+
attr_accessor content: String
|
134
|
+
attr_accessor draft: String
|
135
|
+
|
136
|
+
attr_reader edit_uri: String
|
137
|
+
attr_reader id: String?
|
138
|
+
attr_reader updated : Time?
|
139
|
+
|
140
|
+
attr_writer categories: Array[String]
|
141
|
+
|
142
|
+
def self.load_xml: (String xml) -> Entry
|
143
|
+
def self.create: (?uri: String, ?edit_uri: String, ?author_name: String, ?title: String, ?content: String, ?draft: String, ?categories: Array[String], ?updated: String) ?{ (Entry) -> void } -> Entry
|
144
|
+
def self.build_xml: (String uri, String edit_uri, String author_name, String title, String content, String draft, Array[String]? categories, String? updated) -> String
|
145
|
+
|
146
|
+
def updated=: (String date) -> Time?
|
147
|
+
def edit_uri=: (String uri) -> void
|
148
|
+
def draft?: () -> bool
|
149
|
+
def categories: () -> Array[String]
|
150
|
+
def each_category: () { (String) -> void } -> Array[String]
|
151
|
+
def to_xml: () -> String
|
152
|
+
def formatted_content: () -> untyped # result of Nokogiri::XML::NodeSet#[]
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
def initialize: (String xml) -> void
|
157
|
+
def parse_document: () -> void
|
158
|
+
def parse_categories: () -> Array[untyped]
|
159
|
+
def update_xml: () -> void
|
160
|
+
def categories_modified?: (Nokogiri::XML::NodeSet old_categories, Array[String] new_categories) -> bool
|
161
|
+
end
|
162
|
+
|
163
|
+
class Feed
|
164
|
+
@document: Nokogiri::XML::Document
|
165
|
+
@entries: Array[Entry]
|
166
|
+
|
167
|
+
attr_reader uri: String
|
168
|
+
attr_reader next_uri: String
|
169
|
+
attr_reader title: String
|
170
|
+
attr_reader author_name: String
|
171
|
+
attr_reader updated: Time
|
172
|
+
|
173
|
+
def self.load_xml: (String xml) -> Feed
|
174
|
+
|
175
|
+
def entries: () -> Array[Entry]
|
176
|
+
def each_entry: () { (Entry) -> void } -> Array[Entry]
|
177
|
+
def has_next?: () -> bool
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
def initialize: (String xml) -> void
|
182
|
+
def parse_document: () -> void
|
183
|
+
def parse_entry: () -> void
|
184
|
+
end
|
185
|
+
|
186
|
+
module Requester
|
187
|
+
ATOM_CONTENT_TYPE: String
|
188
|
+
DEFAULT_HEADER: Hash[String, String]
|
189
|
+
|
190
|
+
def self.create: (Configuration config) -> (Basic | OAuth)
|
191
|
+
|
192
|
+
class RequestError < StandardError
|
193
|
+
end
|
194
|
+
|
195
|
+
class OAuth
|
196
|
+
@access_token: ::OAuth::AccessToken
|
197
|
+
|
198
|
+
def initialize: (::OAuth::AccessToken access_token) -> void
|
199
|
+
def get: (String uri) -> Net::HTTPResponse
|
200
|
+
def post: (String uri, ?String body, ?Hash[String, String] headers) -> Net::HTTPResponse
|
201
|
+
def put: (String uri, ?String body, ?Hash[String, String] headers) -> Net::HTTPResponse
|
202
|
+
def delete: (String uri, ?Hash[String, String] headers) -> Net::HTTPResponse
|
203
|
+
|
204
|
+
private
|
205
|
+
|
206
|
+
def request: (:get | :post | :put | :delete method, String uri, ?body: String?, ?headers: Hash[String, String]?) -> Net::HTTPResponse
|
207
|
+
end
|
208
|
+
|
209
|
+
class Basic
|
210
|
+
METHODS: {get: singleton(Net::HTTP::Get), post: singleton(Net::HTTP::Post), put: singleton(Net::HTTP::Put), delete: singleton(Net::HTTP::Delete)}
|
211
|
+
|
212
|
+
@user_id: String
|
213
|
+
@api_key: String
|
214
|
+
|
215
|
+
def initialize: (String user_id, String api_key) -> void
|
216
|
+
def get: (String uri) -> Net::HTTPResponse
|
217
|
+
def post: (String uri, String body, ?Hash[String, String] headers) -> Net::HTTPResponse
|
218
|
+
def put: (String uri, String body, ?Hash[String, String] headers) -> Net::HTTPResponse
|
219
|
+
def delete: (String uri, ?Hash[String, String] headers) -> Net::HTTPResponse
|
220
|
+
|
221
|
+
private
|
222
|
+
|
223
|
+
def request: (String uri, :get | :post | :put | :delete method, ?body: String?, ?headers: Hash[String, String]) -> Net::HTTPResponse
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# polyfill for ostruct
|
229
|
+
class OpenStruct
|
230
|
+
def initialize: (?Hash[untyped, untyped]? hash) -> OpenStruct
|
231
|
+
def []: (String | Symbol) -> Object
|
232
|
+
def to_h: -> Hash[Symbol, Object]
|
233
|
+
end
|
234
|
+
|
235
|
+
# polyfill for oauth
|
236
|
+
module OAuth
|
237
|
+
class AccessToken
|
238
|
+
def initialize: (untyped, untyped, ?untyped) -> void
|
239
|
+
end
|
240
|
+
|
241
|
+
class Consumer
|
242
|
+
def initialize: (untyped, untyped, ?untyped) -> void
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# polyfill for yaml
|
247
|
+
module YAML
|
248
|
+
def self.load: (String yaml, ?String? filename, ?fallback: bool, ?symbolize_names: bool) -> untyped
|
249
|
+
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.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kohei Yamamoto
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -126,19 +126,21 @@ description: Hatenablog AtomPub API library
|
|
126
126
|
email:
|
127
127
|
- kymmt90@gmail.com
|
128
128
|
executables:
|
129
|
-
-
|
129
|
+
- get_hatena_oauth_access_token
|
130
130
|
extensions: []
|
131
131
|
extra_rdoc_files: []
|
132
132
|
files:
|
133
133
|
- ".github/workflows/build.yml"
|
134
134
|
- ".gitignore"
|
135
|
+
- CHANGELOG.md
|
135
136
|
- Gemfile
|
136
137
|
- LICENSE.txt
|
137
138
|
- README.md
|
138
139
|
- Rakefile
|
140
|
+
- Steepfile
|
139
141
|
- bin/console
|
140
142
|
- bin/setup
|
141
|
-
- exe/
|
143
|
+
- exe/get_hatena_oauth_access_token
|
142
144
|
- hatenablog.gemspec
|
143
145
|
- lib/hatenablog.rb
|
144
146
|
- lib/hatenablog/category.rb
|
@@ -148,11 +150,14 @@ files:
|
|
148
150
|
- lib/hatenablog/feed.rb
|
149
151
|
- lib/hatenablog/requester.rb
|
150
152
|
- lib/hatenablog/version.rb
|
153
|
+
- rbs_collection.lock.yaml
|
154
|
+
- rbs_collection.yaml
|
155
|
+
- sig/hatenablog.rbs
|
151
156
|
homepage: https://github.com/kymmt90/hatenablog
|
152
157
|
licenses:
|
153
158
|
- MIT
|
154
159
|
metadata: {}
|
155
|
-
post_install_message:
|
160
|
+
post_install_message:
|
156
161
|
rdoc_options: []
|
157
162
|
require_paths:
|
158
163
|
- lib
|
@@ -160,15 +165,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
160
165
|
requirements:
|
161
166
|
- - ">="
|
162
167
|
- !ruby/object:Gem::Version
|
163
|
-
version: '2.
|
168
|
+
version: '2.3'
|
164
169
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
170
|
requirements:
|
166
171
|
- - ">="
|
167
172
|
- !ruby/object:Gem::Version
|
168
173
|
version: '0'
|
169
174
|
requirements: []
|
170
|
-
rubygems_version: 3.
|
171
|
-
signing_key:
|
175
|
+
rubygems_version: 3.2.3
|
176
|
+
signing_key:
|
172
177
|
specification_version: 4
|
173
178
|
summary: Hatenablog AtomPub API library
|
174
179
|
test_files: []
|