Last active
June 9, 2023 01:36
-
-
Save CestDiego/91fdac8fcc42d27d2ca1fedec1c70507 to your computer and use it in GitHub Desktop.
ITP Camp Dashboard converter to ICS
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
// 🪄 Experimental: Use at your own risk ✨ | |
// Paste this into the Chrome developer tools console while you are in your dashboard page in list view | |
// It will either open your calendar or download an ics file, it works on my computer :) | |
// Read the code, and suggest improvements thanks. | |
let sessionsLists = document.querySelectorAll('#currentSessionsList .sessionListItem') | |
//Does not support events that end in the morning | |
let getEventData = event =>{ | |
let date = event.dataset.date | |
let time = event.querySelector('.sessionInfo b').textContent.replace('am','').replace('pm','').split('-') | |
let eventData; | |
eventData = { | |
eventName: event.querySelector('.sessionLeftColumn h3 a').textContent, | |
date, | |
time, | |
location: event.querySelector('.sessionLeftColumn h3 a').href | |
} | |
return eventData; | |
} | |
let getStartEndTime = (timeData) => { | |
const tzOffset = (new Date()).getTimezoneOffset() / 60 | |
const [start, end] = timeData.map(time => time.split(':')) | |
// TODO: Assumes that no event starts and ends in the morning | |
if (Number(start[0]) < Number(end[0])) { | |
start[0] = String(Number(start[0]) + 12); | |
} | |
end[0] = String(Number(end[0]) + 12); | |
// offset | |
// start[0] = String(Number(start[0]) + tzOffset); | |
// end[0] = String(Number(end[0]) + tzOffset); | |
return { | |
start: "T" + start[0].padStart(2,'0') + (start.length > 1 ? start[1].padStart(2,'0') : '00')+ '00', | |
end: "T" + end[0].padStart(2,'0') + (end.length > 1 ? end[1].padStart(2,'0') : '00')+ '00', | |
} | |
} | |
let getVEvent = (eventData) =>{ | |
if (eventData.time.length !== 2) | |
throw new Error('no time range in one of the events', eventData); | |
const yearMonthDay = eventData.date.replaceAll('-','') | |
const time = getStartEndTime(eventData.time) | |
return ` | |
BEGIN:VEVENT | |
DTSTART:${yearMonthDay}${time.start} | |
DTEND:${yearMonthDay}${time.end} | |
DTSTAMP:20230608T225928Z | |
LOCATION:${eventData.location} | |
SUMMARY:${eventData.eventName} | |
END:VEVENT` | |
} | |
// Spread operator magic | |
const header = `BEGIN:VCALENDAR | |
VERSION:2.0 | |
PRODID:-//ical.marudot.com//iCal Event Maker | |
CALSCALE:GREGORIAN | |
BEGIN:VTIMEZONE | |
TZID:America/New_York | |
LAST-MODIFIED:20201011T015911Z | |
TZURL:http://tzurl.org/zoneinfo-outlook/America/New_York | |
X-LIC-LOCATION:America/New_York | |
BEGIN:DAYLIGHT | |
TZNAME:EDT | |
TZOFFSETFROM:-0500 | |
TZOFFSETTO:-0400 | |
DTSTART:19700308T020000 | |
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU | |
END:DAYLIGHT | |
BEGIN:STANDARD | |
TZNAME:EST | |
TZOFFSETFROM:-0400 | |
TZOFFSETTO:-0500 | |
DTSTART:19701101T020000 | |
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU | |
END:STANDARD | |
END:VTIMEZONE` | |
const footer = ` | |
END:VCALENDAR | |
` | |
const ics = header + [...sessionsLists].map(getEventData).map(getVEvent).join('') + footer | |
console.log(ics) | |
window.open("data:text/calendar;charset=utf8," + escape(ics)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment