Created
February 13, 2020 07:53
-
-
Save AlJohri/2e79aa77f678a2e9a10f0501cc25d8e4 to your computer and use it in GitHub Desktop.
This file contains 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
#!/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