shiftnote 0.1.0
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 +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: []
|