kobot 1.2.4 → 2.1.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: 0e8cedf9053f994144d21b233b2c68fb4e03aff011192f1273e1ad24d347c4f9
4
- data.tar.gz: 8daab86f87c5ffe5e0588c9029ccd062954ca7ad3557769861ef19fd07347c79
3
+ metadata.gz: e51c45d51bed6c3e614f58f41e557a9da9ab4dd6d457419bf1f2d654bc0e8e6d
4
+ data.tar.gz: 6cf858d531f3ef1b990751a8c821fd13965f04b234191a324598c9eefc68ac6c
5
5
  SHA512:
6
- metadata.gz: 4aaaa2f0e8eebe98487536158b0f571e794b76db95dec5cd2eb268037dfd0888045d6cebbeb46876162ed9944813f7429e8a4466da20ca9010ecacfd552cd302
7
- data.tar.gz: 9ede3410f3ad664982db308f382140eb19bc8140970fc4991f68829a0c63fe664a6978b99ef5753036954a0bbabb9731b3f7e5fe08aff11c589798898ce0ec59
6
+ metadata.gz: 4f00479950ad49f878f85fc515e5cb337a0fe3b047fa49a8b94dd5bcf2b776008f24d168c122c6f651445a1a883084c56296d9a4b034e9693f66b6336422351a
7
+ data.tar.gz: c6dc7304b15f26a6ae39dcfd9e644c82081b22519d2b28469f6671e570c73c70baf91be0e30eb4950833330b1a39cf200d3c9722d819c57377ab678f9efa2e6c
data/CHANGELOG.md CHANGED
@@ -1,27 +1,42 @@
1
- ### v1.0.0
2
- - Initial release
1
+ ### v2.1.0
2
+ - Changed i18n identification strategy due to that KOT displays in Japanese even though the login screen is in English
3
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
4
+ ### v2.0.0
5
+ - Added -a, --auto-skip flag to support the enabling and disabling of auto-skipping feature
6
+ - Renamed the schedule config option from -a, --auto-skip-without to -w, --auto-skip-without
8
7
 
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
8
+ ### v1.3.0
9
+ - Added config option (-a, --auto-skip-without) to enable automatic skipping based on schedule
10
+ - Replaced deprecated options with capabilities option in Selenium driver initialization
11
+ - Refactored scattered attr_accessors and reduced instance variables count reported by Rubocop
12
+
13
+ ### v1.2.5
14
+ - Added I18n support for both English and Japanese KOT UI
15
+
16
+ ### v1.2.4
17
+ - Changed to use boolean values for validation instead of raising exceptions
18
+
19
+ ### v1.2.3
20
+ - Improved validation logic to skip running due to weekend or intentional skips
21
+ - Refactored engine by reducing methods length based on reports by Rubocop
22
+
23
+ ### v1.2.2
24
+ - Improved login screen wait and logging
25
+ - Applied fix for offenses about empty lines and long lines reported by Rubocop
12
26
 
13
27
  ### v1.2.1
14
28
  - Improved logging for better readability in logs
15
29
  - Switched to builtin Logger#deprecate from Logger#warn for deprecations
16
30
  - Renamed internal method to skip? from holiday? as it was meant for skipping any specified date
17
31
 
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
32
+ ### v1.2.0
33
+ - Added an option to allow forcibly running regardless of weekends or public holidays
34
+ - Added an ENV flag to allow requiring lib in local workspace for development purpose
21
35
 
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
36
+ ### v1.1.0
37
+ - Deprecated lower-case environment variables for credentials configuration
38
+ - Updated option help doc to indicate weekends and public holidays are skipped by default
39
+ - Updated required_ruby_version to be >= 2.4.0 to align with the webdrivers dependency
25
40
 
26
- ### v1.2.4
27
- - Changed to use boolean values for validation instead of raising exceptions
41
+ ### v1.0.0
42
+ - Initial release
data/README.md CHANGED
@@ -62,6 +62,10 @@ Usage: kobot [options]
62
62
  -s, --skip [D1,D2,D3] Specify dates to skip clock in/out with date format YYYY-MM-DD and
63
63
  multiple values separated by comma, such as: 2020-05-01,2020-12-31;
64
64
  weekends and public holidays in Japan will be skipped by default
