kobot 1.0.0 → 1.2.3

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: 5a9d8a789566c49cffabd4006d13502a6222a211d9193cdf58f0523c6dd89937
4
- data.tar.gz: 993fed11502b5149ece85da3d46d69f74169cf75c479221e56becf6b195d6d97
3
+ metadata.gz: 3eba14b1e3b076a368dd700c2ac46a9db4fd13bf57a58e29797de7db7eb16fc3
4
+ data.tar.gz: 1926333cefbaf4272ae117cc7afb12284ed85d6ff41aa96a02094904599b5312
5
5
  SHA512:
6
- metadata.gz: 3fe31ae275852246a0ba1656f829352ef204278d55f4578bc160d1917b8c07a8586b621eee42ed80e1c7535c0650de0cd8a7edcbb5b7da9f7359f2fa42a8a435
7
- data.tar.gz: e904e08fe88b5c616e5c7287e77a6de4d0e7b85dba1306e4c5dd8ab9ff24938437cd69dcfed4e2da0c6904ddbfb561a96a4aea92f0d61a268b2460591d950efe
6
+ metadata.gz: '08ad9cb2d55c2931a34ed4243884a7e16c189d1d914e5aa935cfd4d32fc3d3d7567cdaecdb53de54e980e84ec4c6e696761b7f9b15fb65e3a0eef11f829370e5'
7
+ data.tar.gz: f8662e41fe53d35df04b1b530f946621330124684d6bd955e6b18e53830efaef74c22db66818a8a3958aa8a4745b4d37090419f538962c3a4876e8dbb9b6c1d7
@@ -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](selenium.dev),
5
- and with Google Gmail service email notification can also be sent to notify the results.
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 setting environment variables, which is the recommended way of running the
25
- job on platforms like Heroku. When running for the first time, if none of the configuration file
26
- and ENV satisfies all required credentials, an interactive prompt will be displayed for setting,
27
- so there is no need to manually prepare the file beforehand. The content looks something like:
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
- ```bash
57
+ ```
55
58
  $ kobot -h
56
59
  Usage: kobot [options]
57
- -c, --clock CLOCK The clock action: in, out
58
- -l, --loglevel [LEVEL] Specify log level: debug, info, warn, error. Default is info
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
- -t, --to [TO] Email address to send notification to. By default it is sent to
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
- ```bash
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
- ```bash
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
- 30 09 * * * user kobot --clock in --notify
85
- 30 18 * * * user kobot --clock out --notify
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
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bundler/setup'
4
5
  require 'kobot'
data/exe/kobot CHANGED
@@ -1,6 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'kobot'
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
@@ -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.3.0')
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
@@ -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/'
@@ -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,
@@ -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('Credentials load successful')
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.chomp.split('=')
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?
@@ -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
- if weekend?
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
- verify_today_record!
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
- @browser&.quit
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(css: 'td.start_end_timerecord[data-ht-sort-index="START_TIMERECORD"]').text
135
- @kot_today_clock_out = tr.find_element(css: 'td.start_end_timerecord[data-ht-sort-index="END_TIMERECORD"]').text
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 verify_today_record!
150
- raise KotRecordError, "Today=#{@today} is not found on kot." if @kot_today.strip.empty?
151
- raise KotRecordError, "Today=#{@today} is marked as weekend on kot: #{@kot_today}" if kot_weekend?
152
- raise KotRecordError, "Today=#{@today} is marked as public holiday on kot: #{@kot_today}" if kot_public_holiday?
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 holiday?
250
+ def skip?
219
251
  return false unless Config.skip
220
252
  return false unless Config.skip.respond_to? :include?
221
253
 
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kobot
4
+ class KotSkip < StandardError
5
+ end
4
6
 
5
7
  class KotRecordError < StandardError
6
8
  end
@@ -10,5 +12,4 @@ module Kobot
10
12
 
11
13
  class KotClockOutError < StandardError
12
14
  end
13
-
14
15
  end
@@ -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}.
@@ -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', 'The clock action: in, out') do |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. Default is info') do |level|
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') do |skip|
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. By default it is sent 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
- raise OptionParser::InvalidArgument, 'The clock option must be either: in, out' unless %w[in out].include? options[:clock]
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kobot
4
- VERSION = '1.0.0'
4
+ VERSION = '1.2.3'
5
5
  end
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.0.0
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-08-10 00:00:00.000000000 Z
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.3.0
103
+ version: 2.4.0
104
104
  required_rubygems_version: !ruby/object:Gem::Requirement
105
105
  requirements:
106
106
  - - ">="