shiftnote 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/shiftnote.rb +80 -0
- data/lib/shiftnote/days_of_week_shift.rb +27 -0
- data/lib/shiftnote/days_of_week_shifts.rb +25 -0
- data/lib/shiftnote/employee_overview_view_model.rb +47 -0
- data/lib/shiftnote/errors.rb +5 -0
- data/lib/shiftnote/schedule_this_week_view_model.rb +19 -0
- data/lib/shiftnote/shift_view_model.rb +60 -0
- metadata +96 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a2b6656f26dac7e804d5913fc203623998e548e8af5ef23defc3ee2447d02e2a
|
4
|
+
data.tar.gz: 3b3e588761717222c407be99ee76219d9cfa7ed18383a81145eae5fe34205d54
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e0f3b24ac76fd45f84f2a65817c2b4b57afb2d7d81d292f69231dba98fe27083bf2068e95212e6c5bf5e688147487551a30b90b5fcbe11f5d45f68bb8baa4b82
|
7
|
+
data.tar.gz: fc572be0e9db37eb992a7f7615332ecc29d12bcc284a3d4ecb330a9a0b751e136a6b198438e5973f688ce5267092e3eeafc846ec8a8ccc8aca42344047309ec2
|
data/lib/shiftnote.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Gems needed to do a good job
|
4
|
+
require 'rest-client'
|
5
|
+
require 'nokogiri'
|
6
|
+
require 'json'
|
7
|
+
require 'rails'
|
8
|
+
|
9
|
+
# All ShiftNote functionality, whether extended or just here.
|
10
|
+
class ShiftNote
|
11
|
+
# Initialize a new ShiftNote variable, via a cookie.
|
12
|
+
# @param cookie [String] Cookie of an authenticated user.
|
13
|
+
def initialize(credentials = {})
|
14
|
+
@credentials = credentials
|
15
|
+
generate_cookie(credentials[:username], credentials[:password])
|
16
|
+
end
|
17
|
+
|
18
|
+
def generate_cookie(username, password)
|
19
|
+
uri = URI.parse('https://ww1.shiftnote.com/login')
|
20
|
+
request = Net::HTTP::Post.new(uri)
|
21
|
+
request.content_type = 'application/x-www-form-urlencoded'
|
22
|
+
request.set_form_data(
|
23
|
+
'FullSite' => 'False',
|
24
|
+
'ReturnUrl' => '',
|
25
|
+
'username' => username,
|
26
|
+
'Password' => password,
|
27
|
+
'Submit' => 'Submit',
|
28
|
+
'remember' => 'true'
|
29
|
+
)
|
30
|
+
|
31
|
+
req_options = {
|
32
|
+
use_ssl: uri.scheme == 'https'
|
33
|
+
}
|
34
|
+
|
35
|
+
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
|
36
|
+
http.request(request)
|
37
|
+
end
|
38
|
+
# response.code
|
39
|
+
raise Errors::InvalidCredentials, 'The provided credentials are invalid, please try again.' if response.body.include?("There was no match for the username and password provided, please try again!")
|
40
|
+
|
41
|
+
@cookie = response.header['Set-Cookie']
|
42
|
+
end
|
43
|
+
|
44
|
+
# Initialize the Employee
|
45
|
+
# @return [ShiftNote::EmployeeOverviewViewModel] the employee
|
46
|
+
def employee
|
47
|
+
shiftnote = RestClient.get('https://ww1.shiftnote.com/BulletinBoard/', Cookie: @cookie)
|
48
|
+
|
49
|
+
doc = Nokogiri::HTML.parse(shiftnote.body)
|
50
|
+
|
51
|
+
begin
|
52
|
+
data = doc.search('div#MyScheduleDiv').at('script').text
|
53
|
+
rescue NoMethodError
|
54
|
+
generate_cookie(@credentials[:username], @credentials[:password])
|
55
|
+
retry
|
56
|
+
end
|
57
|
+
|
58
|
+
data = data.gsub('<script>', '').delete(';').gsub('</script>', '').gsub('window.scheduleMinebindings = ShiftNote.Bind(window.scheduleMinemodel)', '').gsub('window.scheduleMinemodel = ', '')
|
59
|
+
|
60
|
+
@employee = EmployeeOverviewViewModel.new(JSON.parse(data))
|
61
|
+
end
|
62
|
+
|
63
|
+
# @param weeks [Integer]
|
64
|
+
def get_all_upcoming_shifts(_weeks = 0)
|
65
|
+
employee if @employee = nil?
|
66
|
+
week2 = RestClient.get("https://ww1.shiftnote.com/Schedules/ScheduleMine/?startDate=#{nextmonday.month}%2F#{nextmonday.day}%2F#{nextmonday.year}&noContainer=true&_=1559999273196", Cookie: @cookie)
|
67
|
+
|
68
|
+
week2doc = Nokogiri::HTML.parse(week2.body)
|
69
|
+
dataweek2 = JSON.parse(scrapejunk(week2doc.at('script').text))
|
70
|
+
me2 = EmployeeOverviewViewModel.new(dataweek2)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Require files.
|
75
|
+
require_relative 'shiftnote/days_of_week_shift'
|
76
|
+
require_relative 'shiftnote/days_of_week_shifts'
|
77
|
+
require_relative 'shiftnote/employee_overview_view_model'
|
78
|
+
require_relative 'shiftnote/errors'
|
79
|
+
require_relative 'shiftnote/schedule_this_week_view_model'
|
80
|
+
require_relative 'shiftnote/shift_view_model'
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class ShiftNote::DaysOfWeekShift
|
2
|
+
def initialize(data)
|
3
|
+
@raw = data
|
4
|
+
@date = Time.parse(data['ShiftDate'])
|
5
|
+
@raw_shifts = data['Shifts']
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :date
|
9
|
+
|
10
|
+
def shifts
|
11
|
+
shifts = []
|
12
|
+
@raw_shifts.each do |e|
|
13
|
+
shifts.push ShiftNote::ShiftViewModel.new(e)
|
14
|
+
end
|
15
|
+
shifts
|
16
|
+
end
|
17
|
+
|
18
|
+
def amount_of_shifts
|
19
|
+
@raw_shifts.length
|
20
|
+
end
|
21
|
+
|
22
|
+
def first_shift
|
23
|
+
ShiftNote::ShiftViewModel.new(@raw_shifts.first)
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :raw
|
27
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class ShiftNote::DaysOfWeekShifts
|
2
|
+
def initialize(data)
|
3
|
+
@data = data
|
4
|
+
end
|
5
|
+
|
6
|
+
def days
|
7
|
+
dayz = []
|
8
|
+
@data.each do |e|
|
9
|
+
dayz.push ShiftNote::DaysOfWeekShift.new(e)
|
10
|
+
end
|
11
|
+
dayz
|
12
|
+
end
|
13
|
+
|
14
|
+
def working_days
|
15
|
+
dayz = []
|
16
|
+
@data.each do |e|
|
17
|
+
dayz.push ShiftNote::DaysOfWeekShift.new(e) unless e['Shifts'].empty?
|
18
|
+
end
|
19
|
+
dayz
|
20
|
+
end
|
21
|
+
|
22
|
+
def raw
|
23
|
+
@data
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
class ShiftNote::EmployeeOverviewViewModel
|
2
|
+
def initialize(data)
|
3
|
+
@raw = data
|
4
|
+
@id = data['EmployeeId']
|
5
|
+
@name = data['EmployeeName']
|
6
|
+
@phones = {
|
7
|
+
'home' => data['HomePhone'],
|
8
|
+
'mobile' => data['MobilePhone']
|
9
|
+
}
|
10
|
+
@email = data['Email']
|
11
|
+
@birthday = Time.parse(data['BirthDate'])
|
12
|
+
@schedule_this_week = ShiftNote::ScheduleThisWeekViewModel.new(data['ScheduleThisWeekViewModel'])
|
13
|
+
@trade_shifts = data['TradeShifts']
|
14
|
+
@trade_shifts_current_day = data['TradeShiftsCurrentDay']
|
15
|
+
@positions = data['ThisEmployeePositions']
|
16
|
+
@last_day = data['LastDay'] ? Time.parse(data['LastDay']) : nil
|
17
|
+
@hire_day = data['HireDate'] ? Time.parse(data['HireDate']) : nil
|
18
|
+
end
|
19
|
+
|
20
|
+
# This is the employee's ID. Really has no use outside of Shiftnote internal data
|
21
|
+
# @return [Integer] the employee's internal ID
|
22
|
+
attr_reader :id
|
23
|
+
|
24
|
+
# The employee's (legal) name.
|
25
|
+
# @return [String] the employee's name
|
26
|
+
attr_reader :name
|
27
|
+
|
28
|
+
# An array containing the user's home and mobile phone numbers
|
29
|
+
# @return [Array<String>] the user's phone numbers.
|
30
|
+
attr_reader :phones
|
31
|
+
|
32
|
+
# @return [String] the user's email.
|
33
|
+
attr_reader :email
|
34
|
+
|
35
|
+
# @return [Time] the user's birthday
|
36
|
+
attr_reader :birthday
|
37
|
+
|
38
|
+
# The user's "Schedule This Week," consider the return type for info
|
39
|
+
# @return [ShiftNote::ScheduleThisWeekViewModel]
|
40
|
+
attr_reader :schedule_this_week
|
41
|
+
attr_reader :raw
|
42
|
+
attr_reader :trade_shifts
|
43
|
+
attr_reader :trade_shifts_current_day
|
44
|
+
attr_reader :positions
|
45
|
+
attr_reader :last_day
|
46
|
+
attr_reader :hire_day
|
47
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class ShiftNote::ScheduleThisWeekViewModel
|
2
|
+
def initialize(data)
|
3
|
+
@raw = data
|
4
|
+
@start_date = Time.parse(data['StartDate'])
|
5
|
+
@end_date = Time.parse(data['EndDate'])
|
6
|
+
@hours = data['Hours']
|
7
|
+
@cost = data['Cost']
|
8
|
+
@shifts = data['Shifts']
|
9
|
+
@schedule = ShiftNote::DaysOfWeekShifts.new(data['DaysOfWeekShifts'])
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :start_date
|
13
|
+
attr_reader :end_date
|
14
|
+
attr_reader :hours
|
15
|
+
attr_reader :cost
|
16
|
+
attr_reader :shifts
|
17
|
+
attr_reader :schedule
|
18
|
+
attr_reader :raw
|
19
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
class ShiftNote::ShiftViewModel
|
2
|
+
def initialize(data)
|
3
|
+
@raw = data
|
4
|
+
@schedule_id = data['ScheduleId']
|
5
|
+
@schedule_name = data['ScheduleName']
|
6
|
+
@schedule_status_id = data['ScheduleStatusId']
|
7
|
+
@shift_id = data['ShiftId']
|
8
|
+
@employee_id = data['EmployeeId']
|
9
|
+
@employee = data['Employee']
|
10
|
+
@shift_date = Time.parse(data['ShiftDate'])
|
11
|
+
@time_in = Time.parse(data['TimeIn'])
|
12
|
+
@time_out = Time.parse(data['TimeOut'])
|
13
|
+
@position = data['Position']
|
14
|
+
@position_color = data['PositionColor']
|
15
|
+
@internal_location = data['InternalLocation']
|
16
|
+
@open = data['Open']
|
17
|
+
@close = data['Close']
|
18
|
+
@on_call = data['OnCall']
|
19
|
+
@volume = data['Volume']
|
20
|
+
@note = data['Note']
|
21
|
+
@hours = data['Hours']
|
22
|
+
@cost = data['Cost']
|
23
|
+
@is_pending_pickup = data['IsPendingPickUp']
|
24
|
+
@is_pending_manager_approval = data['IsPendingManagerApproval']
|
25
|
+
@is_pending_swap = data['IsPendingSwap']
|
26
|
+
@is_pending_swap_manager_approval = data['IsPendingSwapManagerApproval']
|
27
|
+
@hide_end_times = data['HideEndTimes']
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :schedule_id
|
31
|
+
attr_reader :schedule_name
|
32
|
+
attr_reader :schedule_status_id
|
33
|
+
attr_reader :shift_id
|
34
|
+
attr_reader :employee_id
|
35
|
+
attr_reader :employee
|
36
|
+
attr_reader :shift_date
|
37
|
+
attr_reader :time_in
|
38
|
+
attr_reader :time_out
|
39
|
+
attr_reader :position
|
40
|
+
attr_reader :position_color
|
41
|
+
attr_reader :internal_location
|
42
|
+
attr_reader :open
|
43
|
+
attr_reader :close
|
44
|
+
attr_reader :on_call
|
45
|
+
attr_reader :volume
|
46
|
+
attr_reader :note
|
47
|
+
attr_reader :hours
|
48
|
+
attr_reader :cost
|
49
|
+
attr_reader :is_pending_pickup
|
50
|
+
attr_reader :is_pending_manager_approval
|
51
|
+
attr_reader :is_pending_swap
|
52
|
+
attr_reader :is_pending_swap_manager_approval
|
53
|
+
attr_reader :hide_end_times
|
54
|
+
attr_reader :raw
|
55
|
+
|
56
|
+
# Releases the shift
|
57
|
+
def release(employee = 0)
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shiftnote
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chew
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-06-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: nokogiri
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.10.3
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.10.3
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rest-client
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.1.0.rc1
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.1.0.rc1
|
55
|
+
description: ShiftNote, an employee shift management system, but for Ruby
|
56
|
+
email: chew@chew.pw
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- lib/shiftnote.rb
|
62
|
+
- lib/shiftnote/days_of_week_shift.rb
|
63
|
+
- lib/shiftnote/days_of_week_shifts.rb
|
64
|
+
- lib/shiftnote/employee_overview_view_model.rb
|
65
|
+
- lib/shiftnote/errors.rb
|
66
|
+
- lib/shiftnote/schedule_this_week_view_model.rb
|
67
|
+
- lib/shiftnote/shift_view_model.rb
|
68
|
+
homepage: https://github.com/Chew/ShiftNoteRB
|
69
|
+
licenses:
|
70
|
+
- MIT
|
71
|
+
metadata:
|
72
|
+
bug_tracker_uri: https://github.com/Chew/ShiftNoteRB/issues
|
73
|
+
changelog_uri: https://github.com/Chew/ShiftNoteRB/releases
|
74
|
+
homepage_uri: http://github.com/Chew/ShiftNoteRB
|
75
|
+
source_code_uri: http://github.com/Chew/ShiftNoteRB
|
76
|
+
wiki_uri: http://github.com/Chew/ShiftNoteRB/wiki
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 2.2.4
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubygems_version: 3.0.2
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: ShiftNote, an employee shift management system, but for Ruby.
|
96
|
+
test_files: []
|