hatenablog 0.7.0 → 0.8.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
  SHA256:
3
- metadata.gz: 2f5ba2be4110aba1299f43e9392477651511fc8f25b833fa0cbbadf19ead23b9
4
- data.tar.gz: afbde859959d37d364e249e22b4a02206db70bd274040fb62068227f74e9447e
3
+ metadata.gz: 5c6ebd627cfd566a53f9423b632b3ef6f42d285e2ffa84b176af438022a78bbe
4
+ data.tar.gz: c7dbd064aee0d3557c17464be93b351cc741b973c16ede5dd6d8cf6afde30bfc
5
5
  SHA512:
6
- metadata.gz: 3578cefbfeddc8cd8d7ebd143fc581daea4e76a8299acb2d1de0004b18ead98969f7245cd9569c216664163e0940ae54a85f0a3a73d9edeb83be8e054b5ca4d9
7
- data.tar.gz: 34c100e0157ae121c65baf6c71cbd13b50fbcad17a6fe3e330bb4413f290632568a287c33562b72a1dc7c49eb924f93b29415f8e67544684722a1cd2bc506174
6
+ metadata.gz: fe094c01e6c51c1b41bd674bc6aa891767532c3472135312709d090bd1301dfcc3041fb95e90a7a641c20ea07f5a32403d6d006a13a8a6c16aa319c74ad1c454
7
+ data.tar.gz: 8c86b99f15106170419012c8e8d15c90b1a2644488a62b16cfb76defad288ca81cb04a920f772d8fedf314f88ff8c4351889439a766e59305caad5134d0d15cf
@@ -1,32 +1,49 @@
1
1
  name: build
2
2
 
3
- on: [pull_request]
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.4', '2.5', '2.6', '2.7']
14
+ ruby: ['2.6', '2.7', '3.0', '3.1.0-preview1']
11
15
  include:
12
- - ruby: '2.7'
16
+ - ruby: '3.0'
13
17
  report-coverage: true
14
18
  steps:
15
- - uses: actions/checkout@v2
16
- - uses: ruby/setup-ruby@v1
17
- with:
18
- ruby-version: ${{ matrix.ruby }}
19
- - run: gem install bundler
20
- - run: bundle install -j4
21
- - name: Run tests and report test coverage
22
- if: matrix.report-coverage
23
- uses: paambaati/codeclimate-action@v2.4.0
24
- env:
25
- CC_TEST_REPORTER_ID: 309cf0784d00d2a6009566d28be111a8a0280cdeb2da280225eedf577b16beb5
26
- with:
27
- coverageCommand: bundle exec rake
28
- - name: Run tests
29
- if: "!matrix.report-coverage"
30
- env:
31
- TZ: Asia/Tokyo
32
- run: bundle exec rake
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
@@ -34,3 +34,4 @@ Gemfile.lock
34
34
 
35
35
  # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
36
36
  .rvmrc
