kakuyomu_agent 0.1.0 → 0.2.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 +6 -3
- data/lib/kakuyomu_agent.rb +12 -87
- data/lib/kakuyomu_agent/action.rb +16 -0
- data/lib/kakuyomu_agent/actions/create_episode.rb +27 -0
- data/lib/kakuyomu_agent/actions/delete_episode.rb +22 -0
- data/lib/kakuyomu_agent/actions/login.rb +20 -0
- data/lib/kakuyomu_agent/actions/update_episode.rb +27 -0
- data/lib/kakuyomu_agent/error.rb +5 -0
- data/lib/kakuyomu_agent/url_helper.rb +31 -0
- data/lib/kakuyomu_agent/version.rb +1 -1
- metadata +9 -3
- data/lib/kakuyomu_agent/url_utils.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5402095c5853b227b4f10d74fdb79430e6352af2b5a005c3a89ad5ab2a317714
|
4
|
+
data.tar.gz: 5e309384fb7094fb5a74203fd605e33c4d3150fd8d16dbc76aded9d3179f830a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 455b5695ee51d1a9c231292cc4249cf58df425abd590c1cfd0ca530fd5d34d7815759cfc223f92f2b305088b0727942b0bb1af7525979be5563220e37441a429
|
7
|
+
data.tar.gz: c4ee9b0911c4fe852cea0a79454afe37839f7de58d9cd3546f7ca73866e314ef9def5ee2881d491db1db3fb1d45c76f49fe7c727af99c2f8f38ee565863987b0
|
data/README.md
CHANGED
@@ -23,16 +23,19 @@ Or install it yourself as:
|
|
23
23
|
```ruby
|
24
24
|
require 'kakuyomu_agent'
|
25
25
|
|
26
|
-
agent = KakuyomuAgent.new
|
26
|
+
agent = KakuyomuAgent.new(driver: Selenium::WebDriver.for(:chrome))
|
27
27
|
|
28
28
|
# ログイン
|
29
29
|
agent.login!(email: YOUR_EMAIL, password: YOUR_PASSWORD)
|
30
30
|
|
31
31
|
# 小説の URL から work_id を抽出
|
32
|
-
work_id = KakuyomuAgent::
|
32
|
+
work_id = KakuyomuAgent::UrlHelper.extract_work_id('https://kakuyomu.jp/works/1234567890123456789') # => 1234567890123456789
|
33
33
|
|
34
34
|
# エピソードを執筆
|
35
|
-
|
35
|
+
episode_url = agent.create_episode(work_id: work_id, title: 'タイトル', body: '本文')
|
36
|
+
|
37
|
+
# エピソードの URL から episode_id を抽出
|
38
|
+
episode_id = KakuyomuAgent::UrlHelper.extract_episode_id(episode_url)
|
36
39
|
|
37
40
|
# エピソードを編集
|
38
41
|
agent.update_episode(work_id: work_id, episode_id: episode_id, title: '新しいタイトル', body: '新しい本文')
|
data/lib/kakuyomu_agent.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
require 'selenium-webdriver'
|
2
2
|
|
3
|
-
require_relative 'kakuyomu_agent/
|
3
|
+
require_relative 'kakuyomu_agent/url_helper'
|
4
|
+
require_relative 'kakuyomu_agent/action'
|
5
|
+
require_relative 'kakuyomu_agent/error'
|
4
6
|
require_relative 'kakuyomu_agent/version'
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
require_relative 'kakuyomu_agent/actions/create_episode'
|
9
|
+
require_relative 'kakuyomu_agent/actions/delete_episode'
|
10
|
+
require_relative 'kakuyomu_agent/actions/login'
|
11
|
+
require_relative 'kakuyomu_agent/actions/update_episode'
|
9
12
|
|
13
|
+
class KakuyomuAgent
|
10
14
|
BASE_URL = 'https://kakuyomu.jp'
|
11
15
|
|
12
16
|
attr_reader :base_url, :driver
|
@@ -22,101 +26,22 @@ class KakuyomuAgent
|
|
22
26
|
end
|
23
27
|
|
24
28
|
def login!(email:, password:)
|
25
|
-
|
26
|
-
driver.find_element(name: 'email_address').send_keys(email)
|
27
|
-
driver.find_element(name: 'password').send_keys(password)
|
28
|
-
driver.find_element(xpath: '//button[text()="ログイン"]').click
|
29
|
-
|
30
|
-
Selenium::WebDriver::Wait.new.until do
|
31
|
-
driver.find_element(id: 'page-my')
|
32
|
-
end
|
33
|
-
|
29
|
+
Actions::Login.new(self).run(email, password)
|
34
30
|
@logged_in = true
|
35
|
-
rescue Selenium::WebDriver::Error::WebDriverError => e
|
36
|
-
raise Error, "Logging in failed: #{e.message}"
|
37
31
|
end
|
38
32
|
|
39
33
|
def create_episode(work_id:, title:, body:)
|
40
34
|
raise NotLoggedInError unless logged_in?
|
41
|
-
|
42
|
-
driver.navigate.to(new_episode_url(work_id))
|
43
|
-
|
44
|
-
title_input = driver.find_element(name: 'title')
|
45
|
-
title_input.clear
|
46
|
-
title_input.send_keys(title)
|
47
|
-
|
48
|
-
driver.find_element(name: 'body').send_keys(body)
|
49
|
-
|
50
|
-
driver.find_element(id: 'reserveButton').click
|
51
|
-
driver.find_element(id: 'reservationControl-footer').find_element(tag_name: 'button').click
|
52
|
-
|
53
|
-
Selenium::WebDriver::Wait.new.until do
|
54
|
-
driver.find_element(id: 'page-my-works-episodes-published')
|
55
|
-
end
|
56
|
-
|
57
|
-
episode_id = UrlUtils.extract_episode_id(driver.current_url)
|
58
|
-
episode_url(work_id, episode_id)
|
59
|
-
rescue Selenium::WebDriver::Error::WebDriverError => e
|
60
|
-
raise Error, "Creating episode failed: #{e.message}"
|
35
|
+
Actions::CreateEpisode.new(self).run(work_id, title, body)
|
61
36
|
end
|
62
37
|
|
63
38
|
def update_episode(work_id:, episode_id:, title:, body:)
|
64
39
|
raise NotLoggedInError unless logged_in?
|
65
|
-
|
66
|
-
driver.navigate.to(edit_episode_url(work_id, episode_id))
|
67
|
-
|
68
|
-
title_input = driver.find_element(name: 'title')
|
69
|
-
title_input.clear
|
70
|
-
title_input.send_keys(title)
|
71
|
-
|
72
|
-
body_textarea = driver.find_element(name: 'body')
|
73
|
-
body_textarea.clear
|
74
|
-
body_textarea.send_keys(body)
|
75
|
-
|
76
|
-
driver.find_element(id: 'updateButton').click
|
77
|
-
|
78
|
-
Selenium::WebDriver::Wait.new.until do
|
79
|
-
driver.find_element(id: 'page-my-works-episodes-published')
|
80
|
-
end
|
81
|
-
|
82
|
-
episode_url(work_id, episode_id)
|
83
|
-
rescue Selenium::WebDriver::Error::WebDriverError => e
|
84
|
-
raise Error, "Updating episode failed: #{e.message}"
|
40
|
+
Actions::UpdateEpisode.new(self).run(work_id, episode_id, title, body)
|
85
41
|
end
|
86
42
|
|
87
43
|
def delete_episode(work_id:, episode_id:)
|
88
44
|
raise NotLoggedInError unless logged_in?
|
89
|
-
|
90
|
-
driver.navigate.to(edit_episode_url(work_id, episode_id))
|
91
|
-
driver.find_element(id: 'contentMainHeader-toolButton').click
|
92
|
-
driver.find_element(id: 'contentAsideHeader').find_element(xpath: '//*[contains(text(), "ツール")]').click
|
93
|
-
driver.find_element(id: 'deleteEpisode').find_element(tag_name: 'button').click
|
94
|
-
driver.switch_to.alert.accept
|
95
|
-
|
96
|
-
Selenium::WebDriver::Wait.new.until do
|
97
|
-
driver.find_element(id: 'modelessMessage')
|
98
|
-
end
|
99
|
-
|
100
|
-
true
|
101
|
-
rescue Selenium::WebDriver::Error::WebDriverError => e
|
102
|
-
raise Error, "Deleting episode failed: #{e.message}"
|
103
|
-
end
|
104
|
-
|
105
|
-
private
|
106
|
-
|
107
|
-
def login_url
|
108
|
-
"#{base_url}/login"
|
109
|
-
end
|
110
|
-
|
111
|
-
def episode_url(work_id, episode_id)
|
112
|
-
"#{base_url}/works/#{work_id}/episodes/#{episode_id}"
|
113
|
-
end
|
114
|
-
|
115
|
-
def new_episode_url(work_id)
|
116
|
-
"#{base_url}/my/works/#{work_id}/episodes/new"
|
117
|
-
end
|
118
|
-
|
119
|
-
def edit_episode_url(work_id, episode_id)
|
120
|
-
"#{base_url}/my/works/#{work_id}/episodes/#{episode_id}"
|
45
|
+
Actions::DeleteEpisode.new(self).run(work_id, episode_id)
|
121
46
|
end
|
122
47
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class KakuyomuAgent
|
2
|
+
module Actions
|
3
|
+
class CreateEpisode < Action
|
4
|
+
def run(work_id, title, body)
|
5
|
+
driver.get(new_episode_url(work_id))
|
6
|
+
|
7
|
+
title_input = driver.find_element(name: 'title')
|
8
|
+
title_input.clear
|
9
|
+
title_input.send_keys(title)
|
10
|
+
|
11
|
+
driver.find_element(name: 'body').send_keys(body)
|
12
|
+
|
13
|
+
driver.find_element(id: 'reserveButton').click
|
14
|
+
driver.find_element(id: 'reservationControl-footer').find_element(tag_name: 'button').click
|
15
|
+
|
16
|
+
Selenium::WebDriver::Wait.new.until do
|
17
|
+
driver.find_element(id: 'page-my-works-episodes-published')
|
18
|
+
end
|
19
|
+
|
20
|
+
episode_id = UrlHelper.extract_episode_id(driver.current_url)
|
21
|
+
episode_url(work_id, episode_id)
|
22
|
+
rescue Selenium::WebDriver::Error::WebDriverError => e
|
23
|
+
raise ActionFailedError.new(e)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class KakuyomuAgent
|
2
|
+
module Actions
|
3
|
+
class DeleteEpisode < Action
|
4
|
+
def run(work_id, episode_id)
|
5
|
+
driver.get(edit_episode_url(work_id, episode_id))
|
6
|
+
|
7
|
+
driver.find_element(id: 'contentMainHeader-toolButton').click
|
8
|
+
driver.find_element(id: 'contentAsideHeader').find_element(xpath: '//*[contains(text(), "ツール")]').click
|
9
|
+
driver.find_element(id: 'deleteEpisode').find_element(tag_name: 'button').click
|
10
|
+
driver.switch_to.alert.accept
|
11
|
+
|
12
|
+
Selenium::WebDriver::Wait.new.until do
|
13
|
+
driver.find_element(id: 'modelessMessage')
|
14
|
+
end
|
15
|
+
|
16
|
+
true
|
17
|
+
rescue Selenium::WebDriver::Error::WebDriverError => e
|
18
|
+
raise ActionFailedError.new(e)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class KakuyomuAgent
|
2
|
+
module Actions
|
3
|
+
class Login < Action
|
4
|
+
def run(email, password)
|
5
|
+
driver.get(login_url)
|
6
|
+
|
7
|
+
driver.find_element(name: 'email_address').send_keys(email)
|
8
|
+
driver.find_element(name: 'password').send_keys(password)
|
9
|
+
|
10
|
+
driver.find_element(xpath: '//button[text()="ログイン"]').click
|
11
|
+
|
12
|
+
Selenium::WebDriver::Wait.new.until do
|
13
|
+
driver.find_element(id: 'page-my')
|
14
|
+
end
|
15
|
+
rescue Selenium::WebDriver::Error::WebDriverError => e
|
16
|
+
raise ActionFailedError.new(e)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class KakuyomuAgent
|
2
|
+
module Actions
|
3
|
+
class UpdateEpisode < Action
|
4
|
+
def run(work_id, episode_id, title, body)
|
5
|
+
driver.get(edit_episode_url(work_id, episode_id))
|
6
|
+
|
7
|
+
title_input = driver.find_element(name: 'title')
|
8
|
+
title_input.clear
|
9
|
+
title_input.send_keys(title)
|
10
|
+
|
11
|
+
body_textarea = driver.find_element(name: 'body')
|
12
|
+
body_textarea.clear
|
13
|
+
body_textarea.send_keys(body)
|
14
|
+
|
15
|
+
driver.find_element(id: 'updateButton').click
|
16
|
+
|
17
|
+
Selenium::WebDriver::Wait.new.until do
|
18
|
+
driver.find_element(id: 'page-my-works-episodes-published')
|
19
|
+
end
|
20
|
+
|
21
|
+
episode_url(work_id, episode_id)
|
22
|
+
rescue Selenium::WebDriver::Error::WebDriverError => e
|
23
|
+
raise ActionFailedError.new(e)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class KakuyomuAgent
|
2
|
+
module UrlHelper
|
3
|
+
class << self
|
4
|
+
def extract_work_id(url)
|
5
|
+
url[%r{works/(\d+)}, 1]
|
6
|
+
end
|
7
|
+
|
8
|
+
def extract_episode_id(url)
|
9
|
+
url[%r{episodes/(\d+)}, 1]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def login_url
|
16
|
+
"#{base_url}/login"
|
17
|
+
end
|
18
|
+
|
19
|
+
def episode_url(work_id, episode_id)
|
20
|
+
"#{base_url}/works/#{work_id}/episodes/#{episode_id}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def new_episode_url(work_id)
|
24
|
+
"#{base_url}/my/works/#{work_id}/episodes/new"
|
25
|
+
end
|
26
|
+
|
27
|
+
def edit_episode_url(work_id, episode_id)
|
28
|
+
"#{base_url}/my/works/#{work_id}/episodes/#{episode_id}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kakuyomu_agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fuji Nakahara
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: selenium-webdriver
|
@@ -129,7 +129,13 @@ files:
|
|
129
129
|
- bin/setup
|
130
130
|
- kakuyomu_agent.gemspec
|
131
131
|
- lib/kakuyomu_agent.rb
|
132
|
-
- lib/kakuyomu_agent/
|
132
|
+
- lib/kakuyomu_agent/action.rb
|
133
|
+
- lib/kakuyomu_agent/actions/create_episode.rb
|
134
|
+
- lib/kakuyomu_agent/actions/delete_episode.rb
|
135
|
+
- lib/kakuyomu_agent/actions/login.rb
|
136
|
+
- lib/kakuyomu_agent/actions/update_episode.rb
|
137
|
+
- lib/kakuyomu_agent/error.rb
|
138
|
+
- lib/kakuyomu_agent/url_helper.rb
|
133
139
|
- lib/kakuyomu_agent/version.rb
|
134
140
|
homepage: https://github.com/fuji-nakahara/kakuyomu_agent
|
135
141
|
licenses:
|