65
+ -a, --auto-skip Enable auto-skipping by reading schedule from the Time Card page
66
+ -w [SCHEDULE], Skip today if the provided text is not contained in the schedule
67
+ --auto-skip-without column on the Time Card page of KOT; by default 裁量労働 is used;
68
+ effective only if --auto-skip is passed to enable auto-skipping.
65
69
  -t, --to [TO] Email address to send notification to; by default it is sent to
66
70
  the same self email account used in SMTP config as the sender
67
71
  -n, --notify Enable email notification
data/lib/kobot/config.rb CHANGED
@@ -8,24 +8,22 @@ module Kobot
8
8
  attr_accessor :clock,
9
9
  :loglevel,
10
10
  :skip,
11
+ :auto_skip,
12
+ :auto_skip_without,
11
13
  :dryrun,
12
- :force
13
-
14
- attr_accessor :kot_url,
14
+ :force,
15
+ :kot_url,
15
16
  :kot_timezone_offset,
16
- :kot_date_format
17
-
18
- attr_accessor :gmail_notify_enabled,
17
+ :kot_date_format,
18
+ :gmail_notify_enabled,
19
19
  :gmail_notify_subject,
20
20
  :gmail_notify_to,
21
21
  :gmail_smtp_address,
22
- :gmail_smtp_port
23
-
24
- attr_accessor :browser_headless,
22
+ :gmail_smtp_port,
23
+ :browser_headless,
25
24
  :browser_geolocation,
26
- :browser_wait_timeout
27
-
28
- attr_accessor :credentials_file
25
+ :browser_wait_timeout,
26
+ :credentials_file
29
27
 
30
28
  def configure
31
29
  yield self
data/lib/kobot/engine.rb CHANGED
@@ -81,7 +81,10 @@ module Kobot
81
81
  }
82
82
  options = Selenium::WebDriver::Chrome::Options.new(prefs: prefs)
83
83
  options.headless! if Config.browser_headless
84
- @browser = Selenium::WebDriver.for(:chrome, options: options)
84
+ caps = [
85
+ options
86
+ ]
87
+ @browser = Selenium::WebDriver.for(:chrome, capabilities: caps)
85
88
  @wait = Selenium::WebDriver::Wait.new(timeout: Config.browser_wait_timeout)
86
89
  Kobot.logger.info('Launch browser successful')
87
90
  end
@@ -97,7 +100,7 @@ module Kobot
97
100
  Kobot.logger.info("Navigate to: #{@top_url}")
98
101
  @browser.get @top_url
99
102
  @wait.until { @browser.find_element(id: 'modal_window') }
100
- Kobot.logger.info "Page title: #{@browser.title}"
103
+ Kobot.logger.info "Page title (before login): #{@browser.title}"
101
104
  Kobot.logger.debug do
102
105
  "Login with id=#{Credential.kot_id} and password=#{Credential.kot_password}"
103
106
  end
@@ -106,57 +109,75 @@ module Kobot
106
109
  @browser.find_element(css: 'div.btn-control-message').click
107
110
 
108
111
  Kobot.logger.info 'Login successful'
109
- @wait.until { @browser.find_element(id: 'notification_content').text.include?('データを取得しました') }
112
+ clock_in_button = @wait.until { @browser.find_element(css: '.record-clock-in') }
113
+ @selector = if clock_in_button.text.include? '出勤'
114
+ Kobot.logger.info('Identify UI in Japanese')
115
+ Selector.ja
116
+ else
117
+ Kobot.logger.info('Identify UI in English')
118
+ Selector.en
119
+ end
120
+ begin
121
+ @wait.until do
122
+ @browser.find_element(id: 'notification_content').text.include?(@selector.login_success_notification_text)
123
+ end
124
+ rescue StandardError => e
125
+ Kobot.logger.warn "Failed to validate login success notification text: #{e.message}"
126
+ end
110
127
  if Config.browser_geolocation
111
128
  begin
112
- @wait.until { @browser.find_element(id: 'location_area').text.include?('位置情報取得済み') }
129
+ @wait.until do
130
+ @browser.find_element(id: 'location_area').text.include?(@selector.location_area_notification_text)
131
+ end
113
132
  rescue StandardError => e
114
133
  Kobot.logger.warn "Get geolocation failed: #{e.message}"
115
134
  end
116
135
  end
