Skip to content

Instantly share code, notes, and snippets.

@AlJohri
Created February 13, 2020 07:53
Show Gist options
  • Save AlJohri/2e79aa77f678a2e9a10f0501cc25d8e4 to your computer and use it in GitHub Desktop.
Save AlJohri/2e79aa77f678a2e9a10f0501cc25d8e4 to your computer and use it in GitHub Desktop.
#!/usr/bin/osascript -l JavaScript
/*
Usage: ./extract.jxa
Outlook Object Model: https://docs.microsoft.com/en-us/office/vba/api/overview/outlook/object-model
*/
ObjC.import("stdlib");
SystemEvents = Application("System Events");
const calendarName = "Calendar";
const calendarIndex = 1;
const blacklistPhrases = ["Appt"];
function pick(obj, ...keys) {
return Object.fromEntries(
Object.entries(obj).filter(([key]) => keys.includes(key))
);
}
function any(iterable) {
for (var index = 0; index < iterable.length; index++) {
if (iterable[index]) return true;
}
return false;
}
function getDefaultDateRange({daysAgo=7, daysAhead=7}) {
var endTime = new Date();
var startTime = new Date(endTime);
startTime.setDate(startTime.getDate() - daysAgo);
endTime.setDate(endTime.getDate() + daysAhead);
return [startTime, endTime];
}
function getOrCreateCalendar(Calendar) {
const calendarName = "Outlook TickTick Sync";
const calendarDescription =
"Calendar used to synchronize TickTick with Outlook.";
let calendar = Calendar.calendars.whose({ name: calendarName })[0];
try {
calendar.get();
} catch (e) {
console.log(`Calendar "${calendarName}" not found.`);
calendar = null;
}
if (!calendar) {
console.log(`Creating calendar: "${calendarName}"`);
calendar = Calendar.Calendar({
name: calendarName,
description: calendarDescription
}).make();
}
if (calendar.name() != calendarName) {
throw "Something is wrong";
}
return calendar;
}
function getOutlookEvents({
Outlook,
calendarName,
calendarIndex,
startTime = null,
endTime = null,
removeAllDay = true,
removeMultiDay = true,
removeRecurrence = true,
blacklistPhrases = []
}) {
const calendar = Outlook.calendars.whose({ name: calendarName })[
calendarIndex
];
try {
calendar.get();
} catch (e) {
throw `Could not find an Outlook calendar with name "${calendarName}" at index "${calendarIndex}".`;
}
if (calendar.calendarEvents().length === 0) {
throw `Calendar "${calendarName} at index "${calendarIndex}" exists but has 0 events.`;
}
let critera = null;
if (startTime || endTime) {
let range = [];
if (startTime) range.push({ startTime: { _greaterThan: startTime } });
if (endTime) range.push({ endTime: { _lessThan: endTime } });
critera = { _and: range };
}
let events = critera
? calendar.calendarEvents.whose(critera)()
: calendar.calendarEvents();
if (removeAllDay) {
events = events.filter(x => !x.allDayFlag());
}
if (removeMultiDay) {
ONE_DAY = 24 * 60 * 60;
events = events.filter(x => (x.endTime() - x.startTime()) / 1000 < ONE_DAY);
}
if (removeRecurrence) {
// only keep occurance
events = events.filter(x => !x.isRecurring());
}
if (blacklistPhrases.length > 0) {
events = events.filter(
x => !any(blacklistPhrases.map(phrase => x.subject().includes(phrase)))
);
}
return events;
}
function getOrCreateEvent(Calendar, calendar, x) {
const id = x.id().toString();
let event;
try {
event = calendar.events.whose({url: id})[0];
event.get();
} catch (e) {
event = null;
}
if (!event) {
console.log(`Creating event ${id} ${x.subject()}`);
event = Calendar.Event({
url: id,
summary: x.subject(),
startDate: x.startTime(),
endDate: x.endTime(),
description: x.plainTextContent(),
alldayEvent: x.allDayFlag(),
location: x.location(),
});
calendar.events.push(event);
} else {
console.log(`Skipping event ${id} ${x.subject()}, already exists`);
}
return event;
}
function main() {
const Outlook = Application("Microsoft Outlook");
const Calendar = Application("Calendar");
if (!Calendar.running()) {
Calendar.launch();
delay(1);
}
const calendar = getOrCreateCalendar(Calendar);
[startTime, endTime] = getDefaultDateRange({daysAgo:14, daysAhead:14});
const events = getOutlookEvents({
Outlook,
calendarName,
calendarIndex,
startTime,
endTime,
blacklistPhrases,
removeAllDay: true,
removeMultiDay: true,
removeRecurrence: true
});
console.log(
`${events.length} events found between ${startTime} and ${endTime}`
);
for (let event of events) {
getOrCreateEvent(Calendar, calendar, event);
}
}
function run(args) {
const App = Application.currentApplication();
App.includeStandardAdditions = true;
try {
main();
} catch (e) {
App.displayAlert(e.toString());
throw e;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment