Created
August 2, 2022 18:18
-
-
Save EmilePerron/1b7dc81c73b84aa0097d6068263ab8c8 to your computer and use it in GitHub Desktop.
Arc Boost to make Microsoft Teams show notification 2 mins before events
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const notifiedEvents = new Map(); | |
let events = []; | |
// Load and refresh events when the calendar view is open | |
function refreshEvents() { | |
const eventNodes = document.querySelectorAll("[aria-label*='organized by'][aria-label*='for more options'][title*='from']"); | |
if (!eventNodes.length) { | |
return; | |
} | |
events = []; | |
for (const eventNode of eventNodes) { | |
const name = eventNode.title.split('from')[0].trim(); | |
const datetimeString = eventNode.title.split('from')[1].trim().split('to')[0].trim(); | |
const dateString = eventNode.title.split('from')[1].trim().split('to')[0].trim().replace(/(^.+?,\s.+?\s\d+).+$/, '$1'); | |
const timeString = eventNode.title.split('from')[1].trim().split('to')[0].trim().replace(/^.+?,\s.+?\s\d+(.+)$/, '$1').trim(); | |
const date = formatDate(dateString); | |
const time = convertTimeTo24HrsFormat(timeString); | |
events.push({ | |
name, | |
datetime: new Date(`${date} ${time}`), | |
date, | |
time, | |
datetimeString, | |
dateString, | |
timeString, | |
id: `${datetimeString}${name}`, | |
}); | |
} | |
} | |
setInterval(refreshEvents, 1000); | |
// Check for upcoming events | |
setInterval(() => { | |
const now = (new Date()); | |
for (const event of events) { | |
if (notifiedEvents.has(event.id)) { | |
continue; | |
} | |
const secondsUntilEventStart = (event.datetime.getTime() - now.getTime()) / 1000; | |
if (secondsUntilEventStart > 0 && secondsUntilEventStart <= 120) { | |
if (Notification.permission === "granted") { | |
sendEventNotification(event); | |
} else if (Notification.permission !== "denied") { | |
Notification.requestPermission().then(function (permission) { | |
if (permission === "granted") { | |
sendEventNotification(event); | |
} | |
}); | |
} | |
} | |
} | |
window.events = events; | |
}, 5000); | |
function sendEventNotification(event) { | |
notifiedEvents.set(event.id, true); | |
new Notification(`Heads up! ${event.name} is starting at ${event.timeString}`); | |
} | |
// utils | |
function formatDate(date) { | |
const d = new Date(date); | |
const year = new Date().getFullYear(); | |
let month = '' + (d.getMonth() + 1); | |
let day = '' + d.getDate(); | |
if (month.length < 2) { | |
month = '0' + month; | |
} | |
if (day.length < 2) { | |
day = '0' + day; | |
} | |
return `${year}-${month}-${day}`; | |
} | |
function convertTimeTo24HrsFormat(time) { | |
const slicedTime = time.split(/(PM|AM)/gm)[0].trim(); | |
let [hours, minutes] = slicedTime.split(':'); | |
if (hours === '12') { | |
hours = '00'; | |
} | |
let updateHourAndMin; | |
function addition(hoursOrMin) { | |
updateHourAndMin = | |
hoursOrMin.length < 2 | |
? (hoursOrMin = `${0}${hoursOrMin}`) | |
: hoursOrMin; | |
return updateHourAndMin; | |
} | |
if (time.endsWith('PM')) { | |
hours = parseInt(hours, 10) + 12; | |
} | |
return `${addition(hours)}:${addition(minutes)}`; | |
} | |
I made a few tweaks to get this working in British English. Since there are a few differences like date format and "organised" instead of "organized":
Source code (en-gb)
const notifiedEvents = new Map();
let events = [];
// Load and refresh events when the calendar view is open
function refreshEvents() {
const eventNodes = document.querySelectorAll("[aria-label*='organised by'][aria-label*='for more options'][title*='from']");
if (!eventNodes.length) {
return;
}
events = [];
for (const eventNode of eventNodes) {
const name = eventNode.title.split('from')[0].trim();
const datetimeString = eventNode.title.split('from')[1].trim().split('to')[0].trim();
const dateString = eventNode.title.split('from')[1].trim().split('to')[0].trim().slice(0, -6);
const time = eventNode.title.split('from')[1].trim().split('to')[0].trim().substr(-5);
const date = formatDate(dateString);
events.push({
name,
datetime: new Date(`${date} ${time}`),
date,
time,
datetimeString,
dateString,
id: `${datetimeString}${name}`,
});
}
}
setInterval(refreshEvents, 1000);
// Check for upcoming events
setInterval(() => {
const now = (new Date());
for (const event of events) {
if (notifiedEvents.has(event.id)) {
continue;
}
const secondsUntilEventStart = (event.datetime.getTime() - now.getTime()) / 1000;
if (secondsUntilEventStart > 0 && secondsUntilEventStart <= 120) {
if (Notification.permission === "granted") {
sendEventNotification(event);
} else if (Notification.permission !== "denied") {
Notification.requestPermission().then(function (permission) {
if (permission === "granted") {
sendEventNotification(event);
}
});
}
}
}
window.events = events;
}, 5000);
function sendEventNotification(event) {
notifiedEvents.set(event.id, true);
new Notification(`Heads up! ${event.name} is starting at ${event.time}`);
}
// utils
function formatDate(date) {
const d = new Date(date);
const year = new Date().getFullYear();
let month = '' + (d.getMonth() + 1);
let day = '' + d.getDate();
if (month.length < 2) {
month = '0' + month;
}
if (day.length < 2) {
day = '0' + day;
}
return `${year}-${month}-${day}`;
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This isn't a perfect gist, but it works for my purpose and I figured it might be a good starting point for others as well.
Basically:
Please don't mind the code quality: I hadn't planned on sharing this 😅