37
+ /.gem_rbs_collection/
data/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
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.8.0 - 2021-11-20
10
+
11
+ ### Added
12
+
13
+ - [Create the signature with RBS](https://github.com/kymmt90/hatenablog/pull/24)
14
+ - This is experimental
15
+
16
+ ### Changed
17
+
18
+ - [Change the executable name to more specific one](https://github.com/kymmt90/hatenablog/pull/26)
19
+ - From `get_access_token` to `get_hatena_oauth_access_token`
20
+ - [Use only supported Rubies in 2021-11](https://github.com/kymmt90/hatenablog/pull/27)
21
+ - Drop Ruby 2.4 and 2.5 and add Ruby 3.1.0-preview1
data/Gemfile CHANGED
@@ -1,7 +1,11 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ group :development, :test do
4
+ gem 'steep'
5
+ end
6
+
3
7
  group :test do
4
- gem 'simplecov', '~> 0.17.1'
8
+ gem 'simplecov'
5
9
  end
6
10
 
7
11
  # Specify your gem's dependencies in hatenablog.gemspec
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
- gem 'hatenablog'
22
+ ```
23
+ gem 'hatenablog'
24
+ ```
23
25
 
24
26
  And then execute:
25
27
 
26
- $ bundle
28
+ ```
29
+ $ bundle
30
+ ```
27
31
 
28
32
  Or install it yourself as:
29
33
 
30
- $ gem install hatenablog
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
- $ get_access_token <your consumer key> <your consumer secret>
45
- Visit this website and get the PIN: https://www.hatena.com/oauth/authorize?oauth_token=XXXXXXXXXXXXXXXXXXXX
46
- Enter the PIN: <your PIN> [Enter]
47
- Access token: <your access token>
48
- Access token secret: <your access token secret>
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.update # Updated datetime
175
+ feed.updated # Updated datetime
168
176
 
169
177
  feed.entries # entries in the feed
170
178
  feed.each_entry do |entry|
data/Rakefile CHANGED
@@ -11,6 +11,7 @@ Rake::TestTask.new do |t|
11
11
  t.libs << "test"
12
12
  t.test_files = Dir["test/hatenablog/*_test.rb"]
13
13
  t.verbose = true
14
+ t.warning = true
14
15
  end
15
16
 
16
17
  YARD::Rake::YardocTask.new do |t|
data/Steepfile ADDED
@@ -0,0 +1,11 @@
1
+ D = Steep::Diagnostic
2
+
3
+ target :lib do
4
+ check "lib"
5
+ signature "sig"
6
+
7
+ repo_path ".gem_rbs_collection"
8
+ library "erb", "net-http", "nokogiri", "set", "time", "uri"
9
+
10
+ configure_code_diagnostics(D::Ruby.all_error)
11
+ end
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.2'
22
+ spec.required_ruby_version = '>= 2.3'
23
23
 
24
24
  spec.add_development_dependency "bundler"
25
25
  spec.add_development_dependency "rake"
@@ -16,9 +16,10 @@ module Hatenablog
16
16
  end
17
17
 
18
18
  def each(&block)
19
- return enum_for(__method__) unless block_given?
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([]) do |categories, category|
42
+ @categories = @document.css('atom|category').inject(Array.new) do |categories, category|
42
43
  categories << category['term'].to_s
43
44
  end
44
45
 
@@ -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 = nil)
28
+ def initialize(config = Configuration.new)
28
29
  if block_given?
29
- yield config = Configuration.new
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, nil)
63
+ Entries.new(self, 0, :all)
63
64
  end
64
65
 
65
66
  # Get the next feed of the given feed.
@@ -161,7 +162,7 @@ module Hatenablog
161
162
  xml.name author_name
162
163
  end
163
164
  xml.content(content, type: 'text/x-markdown')
164
- xml.updated updated unless updated.empty? || updated.nil?
165
+ xml.updated updated if updated && !updated.empty?
165
166
  categories.each do |category|
166
167
  xml.category(term: category)
167
168
  end
@@ -207,19 +208,45 @@ module Hatenablog
207
208
  class Entries
208
209
  include Enumerable
209
210
 
210
- def initialize(client, page = 0)
211
+ def initialize(client, page = 0, fetch = :partial)
211
212
  @client = client
212
213
  @page = page
214
+ @fetch = fetch
213
215
  end
214
216
 
215
217
  def each(&block)
216
- return enum_for(__method__) unless block_given?
218
+ return enum_for unless block_given?
219
+
220
+ # @type var block: ^(Entry) -> void
221
+ if @fetch == :all
222
+ each_all(&block)
223
+ else
224
+ each_partial(&block)
225
+ end
226
+ end
227
+
228
+ private
229
+
230
+ def each_all(&block)
231
+ feed = nil
232
+
233
+ while feed = @client.next_feed(feed)
234
+ feed.entries.each { |entry| block.call(entry) }
235
+ end
236
+
237
+ self
238
+ end
239
+
240
+ def each_partial(&block)
241
+ feed = nil
217
242
 
218
243
  current_page = 0
219
- until (@page && current_page > @page) || !(feed = @client.next_feed(feed))
244
+ while current_page <= @page && feed = @client.next_feed(feed)
220
245
  feed.entries.each { |entry| block.call(entry) }
221
246
  current_page += 1
222
247
  end
248
+
249
+ self
223
250
  end
224
251
  end
225
252
  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
 
@@ -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
- attr_reader :edit_uri, :id, :updated
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)
@@ -147,7 +156,7 @@ module Hatenablog
147
156
  end
148
157
 
149
158
  def parse_categories
150
- categories = @document.css('category').inject([]) do |categories, category|
159
+ categories = @document.css('category').inject(Array.new) do |categories, category|
151
160
  categories << category['term'].to_s
152
161
  end
153
162
  categories
@@ -162,7 +171,7 @@ module Hatenablog
162
171
  @document.at_css('entry app|control app|draft').content = @draft
163
172
 
164
173
  unless @updated.nil? || @document.at_css('entry updated').nil?
165
- @document.at_css('entry updated').content = @updated.iso8601
174
+ @document.at_css('entry updated').content = @updated&.iso8601
166
175
  end
167
176
 
168
177
  unless @categories.nil?
@@ -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([]) do |entries, entry|
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)
@@ -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 = nil)
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 = nil )
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 = nil)
116
+ def delete(uri, headers = {})
117
117
  request(uri, :delete, headers: headers)
118
118
  end
119
119
 
120
120
  private
121
- def request(uri, method, body: nil, headers: nil)
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.start(uri.hostname, uri.port, use_ssl: uri.port == 443)
131
- http.request(req)
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
@@ -1,3 +1,3 @@
1
1
  module Hatenablog
2
- VERSION = "0.7.0"
2
+ VERSION = "0.8.0"
3
3
  end
@@ -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
@@ -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
@@ -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.7.0
4
+ version: 0.8.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: 2020-07-08 00:00:00.000000000 Z
11
+ date: 2021-11-20 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
- - get_access_token
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/get_access_token
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.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.1.2
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: []