-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathauto-break-time.ts
168 lines (153 loc) · 4.93 KB
/
auto-break-time.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// import cw, { morgen } from "morgen-cw-sdk";
import { Interval } from "luxon";
import cw, { sandbox } from "../src";
import { fetchJSON, fetchMorgen, morgen } from "../src/global";
const { log } = sandbox.util;
const { luxon } = sandbox.deps;
const wf = cw.workflow(
{
name: "Automatic breaks (SDK test)",
},
async function run(trigger) {
if (!trigger.accounts?.calendar?.[0]?.calendarId)
throw new Error("No calendar configured!");
const { accountId, calendarId } = trigger.accounts.calendar[0];
// Break preferences for the working day every day
// e.g. "10am, 3pm, 6pm"
// duration: { minutes: 15 }
const preferredBreaks = [
{
time: "10:00",
title: "Coffee ☕️✨",
duration: { minutes: 15 },
},
{
time: "12:00",
title: "Lunch 🥪",
duration: { minutes: 60 },
},
{
time: "15:00",
title: "Stretch break 🧘",
duration: { minutes: 30 },
},
];
const { DateTime, Interval, Duration } = luxon;
const rangeDays = 7;
// Get events for the next 7 days
const today = DateTime.now().setZone("Europe/Zurich").startOf("day");
const nextWeek = today.plus({ days: rangeDays });
const evs = await morgen().events.listEventsV3({
accountId,
calendarIds: calendarId,
start: today.toISO({ suppressMilliseconds: true, includeOffset: false })!,
end: nextWeek.toISO({
suppressMilliseconds: true,
includeOffset: false,
})!,
});
const intervals =
evs?.data?.events?.map((e) => {
const start = DateTime.fromISO(e.start!, { zone: e.timeZone });
const end = start.plus(Duration.fromISO(e.duration!));
return {
interval: Interval.fromDateTimes(start, end),
isBreak: e.description?.includes("#break"),
};
}) || [];
const newBreaks: {
interval: Interval;
title: string;
}[] = [];
for (let day = 0; day < rangeDays; day++) {
const currentDay = today.plus({ day });
// Ignore weekends
if (currentDay.weekday > 5) continue;
for (let brk of preferredBreaks) {
const [hour, minute] = brk.time.split(":").map((i) => parseInt(i, 10));
log(brk.time, brk.time.split(":"));
log(hour + "h" + minute + "m");
const duration = Duration.fromObject(brk.duration);
// Check if the break already exists
let newInterval = Interval.after(
currentDay.set({ hour, minute }),
duration
);
let existingInterval = intervals.find((existingInterval) =>
existingInterval.interval.intersection(newInterval)
);
let shouldCreateBreak = true;
// Until there is no intersection with an existing interval, move the
// newly proposed break time
while (existingInterval) {
// There's an intersection, give up if it is equal to the break
if (
existingInterval.interval.equals(newInterval) &&
existingInterval.isBreak
) {
existingInterval = undefined;
shouldCreateBreak = false;
// Do not add the break, there's already one there
continue;
}
// There's an intersection, but it's not a break,
// so move the start time to the end of this event.
newInterval = newInterval.set({
start: existingInterval.interval.end!,
end: existingInterval.interval.end?.plus(newInterval.toDuration()),
});
// Check whether this new interval intersects with an existing one
existingInterval = intervals.find(
(existingInterval) =>
newInterval && existingInterval.interval.intersection(newInterval)
);
}
if (!shouldCreateBreak) continue;
newBreaks.push({
...brk,
title: brk.title || "Break",
interval: newInterval,
});
}
}
log(JSON.stringify(newBreaks));
log(accountId + " " + calendarId);
for (let brk of newBreaks) {
const start = brk.interval.start!.toISO({
suppressMilliseconds: true,
includeOffset: false,
})!;
log("Creating ... " + JSON.stringify({ start, title: brk.title }));
const resp = await morgen().events.createEventV3({
requestBody: {
calendarId,
accountId,
title: brk.title,
description: "#break",
timeZone: "Europe/Zurich",
showWithoutTime: false,
start,
duration: brk.interval.toDuration().rescale().toISO()!,
},
});
log("Resp " + JSON.stringify(resp));
}
}
);
wf.upload().then(() => wf.trigger());
/*
wf.run({
httpParams: {},
eventUpdates: { added: [], removed: [], modified: [] },
accounts: {
calendar: [
{
accountId: "123",
calendarId: "123",
},
],
},
user: { email: "", firstName: "" },
});
//);
//*/