-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(place): event scrape #118
base: master
Are you sure you want to change the base?
Changes from all commits
4681de3
1750ca1
ef510df
9554a98
983fdb3
50da4b9
de3d651
e20f841
7bba7f1
d8c7982
96bac74
927be22
58de43f
c00bece
043c66c
fb7693a
5475bb8
5a90b79
ccd89e4
41a3d32
03746c8
5be46e7
3d94bc1
0340904
934633c
0e234bc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
require "place_calendar" | ||
|
||
class Place::EventScrape < PlaceOS::Driver | ||
descriptive_name "PlaceOS Event Scrape" | ||
generic_name :EventScrape | ||
|
||
default_settings({ | ||
zone_ids: ["placeos-zone-id"], | ||
internal_domains: ["PlaceOS.com"] | ||
}) | ||
|
||
accessor staff_api : StaffAPI_1 | ||
|
||
@zone_ids = [] of String | ||
@internal_domains = [] of String | ||
|
||
alias Event = PlaceCalendar::Event | ||
|
||
struct SystemWithEvents | ||
include JSON::Serializable | ||
|
||
def initialize(@name : String, @zones : Array(String), @events : Array(Event)) | ||
end | ||
end | ||
|
||
def on_load | ||
on_update | ||
end | ||
|
||
def on_update | ||
@zone_ids = setting?(Array(String), :zone_ids) || [] of String | ||
@internal_domains = setting?(Array(String), :internal_domains) || [] of String | ||
end | ||
|
||
def todays_bookings | ||
response = { | ||
internal_domains: @internal_domains, | ||
systems: {} of String => SystemWithEvents | ||
} | ||
|
||
now = Time.local | ||
start_epoch = now.at_beginning_of_day.to_unix | ||
end_epoch = now.at_end_of_day.to_unix | ||
|
||
@zone_ids.each do |z_id| | ||
staff_api.systems(zone_id: z_id).get.as_a.each do |sys| | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The It should be possible to reorganise this so that you map |
||
sys_id = sys["id"].as_s | ||
# In case the same system is in multiple zones | ||
next if response[:systems][sys_id]? | ||
|
||
response[:systems][sys_id] = SystemWithEvents.new( | ||
name: sys["name"].as_s, | ||
zones: Array(String).from_json(sys["zones"].to_json), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a roundtrip through some JSON serialisation here that doesn't look to be required. |
||
events: get_system_bookings(sys_id, start_epoch, end_epoch) | ||
) | ||
end | ||
end | ||
|
||
response | ||
end | ||
|
||
def get_system_bookings(sys_id : String, start_epoch : Int64?, end_epoch : Int64?) : Array(Event) | ||
booking_module = staff_api.modules_from_system(sys_id).get.as_a.find { |mod| mod["name"] == "Bookings" } | ||
# If the system has a booking module with bookings | ||
if booking_module && (bookings = staff_api.get_module_state(booking_module["id"].as_s).get["bookings"]?) | ||
Comment on lines
+63
to
+65
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You may need to expand the staff API driver to support this, but this can collapse into a single query via this endpoint: |
||
bookings = Array(Event).from_json(bookings.as_s) | ||
|
||
# If both start_epoch and end_epoch are passed | ||
if start_epoch && end_epoch | ||
# Convert start/end_epoch to Time object as Event.event_start.class == Time | ||
start_time = Time.unix(start_epoch) | ||
end_time = Time.unix(end_epoch) | ||
range = (start_time..end_time) | ||
# Only select bookings within start_epoch and end_epoch | ||
bookings.select! { |b| range.includes?(b.event_start) } | ||
bookings | ||
end | ||
|
||
bookings | ||
else | ||
[] of Event | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
DriverSpecs.mock_driver "Place::EventScrape" do | ||
system({ | ||
StaffAPI: {StaffAPI} | ||
}) | ||
|
||
exec(:get_bookings) | ||
end | ||
|
||
class StaffAPI < DriverSpecs::MockDriver | ||
def systems(zone_id : String) | ||
logger.info { "requesting zone #{zone_id}" } | ||
|
||
sys_1 = { | ||
id: "sys-1", | ||
name: "Room 1", | ||
zones: ["placeos-zone-id"] | ||
} | ||
|
||
if zone_id == "placeos-zone-id" | ||
[sys_1] | ||
else | ||
[ | ||
sys_1, | ||
{ | ||
id: "sys-2", | ||
name: "Room 2", | ||
zones: ["zone-1"] | ||
} | ||
] | ||
end | ||
end | ||
|
||
def modules_from_system(system_id : String) | ||
[ | ||
{ | ||
id: "mod-1", | ||
control_system_id: system_id, | ||
name: "Calendar" | ||
}, | ||
{ | ||
id: "mod-2", | ||
control_system_id: system_id, | ||
name: "Bookings" | ||
}, | ||
{ | ||
id: "mod-3", | ||
control_system_id: system_id, | ||
name: "Bookings" | ||
} | ||
] | ||
end | ||
|
||
def get_module_state(module_id : String, lookup : String? = nil) | ||
now = Time.local | ||
start = now.at_beginning_of_day.to_unix | ||
ending = now.at_end_of_day.to_unix | ||
|
||
{ | ||
bookings: [{ | ||
event_start: start, | ||
event_end: ending, | ||
id: "booking-1", | ||
host: "[email protected]", | ||
title: "Test in #{module_id}" | ||
}].to_json | ||
} | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's unlikely the the server TZ will be the same as the users TZ.
May be worth pulling a larger time slice, then filtering on front-ends, or support passing a timezone either to this method call, or applying as a setting for the driver instance.