kobot 1.0.0 → 1.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +30 -19
- data/bin/console +1 -0
- data/exe/kobot +10 -1
- data/kobot.gemspec +1 -1
- data/lib/kobot.rb +1 -2
- data/lib/kobot/config.rb +2 -2
- data/lib/kobot/credential.rb +7 -8
- data/lib/kobot/engine.rb +56 -24
- data/lib/kobot/exception.rb +2 -1
- data/lib/kobot/mailer.rb +0 -2
- data/lib/kobot/option.rb +17 -7
- data/lib/kobot/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3eba14b1e3b076a368dd700c2ac46a9db4fd13bf57a58e29797de7db7eb16fc3
|
4
|
+
data.tar.gz: 1926333cefbaf4272ae117cc7afb12284ed85d6ff41aa96a02094904599b5312
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '08ad9cb2d55c2931a34ed4243884a7e16c189d1d914e5aa935cfd4d32fc3d3d7567cdaecdb53de54e980e84ec4c6e696761b7f9b15fb65e3a0eef11f829370e5'
|
7
|
+
data.tar.gz: f8662e41fe53d35df04b1b530f946621330124684d6bd955e6b18e53830efaef74c22db66818a8a3958aa8a4745b4d37090419f538962c3a4876e8dbb9b6c1d7
|
data/CHANGELOG.md
CHANGED
@@ -1,2 +1,24 @@
|
|
1
1
|
### v1.0.0
|
2
2
|
- Initial release
|
3
|
+
|
4
|
+
### v1.1.0
|
5
|
+
- Deprecated lower-case environment variables for credentials configuration
|
6
|
+
- Updated option help doc to indicate weekends and public holidays are skipped by default
|
7
|
+
- Updated required_ruby_version to be >= 2.4.0 to align with the webdrivers dependency
|
8
|
+
|
9
|
+
### v1.2.0
|
10
|
+
- Added an option to allow forcibly running regardless of weekends or public holidays
|
11
|
+
- Added an ENV flag to allow requiring lib in local workspace for development purpose
|
12
|
+
|
13
|
+
### v1.2.1
|
14
|
+
- Improved logging for better readability in logs
|
15
|
+
- Switched to builtin Logger#deprecate from Logger#warn for deprecations
|
16
|
+
- Renamed internal method to skip? from holiday? as it was meant for skipping any specified date
|
17
|
+
|
18
|
+
### v1.2.2
|
19
|
+
- Improved login screen wait and logging
|
20
|
+
- Applied fix for offenses about empty lines and long lines reported by Rubocop
|
21
|
+
|
22
|
+
### v1.2.3
|
23
|
+
- Improved validation logic to skip running due to weekend or intentional skips
|
24
|
+
- Refactored engine by reducing methods length based on reports by Rubocop
|
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
# Kobot
|
1
|
+
# Kobot [![Gem Version](https://badge.fury.io/rb/kobot.svg)](https://badge.fury.io/rb/kobot)
|
2
2
|
|
3
3
|
Kobot is a simple tool to automate the clock in or clock out operation on the web service
|
4
|
-
provided by [KING OF TIME](kingtime.jp) by leveraging [Selenium WebDriver](
|
5
|
-
and with Google Gmail service email
|
4
|
+
provided by [KING OF TIME](https://www.kingtime.jp/) by leveraging [Selenium WebDriver](
|
5
|
+
https://www.selenium.dev/), and with Google Gmail service email notifications can also be
|
6
|
+
sent to notify the results.
|
6
7
|
|
7
8
|
It is meant for use only by one working under the discretionary labor system or flexible
|
8
9
|
hours where the daily record is still required regardless of the actual start or end time
|
@@ -21,10 +22,11 @@ Tested on macOS Catelina and runs on Heroku platform so it works on unix-like sy
|
|
21
22
|
#### Configuration
|
22
23
|
|
23
24
|
By default it uses `~/.kobot` file locally to persist credentials for reuse, but all credentials
|
24
|
-
can be overridden by
|
25
|
-
|
26
|
-
|
27
|
-
so there is no need to manually prepare the file beforehand
|
25
|
+
can also be supplied or overridden by runtime environment variables, which is the recommended way
|
26
|
+
of running as scheduled jobs on platforms like Heroku. When running for the first time, if neither
|
27
|
+
the configuration file nor ENV satisfies all required credentials, `an interactive prompt will be
|
28
|
+
displayed for initial setting, so there is no need to manually prepare the file beforehand`. The
|
29
|
+
content looks something like:
|
28
30
|
```property
|
29
31
|
kot_id=xxx
|
30
32
|
kot_password=xxx
|
@@ -34,6 +36,7 @@ Gmail account and password (or `app` password if MFA is on) are asked when notif
|
|
34
36
|
gmail_id=xxx
|
35
37
|
gmail_password=xxx
|
36
38
|
```
|
39
|
+
Note: use all upper-case letters for the above variables if using environment variables, e.g. `KOT_ID`.
|
37
40
|
|
38
41
|
#### Google Chrome browser
|
39
42
|
|
@@ -51,17 +54,20 @@ $ gem install kobot
|
|
51
54
|
## Usage
|
52
55
|
|
53
56
|
Get help doc:
|
54
|
-
```
|
57
|
+
```
|
55
58
|
$ kobot -h
|
56
59
|
Usage: kobot [options]
|
57
|
-
-c, --clock CLOCK
|
58
|
-
-l, --loglevel [LEVEL] Specify log level: debug, info, warn, error
|
60
|
+
-c, --clock CLOCK Required; the clock action option: in, out
|
61
|
+
-l, --loglevel [LEVEL] Specify log level: debug, info, warn, error; default is info
|
59
62
|
-s, --skip [D1,D2,D3] Specify dates to skip clock in/out with date format YYYY-MM-DD and
|
60
|
-
multiple values separated by comma, such as: 2020-05-01,2020-12-31
|
61
|
-
|
63
|
+
multiple values separated by comma, such as: 2020-05-01,2020-12-31;
|
64
|
+
weekends and public holidays in Japan will be skipped by default
|
65
|
+
-t, --to [TO] Email address to send notification to; by default it is sent to
|
62
66
|
the same self email account used in SMTP config as the sender
|
63
67
|
-n, --notify Enable email notification
|
64
68
|
-d, --dryrun Run the process without actual clock in/out
|
69
|
+
-f, --force Run the process forcibly regardless of weekends or public holidays;
|
70
|
+
must be used together with --dryrun to prevent mistaken operations
|
65
71
|
-x, --headless Start browser in headless mode
|
66
72
|
-g, --geolocation Allow browser to use geolocation
|
67
73
|
-h, --help Show this help message
|
@@ -69,20 +75,25 @@ Usage: kobot [options]
|
|
69
75
|
```
|
70
76
|
|
71
77
|
Dryrun to try out:
|
72
|
-
```
|
73
|
-
$ kobot --clock in --dryrun
|
78
|
+
```
|
79
|
+
$ kobot --clock in --notify --dryrun
|
74
80
|
```
|
75
81
|
|
76
82
|
Clock in/out with email notification
|
77
|
-
```
|
78
|
-
$ kobot --clock in --notify
|
79
|
-
$ kobot --clock out --notify
|
83
|
+
```
|
84
|
+
$ kobot --clock in --notify --headless
|
85
|
+
$ kobot --clock out --notify --headless
|
80
86
|
```
|
81
87
|
|
82
88
|
Run the task with crontab
|
83
89
|
```cron
|
84
|
-
|
85
|
-
30
|
90
|
+
# Weekend and public holidays will be skipped by default
|
91
|
+
30 09 * * * user kobot --cin -n -x
|
92
|
+
30 18 * * * user kobot --cout -n -x
|
93
|
+
|
94
|
+
# Skip for weekdays planned to take leave for example
|
95
|
+
30 09 * * * user kobot --cin -n -x -s 2020-09-01,2020-11-11
|
96
|
+
30 18 * * * user kobot --cout -n -x -s 2020-09-01,2020-11-11
|
86
97
|
```
|
87
98
|
On platforms like Heroku, an add-on called [Heroku Scheduler](https://elements.heroku.com/addons/scheduler) makes
|
88
99
|
running scheduled tasks much easier. Tips: either clock in or clock out task can be scheduled multiple times in
|
data/bin/console
CHANGED
data/exe/kobot
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
4
|
+
begin
|
5
|
+
# For quickly tryout in local development
|
6
|
+
# without installing to system gems path
|
7
|
+
raise LoadError if ENV['KOBOT_DEV']
|
8
|
+
|
9
|
+
require 'kobot'
|
10
|
+
rescue LoadError
|
11
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
|
12
|
+
require 'kobot'
|
13
|
+
end
|
5
14
|
|
6
15
|
Kobot.run
|
data/kobot.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
|
|
17
17
|
|
18
18
|
spec.homepage = 'https://github.com/yuan-jiang/kobot'
|
19
19
|
spec.license = 'MIT'
|
20
|
-
spec.required_ruby_version = Gem::Requirement.new('>= 2.
|
20
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.4.0')
|
21
21
|
|
22
22
|
spec.metadata['allowed_push_host'] = 'https://rubygems.org/'
|
23
23
|
spec.metadata['homepage_uri'] = spec.homepage
|
data/lib/kobot.rb
CHANGED
@@ -14,8 +14,6 @@ require 'kobot/engine'
|
|
14
14
|
# and with Google Gmail service email notification can also be sent to notify the results.
|
15
15
|
module Kobot
|
16
16
|
class << self
|
17
|
-
|
18
|
-
# The entrance to run Kobot.
|
19
17
|
def run
|
20
18
|
configure
|
21
19
|
Engine.new.start
|
@@ -33,6 +31,7 @@ module Kobot
|
|
33
31
|
config.clock = options[:clock].to_sym
|
34
32
|
config.loglevel = options[:loglevel]&.to_sym || :info
|
35
33
|
config.dryrun = options[:dryrun]
|
34
|
+
config.force = options[:force]
|
36
35
|
config.skip = options[:skip] || []
|
37
36
|
|
38
37
|
config.kot_url = 'https://s2.kingtime.jp/independent/recorder/personal/'
|
data/lib/kobot/config.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Kobot
|
4
|
-
|
5
4
|
# Configuration definition includes static ones hardcoded and
|
6
5
|
# dynamic ones that can be specified by command line options.
|
7
6
|
class Config
|
@@ -9,7 +8,8 @@ module Kobot
|
|
9
8
|
attr_accessor :clock,
|
10
9
|
:loglevel,
|
11
10
|
:skip,
|
12
|
-
:dryrun
|
11
|
+
:dryrun,
|
12
|
+
:force
|
13
13
|
|
14
14
|
attr_accessor :kot_url,
|
15
15
|
:kot_timezone_offset,
|
data/lib/kobot/credential.rb
CHANGED
@@ -4,7 +4,6 @@ module Kobot
|
|
4
4
|
# Credentials include id and password to login to KOT and
|
5
5
|
# Gmail SMTP id and password to send email notifications.
|
6
6
|
class Credential
|
7
|
-
|
8
7
|
class << self
|
9
8
|
attr_accessor :kot_id,
|
10
9
|
:kot_password,
|
@@ -30,7 +29,7 @@ module Kobot
|
|
30
29
|
@credentials.each do |attr, value|
|
31
30
|
send("#{attr}=".to_sym, value)
|
32
31
|
end
|
33
|
-
Kobot.logger.info('
|
32
|
+
Kobot.logger.info('Load credentials successful')
|
34
33
|
Kobot.logger.debug(@credentials)
|
35
34
|
end
|
36
35
|
|
@@ -41,18 +40,18 @@ module Kobot
|
|
41
40
|
if File.exist? Config.credentials_file
|
42
41
|
File.open(Config.credentials_file) do |file|
|
43
42
|
file.each do |line|
|
44
|
-
attr, value = line.
|
43
|
+
attr, value = line.strip.split('=')
|
45
44
|
@credentials[attr] = value
|
46
45
|
end
|
47
46
|
end
|
48
47
|
end
|
49
|
-
@credentials['kot_id'] = ENV['kot_id'] if ENV['kot_id']
|
50
|
-
@credentials['kot_password'] = ENV['kot_password'] if ENV['kot_password']
|
51
|
-
@credentials['gmail_id'] = ENV['gmail_id'] if ENV['gmail_id']
|
52
|
-
@credentials['gmail_password'] = ENV['gmail_password'] if ENV['gmail_password']
|
53
|
-
|
54
48
|
required_credentials = %w[kot_id kot_password]
|
55
49
|
required_credentials.concat %w[gmail_id gmail_password] if Config.gmail_notify_enabled
|
50
|
+
required_credentials.each do |attr|
|
51
|
+
Kobot.logger.deprecate(attr, attr.upcase) if ENV[attr]
|
52
|
+
env_attr_value = ENV[attr.upcase] || ENV[attr]
|
53
|
+
@credentials[attr] = env_attr_value if env_attr_value
|
54
|
+
end
|
56
55
|
required_credentials.none? do |attr|
|
57
56
|
credential = @credentials[attr]
|
58
57
|
!credential || credential.strip.empty?
|
data/lib/kobot/engine.rb
CHANGED
@@ -6,7 +6,6 @@ module Kobot
|
|
6
6
|
# The core class that launches browser, logins to KOT, reads today
|
7
7
|
# record, and conducts clock in or clock out action based on config.
|
8
8
|
class Engine
|
9
|
-
|
10
9
|
def initialize
|
11
10
|
@now = Time.now.getlocal(Config.kot_timezone_offset)
|
12
11
|
@today = @now.strftime(Config.kot_date_format)
|
@@ -25,28 +24,19 @@ module Kobot
|
|
25
24
|
# System errors or any unknown exceptions occurred if any are
|
26
25
|
# to be popped up and should be handled by the outside caller.
|
27
26
|
def start
|
28
|
-
|
29
|
-
Kobot.logger.info("Today=#{@today} is weekend.")
|
30
|
-
return
|
31
|
-
end
|
32
|
-
if holiday?
|
33
|
-
Kobot.logger.info("Today=#{@today} is holiday.")
|
34
|
-
return
|
35
|
-
end
|
36
|
-
unless %i[in out].include? Config.clock
|
37
|
-
Kobot.logger.warn("Invalid clock operation: #{Config.clock}")
|
38
|
-
return
|
39
|
-
end
|
27
|
+
validate_today!
|
40
28
|
launch_browser
|
41
29
|
login
|
42
30
|
read_today_record
|
43
|
-
|
31
|
+
validate_today_record!
|
44
32
|
if Config.clock == :in
|
45
33
|
clock_in!
|
46
34
|
else
|
47
35
|
clock_out!
|
48
36
|
end
|
49
37
|
logout
|
38
|
+
rescue KotSkip => e
|
39
|
+
Kobot.logger.warn(e.message)
|
50
40
|
rescue KotRecordError => e
|
51
41
|
Kobot.logger.warn(e.message)
|
52
42
|
Mailer.send(clock_notify_message(status: e.message))
|
@@ -65,11 +55,20 @@ module Kobot
|
|
65
55
|
Mailer.send(clock_notify_message(status: e.message))
|
66
56
|
logout
|
67
57
|
ensure
|
68
|
-
|
58
|
+
close_browser
|
69
59
|
end
|
70
60
|
|
71
61
|
private
|
72
62
|
|
63
|
+
def validate_today!
|
64
|
+
raise KotSkip, "Today=#{@today} is skipped as per: --skip=#{Config.skip}" if skip?
|
65
|
+
|
66
|
+
return unless weekend?
|
67
|
+
raise KotSkip, "Today=#{@today} is weekend" unless Config.force
|
68
|
+
|
69
|
+
Kobot.logger.info("[Force] should have exited: today=#{@today} is weekend")
|
70
|
+
end
|
71
|
+
|
73
72
|
def launch_browser
|
74
73
|
prefs = {
|
75
74
|
profile: {
|
@@ -85,9 +84,18 @@ module Kobot
|
|
85
84
|
Kobot.logger.info('Launch browser successful')
|
86
85
|
end
|
87
86
|
|
87
|
+
def close_browser
|
88
|
+
return unless @browser
|
89
|
+
|
90
|
+
Kobot.logger.info('Close browser')
|
91
|
+
@browser.quit
|
92
|
+
end
|
93
|
+
|
88
94
|
def login
|
89
|
-
@browser.get @top_url
|
90
95
|
Kobot.logger.info("Navigate to: #{@top_url}")
|
96
|
+
@browser.get @top_url
|
97
|
+
@wait.until { @browser.find_element(id: 'modal_window') }
|
98
|
+
Kobot.logger.info "Page title: #{@browser.title}"
|
91
99
|
Kobot.logger.debug do
|
92
100
|
"Login with id=#{Credential.kot_id} and password=#{Credential.kot_password}"
|
93
101
|
end
|
@@ -104,13 +112,15 @@ module Kobot
|
|
104
112
|
Kobot.logger.warn "Get geolocation failed: #{e.message}"
|
105
113
|
end
|
106
114
|
end
|
107
|
-
Kobot.logger.info @browser.title
|
115
|
+
Kobot.logger.info "Page title: #{@browser.title}"
|
108
116
|
end
|
109
117
|
|
110
118
|
def logout
|
111
119
|
if @browser.current_url.include? 'admin'
|
120
|
+
Kobot.logger.info('Logout from タイムカード page')
|
112
121
|
@browser.find_element(css: 'div.htBlock-header_logoutButton').click
|
113
122
|
else
|
123
|
+
Kobot.logger.info('Logout from Myレコーダー page')
|
114
124
|
@wait.until { @browser.find_element(id: 'menu_icon') }.click
|
115
125
|
@wait.until { @browser.find_element(link: 'ログアウト') }.click
|
116
126
|
@browser.switch_to.alert.accept
|
@@ -119,6 +129,7 @@ module Kobot
|
|
119
129
|
end
|
120
130
|
|
121
131
|
def read_today_record
|
132
|
+
Kobot.logger.info('Navigate to タイムカード page')
|
122
133
|
@wait.until { @browser.find_element(id: 'menu_icon') }.click
|
123
134
|
@wait.until { @browser.find_element(link: 'タイムカード') }.click
|
124
135
|
|
@@ -131,8 +142,12 @@ module Kobot
|
|
131
142
|
@kot_today = date_cell.text
|
132
143
|
@kot_today_css_class = date_cell.attribute('class')
|
133
144
|
@kot_today_type = tr.find_element(css: 'td.work_day_type').text
|
134
|
-
@kot_today_clock_in = tr.find_element(
|
135
|
-
|
145
|
+
@kot_today_clock_in = tr.find_element(
|
146
|
+
css: 'td.start_end_timerecord[data-ht-sort-index="START_TIMERECORD"]'
|
147
|
+
).text
|
148
|
+
@kot_today_clock_out = tr.find_element(
|
149
|
+
css: 'td.start_end_timerecord[data-ht-sort-index="END_TIMERECORD"]'
|
150
|
+
).text
|
136
151
|
Kobot.logger.debug do
|
137
152
|
{
|
138
153
|
kot_toay: @kot_today,
|
@@ -146,10 +161,23 @@ module Kobot
|
|
146
161
|
end
|
147
162
|
end
|
148
163
|
|
149
|
-
def
|
150
|
-
raise KotRecordError, "Today=#{@today} is not found on kot
|
151
|
-
|
152
|
-
|
164
|
+
def validate_today_record!
|
165
|
+
raise KotRecordError, "Today=#{@today} is not found on kot" if @kot_today.strip.empty?
|
166
|
+
|
167
|
+
if kot_weekend?
|
168
|
+
raise KotRecordError, "Today=#{@today} is marked as weekend on kot: #{@kot_today}" unless Config.force
|
169
|
+
|
170
|
+
Kobot.logger.info(
|
171
|
+
"[Force] should have exited: today=#{@today} is marked as weekend on kot: #{@kot_today}"
|
172
|
+
)
|
173
|
+
end
|
174
|
+
|
175
|
+
return unless kot_public_holiday?
|
176
|
+
raise KotRecordError, "Today=#{@today} is marked as public holiday on kot: #{@kot_today}" unless Config.force
|
177
|
+
|
178
|
+
Kobot.logger.info(
|
179
|
+
"[Force] should have exited: today=#{@today} is marked as public holiday on kot: #{@kot_today}"
|
180
|
+
)
|
153
181
|
end
|
154
182
|
|
155
183
|
def clock_in!
|
@@ -192,21 +220,25 @@ module Kobot
|
|
192
220
|
end
|
193
221
|
|
194
222
|
def click_clock_in_button
|
223
|
+
Kobot.logger.info("Navigate to: #{@top_url}")
|
195
224
|
@browser.get @top_url
|
196
225
|
clock_in_button = @wait.until { @browser.find_element(css: 'div.record-clock-in') }
|
197
226
|
if Config.dryrun
|
198
227
|
Kobot.logger.info('[Dryrun] clock in button (出勤) would have been clicked')
|
199
228
|
else
|
229
|
+
Kobot.logger.info('Clicking the clock in button (出勤)')
|
200
230
|
clock_in_button.click
|
201
231
|
end
|
202
232
|
end
|
203
233
|
|
204
234
|
def click_clock_out_button
|
235
|
+
Kobot.logger.info("Navigate to: #{@top_url}")
|
205
236
|
@browser.get @top_url
|
206
237
|
clock_out_button = @wait.until { @browser.find_element(css: 'div.record-clock-out') }
|
207
238
|
if Config.dryrun
|
208
239
|
Kobot.logger.info('[Dryrun] clock out button (退勤) would have been clicked')
|
209
240
|
else
|
241
|
+
Kobot.logger.info('Clicking the clock in button (退勤)')
|
210
242
|
clock_out_button.click
|
211
243
|
end
|
212
244
|
end
|
@@ -215,7 +247,7 @@ module Kobot
|
|
215
247
|
@now.saturday? || @now.sunday?
|
216
248
|
end
|
217
249
|
|
218
|
-
def
|
250
|
+
def skip?
|
219
251
|
return false unless Config.skip
|
220
252
|
return false unless Config.skip.respond_to? :include?
|
221
253
|
|
data/lib/kobot/exception.rb
CHANGED
data/lib/kobot/mailer.rb
CHANGED
@@ -3,11 +3,9 @@
|
|
3
3
|
require 'net/smtp'
|
4
4
|
|
5
5
|
module Kobot
|
6
|
-
|
7
6
|
# Responsible for sending email notifications in SMTP with Gmail
|
8
7
|
class Mailer
|
9
8
|
class << self
|
10
|
-
|
11
9
|
# Sends email in preconfigured Gmail SMTP credential and to the recipient
|
12
10
|
# configured by #{Config.gmail_notify_to} or self if not configured, with
|
13
11
|
# email subject set by #{Config.gmail_notify_subject}.
|
data/lib/kobot/option.rb
CHANGED
@@ -3,33 +3,32 @@
|
|
3
3
|
require 'optparse'
|
4
4
|
|
5
5
|
module Kobot
|
6
|
-
|
7
6
|
# Responsible for parsing the command line options for custom execution.
|
8
7
|
class Option
|
9
8
|
class << self
|
10
|
-
|
11
9
|
# Parses command line options and returns a hash containing the options.
|
12
10
|
def parse!
|
13
11
|
options = {}
|
14
12
|
opt_parser = OptionParser.new do |opt|
|
15
13
|
opt.banner = "Usage: #{$PROGRAM_NAME} [options]"
|
16
14
|
|
17
|
-
opt.on('-c', '--clock CLOCK', '
|
15
|
+
opt.on('-c', '--clock CLOCK', 'Required; the clock action option: in, out') do |clock|
|
18
16
|
options[:clock] = clock
|
19
17
|
end
|
20
18
|
|
21
|
-
opt.on('-l', '--loglevel [LEVEL]', 'Specify log level: debug, info, warn, error
|
19
|
+
opt.on('-l', '--loglevel [LEVEL]', 'Specify log level: debug, info, warn, error; default is info') do |level|
|
22
20
|
options[:loglevel] = level
|
23
21
|
end
|
24
22
|
|
25
23
|
opt.on('-s', '--skip [D1,D2,D3]', Array,
|
26
24
|
'Specify dates to skip clock in/out with date format YYYY-MM-DD and',
|
27
|
-
'multiple values separated by comma, such as: 2020-05-01,2020-12-31'
|
25
|
+
'multiple values separated by comma, such as: 2020-05-01,2020-12-31;',
|
26
|
+
'weekends and public holidays in Japan will be skipped by default') do |skip|
|
28
27
|
options[:skip] = skip
|
29
28
|
end
|
30
29
|
|
31
30
|
opt.on('-t', '--to [TO]',
|
32
|
-
'Email address to send notification to
|
31
|
+
'Email address to send notification to; by default it is sent to',
|
33
32
|
'the same self email account used in SMTP config as the sender') do |to|
|
34
33
|
options[:to] = to
|
35
34
|
end
|
@@ -42,6 +41,12 @@ module Kobot
|
|
42
41
|
options[:dryrun] = dryrun
|
43
42
|
end
|
44
43
|
|
44
|
+
opt.on('-f', '--force',
|
45
|
+
'Run the process forcibly regardless of weekends or public holidays;',
|
46
|
+
'must be used together with --dryrun to prevent mistaken operations') do |force|
|
47
|
+
options[:force] = force
|
48
|
+
end
|
49
|
+
|
45
50
|
opt.on('-x', '--headless', 'Start browser in headless mode') do |headless|
|
46
51
|
options[:headless] = headless
|
47
52
|
end
|
@@ -62,7 +67,12 @@ module Kobot
|
|
62
67
|
end
|
63
68
|
opt_parser.parse! ARGV
|
64
69
|
raise OptionParser::MissingArgument, 'The clock option is required' if options[:clock].nil?
|
65
|
-
|
70
|
+
unless %w[in out].include? options[:clock]
|
71
|
+
raise OptionParser::InvalidArgument, 'The clock option must be either: in, out'
|
72
|
+
end
|
73
|
+
if options[:force] && !options[:dryrun]
|
74
|
+
raise OptionParser::InvalidArgument, 'Must specify --dryrun for forcibly running'
|
75
|
+
end
|
66
76
|
|
67
77
|
options
|
68
78
|
rescue OptionParser::MissingArgument, OptionParser::InvalidArgument => e
|
data/lib/kobot/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kobot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Jiang
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: webdrivers
|
@@ -100,7 +100,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 2.
|
103
|
+
version: 2.4.0
|
104
104
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
105
|
requirements:
|
106
106
|
- - ">="
|