kakuyomu_agent 0.1.0 → 0.2.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: 15e9b3078d627199445d9d6591c88114143d245740ac7448c06dfe03b75bf668
4
- data.tar.gz: fee06253f5b28622efb18277c15a6b232a5cc413d81e09e4f02d59c4f5f3f983
3
+ metadata.gz: 5402095c5853b227b4f10d74fdb79430e6352af2b5a005c3a89ad5ab2a317714
4
+ data.tar.gz: 5e309384fb7094fb5a74203fd605e33c4d3150fd8d16dbc76aded9d3179f830a
5
5
  SHA512:
6
- metadata.gz: 779b6da5f1ded127de3e618e2957c791c00601848bdc1315dd93a5ca1a4a64aea7997e39372660b58162867e2c69275f9a518489f9c429c4937697709711c8e7
7
- data.tar.gz: dcd128af4875b98da9f58adf24a968ecc4998f026498126285434170afb5b8d101432ddd4e5cb9661997dd0c0e91b6269fb832a181bc8064fa92e21f63ff610c
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::UrlUtils.extract_work_id('https://kakuyomu.jp/works/1234567890123456789') # => 1234567890123456789
32
+ work_id = KakuyomuAgent::UrlHelper.extract_work_id('https://kakuyomu.jp/works/1234567890123456789') # => 1234567890123456789
33
33
 
34
34
  # エピソードを執筆
35
- episode_id = agent.create_episode(work_id: work_id, title: 'タイトル', body: '本文')
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: '新しい本文')
@@ -1,12 +1,16 @@
1
1
  require 'selenium-webdriver'
2
2
 
3
- require_relative 'kakuyomu_agent/url_utils'
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
- class KakuyomuAgent
7
- Error = Class.new(StandardError)
8
- NotLoggedInError = Class.new(Error)
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
- driver.navigate.to(login_url)
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,16 @@
1
+ class KakuyomuAgent
2
+ class Action
3
+ include UrlHelper
4
+ extend Forwardable
5
+
6
+ def_delegators :@agent, :base_url, :driver
7
+
8
+ def initialize(agent)
9
+ @agent = agent
10
+ end
11
+
12
+ def run
13
+ raise NotImplementedError
14
+ end
15
+ end
16
+ 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,5 @@
1
+ class KakuyomuAgent
2
+ Error = Class.new(StandardError)
3
+ NotLoggedInError = Class.new(Error)
4
+ ActionFailedError = Class.new(Error)
5
+ 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
@@ -1,3 +1,3 @@
1
1
  class KakuyomuAgent
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  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.1.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-10 00:00:00.000000000 Z
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/url_utils.rb
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:
@@ -1,13 +0,0 @@
1
- class KakuyomuAgent
2
- module UrlUtils
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
- end
13
- end