Skip to content

Commit d97bb43

Browse files
authored
feat(mulesoft): add Calendar exporter
1 parent e31d7f1 commit d97bb43

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
module MuleSoft; end
2+
3+
require "./models"
4+
require "place_calendar"
5+
6+
class MuleSoft::CalendarExporter < PlaceOS::Driver
7+
descriptive_name "MuleSoft Bookings to Calendar Events Exporter"
8+
generic_name :Bookings
9+
description %(Retrieves and creates bookings using the MuleSoft API)
10+
11+
default_settings({
12+
calendar_time_zone: "Australia/Sydney"
13+
})
14+
15+
accessor calendar : Calendar_1
16+
17+
@time_zone_string : String | Nil = "Australia/Sydney"
18+
@time_zone : Time::Location = Time::Location.load("Australia/Sydney")
19+
@bookings : Array( Hash(String, Int64 | String | Nil) ) = [] of Hash(String, Int64 | String | Nil)
20+
@existing_events : Array(JSON::Any) = [] of JSON::Any
21+
# An array of Attendee that has only the system (room) email address. Generally static
22+
@just_this_system : NamedTuple(email: String, name: String) = {email: "", name: ""}
23+
24+
def on_load
25+
@just_this_system = {
26+
"email": system.email.not_nil!,
27+
"name": system.name
28+
}
29+
on_update
30+
end
31+
32+
def on_update
33+
subscriptions.clear
34+
35+
@time_zone_string = setting?(String, :calendar_time_zone).presence
36+
@time_zone = Time::Location.load(@time_zone_string.not_nil!) if @time_zone_string
37+
self[:timezone] = Time.local.to_s
38+
39+
subscription = system.subscribe(:Bookings_1, :bookings) do |subscription, mulesoft_bookings|
40+
logger.debug {"DETECTED changed in Mulesoft Bookings.."}
41+
@bookings = Array( Hash(String, Int64 | String | Nil) ).from_json(mulesoft_bookings)
42+
logger.debug {"#{@bookings.size} bookings in total"}
43+
44+
update_events
45+
@bookings.each {|b| export_booking(b)}
46+
end
47+
end
48+
49+
def status()
50+
{
51+
"bookings": @bookings,
52+
"events": @existing_events
53+
}
54+
end
55+
56+
def update_events
57+
logger.debug {"FETCHING existing Calendar events..."}
58+
@existing_events = fetch_events()
59+
logger.debug {"#{@existing_events.size} events in total"}
60+
end
61+
62+
protected def fetch_events(past_span : Time::Span = 14.days, future_span : Time::Span = 14.days)
63+
now = Time.local @time_zone
64+
from = now - past_span
65+
til = now + future_span
66+
67+
calendar.list_events(
68+
calendar_id: system.email.not_nil!,
69+
period_start: from.to_unix,
70+
period_end: til.to_unix
71+
).get.as_a
72+
end
73+
74+
75+
protected def export_booking(booking : Hash(String, Int64 | String | Nil))
76+
# Mulesoft booking titles are often nil. Use the body instead in this case
77+
booking["title"] = booking["body"] if booking["title"].nil?
78+
booking["title"] = "#{booking["recurring_master_id"]} #{booking["title"]}"
79+
logger.debug {"Checking for existing events that match: #{booking}"}
80+
81+
unless event_already_exists?(booking, @existing_events)
82+
new_event = {
83+
title: booking["title"],
84+
event_start: booking["event_start"],
85+
event_end: booking["event_end"],
86+
timezone: @time_zone_string,
87+
description: booking["body"],
88+
user_id: system.email.not_nil!,
89+
attendees: [@just_this_system],
90+
location: system.name.not_nil!
91+
}
92+
logger.debug {">>> EXPORTING booking #{new_event}"}
93+
calendar.create_event(**new_event)
94+
end
95+
end
96+
97+
protected def event_already_exists?(new_event : Hash(String, Int64 | String | Nil), existing_events : Array(JSON::Any))
98+
existing_events.each do |existing_event|
99+
return true if events_match?(new_event, existing_event.as_h)
100+
end
101+
false
102+
end
103+
104+
protected def events_match?(event_a : Hash(String, Int64 | String | Nil), event_b : Hash(String, JSON::Any))
105+
event_a.select("event_start", "event_end", "title") == event_b.select("event_start", "event_end", "title")
106+
end
107+
108+
def delete_all_events(past_days : Int32 = 14, future_days : Int32 = 14)
109+
events = fetch_events(past_span: past_days.days, future_span: future_days.days)
110+
event_ids = events.map { |e| e["id"]}
111+
event_ids.each do |event_id|
112+
calendar.delete_event(calendar_id: system.email.not_nil!, event_id: event_id)
113+
end
114+
"Deleted #{event_ids.size} events"
115+
end
116+
117+
end

0 commit comments

Comments
 (0)