117
- Kobot.logger.info "Page title: #{@browser.title}"
136
+ Kobot.logger.info "Page title (after login): #{@browser.title}"
118
137
  end
119
138
 
120
139
  def logout
121
140
  if @browser.current_url.include? 'admin'
122
- Kobot.logger.info('Logout from タイムカード page')
141
+ Kobot.logger.info('Logout from Time Card (タイムカード) page')
123
142
  @browser.find_element(css: 'div.htBlock-header_logoutButton').click
124
143
  else
125
- Kobot.logger.info('Logout from Myレコーダー page')
144
+ Kobot.logger.info('Logout from My Recorder (Myレコーダー) page')
126
145
  @wait.until { @browser.find_element(id: 'menu_icon') }.click
127
- @wait.until { @browser.find_element(link: 'ログアウト') }.click
146
+ @wait.until { @browser.find_element(link: @selector.logout_menu_link_text) }.click
128
147
  @browser.switch_to.alert.accept
129
148
  end
130
149
  Kobot.logger.info 'Logout successful'
131
150
  end
132
151
 
133
152
  def read_today_record
134
- Kobot.logger.info('Navigate to タイムカード page')
153
+ Kobot.logger.info('Navigate to Time Card (タイムカード) page')
135
154
  @wait.until { @browser.find_element(id: 'menu_icon') }.click
136
- @wait.until { @browser.find_element(link: 'タイムカード') }.click
155
+ @wait.until { @browser.find_element(link: @selector.time_card_menu_link_text) }.click
137
156
 
138
157
  time_table = @wait.until { @browser.find_element(css: 'div.htBlock-adjastableTableF_inner > table') }
139
158
  time_table.find_elements(css: 'tbody > tr').each do |tr|
140
159
  date_cell = tr.find_element(css: 'td.htBlock-scrollTable_day')
141
160
  next unless date_cell.text.include? @today
142
161
 
