This repository was archived by the owner on Feb 2, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 105
This repository was archived by the owner on Feb 2, 2021. It is now read-only.
Google Script to Sync with Calendar #98
Copy link
Copy link
Open
Description
I wrote a little Google script that creates a cfp
calendar from your list. To try it, go to drive.google.com, click New -> Google Apps Script, copy the code into the editor, select syncCfpCalendar
as the function to be executed and click the play button. Reload calendar.google.com and you should see a new cfp
calendar. Google also provides triggers so you can run this nightly (click Edit -> Current Project's Triggers).
If you think this is useful, feel free to publish it, put it in a readme, provide a public calendar, whatever you want.
var sources = [
{
rawUrl: 'https://raw.githubusercontent.com/softwaremill/it-cfp-list/master/README.md',
link: 'https://github.com/softwaremill/it-cfp-list'
}
]
// name of the calendar to be updated / created.
var calendarName = 'cfp';
// All calendar events are tagged, so we don't accidentally delete unrelated events.
var tag = {
key: 'generated-by',
value: 'cfp-calendar-sync'
};
// main function
function syncCfpCalendar() {
var cal = openCalendar();
for each (source in sources) {
var markdownContent = loadMarkdownContent(source.rawUrl);
processMarkdownContent(markdownContent, source.link, cal);
}
}
function loadMarkdownContent(url) {
var response = UrlFetchApp.fetch(sources[0].rawUrl);
if (response.getResponseCode() != 200) {
throw new Error("Got HTTP " + response.getResponseCode() + " when fetching " + cfpListUrl);
}
return response.getContentText();
}
function processMarkdownContent(markdownContent, link, cal) {
var tableStart = false
for each (line in markdownContent.split(/\r?\n/)) {
if (!tableStart) {
if (line.match(/\|-+\|-+\|-+\|-+\|-+\|-+\|/)) {
tableStart = true;
}
} else {
if (!startsWith(line, "|")) {
return; // end of table
}
processTableLine(line, link, cal)
}
}
}
function processTableLine(line, link, cal) {
if (!line.match(/\|.*\|.*\|.*\|.*\|.*\|.*\|/)) {
Logger.log("skipping line " + line)
}
line = line.substring(1, line.length-1); // strip "|" from the beginning and end.
fields = line.split("|")
var cfpStart = startDate(fields[0].trim());
var cfpEnd = endDate(fields[0].trim());
var confStart = startDate(fields[1].trim());
var confEnd = endDate(fields[1].trim());
var location = fields[2].trim();
var name = stripLink(fields[3].trim());
var keywords = fields[5].trim();
if (cfpStart && cfpEnd && cfpStart <= cfpEnd) {
createEvent('CFP ' + name, cfpStart, cfpEnd, keywords, location, link, cal)
}
if (confStart && confEnd && confStart <= confEnd) {
createEvent(name, confStart, confEnd, keywords, location, link, cal)
}
}
function createEvent(name, start, endInclusive, keywords, location, link, cal) {
// end date is exclusive, so add 1 day
var evt = cal.createAllDayEvent(name, start, addDays(endInclusive, 1), {description: keywords + ', see ' + link, location: location});
evt.setTag(tag.key, tag.value);
}
function startDate(dateString) {
// Date formats used in the CFP List:
// 2018.12.08
// 2018.11.27-29
// 2018.11.30-12.01
// For the start date, we can ignore stuff following the '-' character.
match = dateString.match(/^([0-9]{4})\.([0-9]{2})\.([0-9]{2})(-.*)?$/)
if (match) {
return dateFromCaptureGroups(match, 1, 2, 3);
}
}
function endDate(dateString) {
// Date formats used in the CFP List:
// 2018.12.08
// 2018.11.27-29
// 2018.11.30-12.01
match = dateString.match(/^([0-9]{4})\.([0-9]{2})\.([0-9]{2})$/)
if (match) {
return dateFromCaptureGroups(match, 1, 2, 3);
}
match = dateString.match(/^([0-9]{4})\.([0-9]{2})\.([0-9]{2})-([0-9]{2})$/)
if (match) {
return dateFromCaptureGroups(match, 1, 2, 4);
}
match = dateString.match(/^([0-9]{4})\.([0-9]{2})\.([0-9]{2})-([0-9]{2})\.([0-9]{2})$/)
if (match) {
return dateFromCaptureGroups(match, 1, 4, 5);
}
}
function dateFromCaptureGroups(match, yearIndex, monthIndex, dayIndex) {
return new Date(parseInt(match[yearIndex], 10), parseInt(match[monthIndex], 10) - 1, dayInt = parseInt(match[dayIndex], 10));
}
function stripLink(markdownString) {
// "[devoxx](https://devoxx.be)" -> "devoxx"
return markdownString.replace(/\[([^\]]+)\]\([^)]+\)/, '$1')
}
function startsWith(s, c) {
return s.indexOf(c) == 0;
}
function addYears(date, years) {
var result = new Date(date);
result.setFullYear(date.getFullYear()+years);
return result;
}
function subtractYears(date, years) {
return addYears(date, 0-years);
}
function addDays(date, days) {
var result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}
function openCalendar() {
var calendars = CalendarApp.getCalendarsByName(calendarName);
switch (calendars.length) {
case 0:
// not found. create a new calendar.
return CalendarApp.createCalendar(calendarName, {summary: 'CFP calendar generated from ...'});
case 1:
// found. clear existing events, because events will be re-created
var today = new Date(),
twoYearsAgo = subtractYears(today, 2), // API requires a time range for getEvents. take a 4 year time range so we get all events.
twoYearsFromNow = addYears(today, 2),
events = calendars[0].getEvents(twoYearsAgo, twoYearsFromNow);
for (var i = 0; i < events.length; i++) {
if (events[i].getTag(tag.key) === tag.value) {
events[i].deleteEvent()
}
}
return calendars[0]
default:
throw new Error('found ' + calendars.length + ' calendars with name ' + calendarName + '.');
}
}
gounthar, maciejwalkowiak, rhuss, ederks85 and it-cfp-list
Metadata
Metadata
Assignees
Labels
No labels