hatenablog 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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: []