143
- Kobot.logger.info('Reading today record')
144
- @kot_today = date_cell.text
145
- @kot_today_css_class = date_cell.attribute('class')
146
- @kot_today_type = tr.find_element(css: 'td.work_day_type').text
147
- @kot_today_clock_in = tr.find_element(
162
+ Kobot.logger.info('Read today record')
163
+ @kot_data = {}
164
+ @kot_data[:today] = date_cell.text
165
+ @kot_data[:today_css_class] = date_cell.attribute('class')
166
+ @kot_data[:today_type] = tr.find_element(css: 'td.work_day_type').text
167
+ @kot_data[:today_schedule] = tr.find_element(css: 'td.schedule').text
168
+ @kot_data[:today_clock_in] = tr.find_element(
148
169
  css: 'td.start_end_timerecord[data-ht-sort-index="START_TIMERECORD"]'
149
170
  ).text
150
- @kot_today_clock_out = tr.find_element(
171
+ @kot_data[:today_clock_out] = tr.find_element(
151
172
  css: 'td.start_end_timerecord[data-ht-sort-index="END_TIMERECORD"]'
152
173
  ).text
153
174
  Kobot.logger.debug do
154
175
  {
155
- kot_toay: @kot_today,
156
- kot_today_css_class: @kot_today_css_class,
157
- kot_today_type: @kot_today_type,
158
- kot_today_clock_in: @kot_today_clock_in,
159
- kot_today_clock_out: @kot_today_clock_out
176
+ kot_toay: @kot_data[:today],
177
+ kot_today_css_class: @kot_data[:today_css_class],
178
+ kot_today_type: @kot_data[:today_type],
179
+ kot_today_clock_in: @kot_data[:today_clock_in],
180
+ kot_today_clock_out: @kot_data[:today_clock_out]
160
181
  }
161
182
  end
162
183
  break
@@ -164,60 +185,71 @@ module Kobot
164
185
  end
165
186
 
166
187
  def validate_today_record!
167
- raise KotRecordError, "Today=#{@today} is not found on kot" if @kot_today.strip.empty?
188
+ raise KotRecordError, "Today=#{@today} is not found on kot" if @kot_data[:today].strip.empty?
168
189
 
169
190
  if kot_weekend?
170
- raise KotRecordError, "Today=#{@today} is marked as weekend on kot: #{@kot_today}" unless Config.force
191
+ raise KotRecordError, "Today=#{@today} is marked as weekend: #{@kot_data[:today]}" unless Config.force
192
+
193
+ Kobot.logger.info(
194
+ "[Force] should have exited: today=#{@today} is marked as weekend: #{@kot_data[:today]}"
195
+ )
196
+ end
197
+
198
+ if kot_public_holiday?
199
+ raise KotRecordError, "Today=#{@today} is marked as public holiday: #{@kot_data[:today]}" unless Config.force
171
200
 
172
201
  Kobot.logger.info(
173
- "[Force] should have exited: today=#{@today} is marked as weekend on kot: #{@kot_today}"
202
+ "[Force] should have exited: today=#{@today} is marked as public holiday: #{@kot_data[:today]}"
174
203
  )
175
204
  end
176
205
 
177
- return unless kot_public_holiday?
178
- raise KotRecordError, "Today=#{@today} is marked as public holiday on kot: #{@kot_today}" unless Config.force
206
+ return unless Config.auto_skip
207
+
208
+ if kot_non_work_schedule?
209
+ raise KotRecordError, "Today=#{@today} is non-work schedule: #{@kot_data[:today_schedule]}" unless Config.force
179
210
 
180
- Kobot.logger.info(
181
- "[Force] should have exited: today=#{@today} is marked as public holiday on kot: #{@kot_today}"
182
- )
211
+ Kobot.logger.info(
212
+ "[Force] should have exited: today=#{@today} is non-work schedule: #{@kot_data[:today_schedule]}"
213
+ )
214
+ end
183
215
  end
184
216
 
185
217
  def clock_in!
186
218
  Kobot.logger.warn("Clock in during the afternoon: #{@now}") if @now.hour > 12
187
- if @kot_today_clock_in.strip.empty?
219
+ if @kot_data[:today_clock_in].strip.empty?
188
220
  click_clock_in_button
189
221
  return if Config.dryrun
190
222
 
191
223
  read_today_record
192
- raise KotClockInError, 'Clock in operation seems to have failed' if @kot_today_clock_in.strip.empty?
224
+ raise KotClockInError, 'Clock in operation seems to have failed' if @kot_data[:today_clock_in].strip.empty?
193
225
 
194
- Kobot.logger.info("Clock in successful: #{@kot_today_clock_in}")
226
+ Kobot.logger.info("Clock in successful: #{@kot_data[:today_clock_in]}")
195
227
  Mailer.send(clock_notify_message(clock: :in))
196
228
  else
197
- Kobot.logger.warn("Clock in done already: #{@kot_today_clock_in}")
229
+ Kobot.logger.warn("Clock in done already: #{@kot_data[:today_clock_in]}")
198
230
  end
199
231
  end
200
232
 
201
233
  def clock_out!
202
234
  Kobot.logger.warn("Clock out during the morning: #{@now}") if @now.hour <= 12
203
235
  unless Config.dryrun
204
- if @kot_today_clock_in.strip.empty?
236
+ if @kot_data[:today_clock_in].strip.empty?
205
237
  raise KotClockOutError,
206
- "!!!No clock in record for today=#{@kot_today}!!!"
238
+ "!!!No clock in record for today=#{@kot_data[:today]}!!!"
207
239
  end
208
240
  end
209
241
 
210
- if @kot_today_clock_out.strip.empty?
242
+ if @kot_data[:today_clock_out].strip.empty?
211
243
  click_clock_out_button
212
244
  return if Config.dryrun
213
245
 
214
246
  read_today_record
215
- raise KotClockOutError, 'Clock out operation seems to have failed' if @kot_today_clock_out.strip.empty?
247
+ raise KotClockOutError, 'Clock out operation seems to have failed' if @kot_data[:today_clock_out].strip.empty?
216
248
 
217
- Kobot.logger.info("Clock out successful: #{@kot_today_clock_out}")
249
+ Kobot.logger.info("Clock out successful: #{@kot_data[:today_clock_out]}")
218
250
  Mailer.send(clock_notify_message(clock: :out))
219
251
  else
220
- Kobot.logger.warn("Clock out done already: #{@kot_today_clock_out}")
252
+ Kobot.logger.warn("Clock out done already: #{@kot_data[:today_clock_out]}")
221
253
  end
222
254
  end
223
255
 
@@ -226,9 +258,9 @@ module Kobot
226
258
  @browser.get @top_url
227
259
  clock_in_button = @wait.until { @browser.find_element(css: 'div.record-clock-in') }
228
260
  if Config.dryrun
229
- Kobot.logger.info('[Dryrun] clock in button (出勤) would have been clicked')
261
+ Kobot.logger.info('[Dryrun] Clock-in button (出勤) would have been clicked')
230
262
  else
231
- Kobot.logger.info('Clicking the clock in button (出勤)')
263
+ Kobot.logger.info('Clicking the Clock-in button (出勤)')
232
264
  clock_in_button.click
233
265
  end
234
266
  end
@@ -238,9 +270,9 @@ module Kobot
238
270
  @browser.get @top_url
239
271
  clock_out_button = @wait.until { @browser.find_element(css: 'div.record-clock-out') }
240
272
  if Config.dryrun
241
- Kobot.logger.info('[Dryrun] clock out button (退勤) would have been clicked')
273
+ Kobot.logger.info('[Dryrun] Clock-out button (退勤) would have been clicked')
242
274
  else
243
- Kobot.logger.info('Clicking the clock in button (退勤)')
275
+ Kobot.logger.info('Clicking the Clock-out button (退勤)')
244
276
  clock_out_button.click
245
277
  end
246
278
  end
@@ -257,18 +289,25 @@ module Kobot
257
289
  end
258
290
 
259
291
  def kot_weekend?
260
- %w[土 日].any? { |kanji| @kot_today&.include? kanji }
292
+ [
293
+ @selector.kot_date_saturday,
294
+ @selector.kot_date_sunday
295
+ ].any? { |weekend| @kot_data[:today]&.include? weekend }
296
+ end
297
+
298
+ def kot_non_work_schedule?
299
+ !@kot_data[:today_schedule]&.include?(Config.auto_skip_without)
261
300
  end
262
301
 
263
302
  def kot_public_holiday?
264
- return true if @kot_today_type&.include? '休日'
303
+ return true if @kot_data[:today_type]&.include? @selector.kot_workday_time_off_text
265
304
 
266
305
  kot_today_highlighted = %w[sunday saturday].any? do |css|
267
- @kot_today_css_class&.include? css
306
+ @kot_data[:today_css_class]&.include? css
268
307
  end
269
308
  if kot_today_highlighted
270
309
  Kobot.logger.warn(
271
- "Today=#{@kot_today} is highlighted (holiday) but not marked as 休日"
310
+ "Today=#{@kot_data[:today]} is highlighted (holiday) but not marked as #{@selector.kot_workday_time_off_text}"
272
311
  )
273
312
  end
274
313
  kot_today_highlighted
@@ -280,8 +319,8 @@ module Kobot
280
319
  "<b>Date:</b> #{@today}",
281
320
  "<b>Status:</b> <span style='color:#{color}'>#{status}</span>"
282
321
  ]
283
- message << "<b>Clock_in:</b> #{@kot_today_clock_in}" if clock
284
- message << "<b>Clock_out:</b> #{@kot_today_clock_out}" if clock == :out
322
+ message << "<b>Clock_in:</b> #{@kot_data[:today_clock_in]}" if clock
323
+ message << "<b>Clock_out:</b> #{@kot_data[:today_clock_out]}" if clock == :out
285
324
  message.join('<br>')
286
325
  end
287
326
  end
data/lib/kobot/mailer.rb CHANGED
@@ -47,7 +47,7 @@ module Kobot
47
47
  To: <#{to}>
48
48
  MIME-Version: 1.0
49
49
  Content-type: text/html
50
- Subject: #{subject}
50
+ Subject: #{subject}
51
51
  Date: #{Time.now.getlocal(Config.kot_timezone_offset)}
52
52
 
53
53
  #{body}
data/lib/kobot/option.rb CHANGED
@@ -27,6 +27,17 @@ module Kobot
27
27
  options[:skip] = skip
28
28
  end
29
29
 
30
+ opt.on('-a', '--auto-skip', 'Enable auto-skipping by reading schedule from the Time Card page') do |auto_skip|
31
+ options[:auto_skip] = auto_skip
32
+ end
33
+
34
+ opt.on('-w', '--auto-skip-without [SCHEDULE]',
35
+ 'Skip today if the provided text is not contained in the schedule',
36
+ 'column on the Time Card page of KOT; by default 裁量労働 is used;',
37
+ 'effective only if --auto-skip is passed to enable auto-skipping.') do |schedule|
38
+ options[:auto_skip_without] = schedule
39
+ end
40
+
30
41
  opt.on('-t', '--to [TO]',
31
42
  'Email address to send notification to; by default it is sent to',
32
43
  'the same self email account used in SMTP config as the sender') do |to|
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kobot
4
+ # The texts used in selectors to identify the elements on KOT UI.
5
+ class Selector
6
+ attr_accessor :login_success_notification_text,
7
+ :location_area_notification_text,
8
+ :time_card_menu_link_text,
9
+ :kot_date_saturday,
10
+ :kot_date_sunday,
11
+ :kot_workday_time_off_text,
12
+ :logout_menu_link_text
13
+
14
+ class << self
15
+ def en
16
+ selector = Selector.new
17
+ selector.login_success_notification_text = 'Data has been obtained'
18
+ selector.location_area_notification_text = 'Obtained location'
19
+ selector.time_card_menu_link_text = 'Time Card'
20
+ selector.kot_date_saturday = 'Sat'
21
+ selector.kot_date_sunday = 'Sun'
22
+ selector.kot_workday_time_off_text = 'time-off'
23
+ selector.logout_menu_link_text = 'Sign out'
24
+ selector
25
+ end
26
+
27
+ def ja
28
+ selector = Selector.new
29
+ selector.login_success_notification_text = 'データを取得しました'
30
+ selector.location_area_notification_text = '位置情報取得済み'
31
+ selector.time_card_menu_link_text = 'タイムカード'
32
+ selector.kot_date_saturday = '土'
33
+ selector.kot_date_sunday = '日'
34
+ selector.kot_workday_time_off_text = '休日'
35
+ selector.logout_menu_link_text = 'ログアウト'
36
+ selector
37
+ end
38
+ end
39
+ end
40
+ end
data/lib/kobot/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kobot
4
- VERSION = '1.2.4'
4
+ VERSION = '2.1.0'
5
5
  end
data/lib/kobot.rb CHANGED
@@ -4,6 +4,7 @@ require 'kobot/version'
4
4
  require 'kobot/exception'
5
5
  require 'kobot/option'
6
6
  require 'kobot/config'
7
+ require 'kobot/selector'
7
8
  require 'kobot/credential'
8
9
  require 'kobot/logger'
9
10
  require 'kobot/mailer'
@@ -33,6 +34,8 @@ module Kobot
33
34
  config.dryrun = options[:dryrun]
34
35
  config.force = options[:force]
35
36
  config.skip = options[:skip] || []
37
+ config.auto_skip = options[:auto_skip]
38
+ config.auto_skip_without = options[:auto_skip_without] || '裁量労働'
36
39
 
37
40
  config.kot_url = 'https://s2.kingtime.jp/independent/recorder/personal/'
38
41
  config.kot_timezone_offset = '+09:00'
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.2.4
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Jiang
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-18 00:00:00.000000000 Z
11
+ date: 2022-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: webdrivers
@@ -83,6 +83,7 @@ files:
83
83
  - lib/kobot/logger.rb
84
84
  - lib/kobot/mailer.rb
85
85
  - lib/kobot/option.rb
86
+ - lib/kobot/selector.rb
86
87
  - lib/kobot/version.rb
87
88
  homepage: https://github.com/yuan-jiang/kobot
88
89
  licenses:
@@ -92,7 +93,7 @@ metadata:
92
93
  homepage_uri: https://github.com/yuan-jiang/kobot
93
94
  source_code_uri: https://github.com/yuan-jiang/kobot
94
95
  changelog_uri: https://github.com/yuan-jiang/kobot/blob/master/CHANGELOG.md
95
- post_install_message:
96
+ post_install_message:
96
97
  rdoc_options: []
97
98
  require_paths:
98
99
  - lib
@@ -107,8 +108,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
108
  - !ruby/object:Gem::Version
108
109
  version: '0'
109
110
  requirements: []
110
- rubygems_version: 3.0.3
111
- signing_key:
111
+ rubygems_version: 3.2.32
112
+ signing_key:
112
113
  specification_version: 4
113
114
  summary: Kobot automates the clock in/out of KING OF TIME.
114
115
  test_files: []