summaryrefslogtreecommitdiff
path: root/src/sinks
diff options
context:
space:
mode:
Diffstat (limited to 'src/sinks')
-rw-r--r--src/sinks/GoogleCalendarSink.ts100
-rw-r--r--src/sinks/ISink.ts7
-rw-r--r--src/sinks/IcalSink.ts46
3 files changed, 153 insertions, 0 deletions
diff --git a/src/sinks/GoogleCalendarSink.ts b/src/sinks/GoogleCalendarSink.ts
new file mode 100644
index 0000000..374cc48
--- /dev/null
+++ b/src/sinks/GoogleCalendarSink.ts
@@ -0,0 +1,100 @@
+import * as fs from 'fs';
+import * as readline from 'readline';
+
+import {google} from 'googleapis';
+
+import {ISink} from './ISink';
+import {IEvent} from '../core/IEvent';
+
+
+const OAuth2Client = google.auth.OAuth2;
+const scopes = ['https://www.googleapis.com/auth/calendar'];
+
+const credentialsPath = 'etc/google/client_secret.json';
+const tokenPath = 'etc/google/credentials.json';
+
+const clientPromise = new Promise((resolve, reject) => {
+ fs.readFile(credentialsPath, (err, data) => {
+ if (err) return reject(err);
+
+ const credentials = JSON.parse(data.toString());
+ const {client_secret, client_id, redirect_uris} = credentials.installed;
+
+ const client = new OAuth2Client(client_id, client_secret, redirect_uris[0]);
+
+ fs.readFile(tokenPath, (err, data) => {
+ if (err) {
+ const authUrl = client.generateAuthUrl({
+ access_type: 'offline',
+ scope: scopes,
+ });
+
+ console.log('Authorize this app by visiting this url:', authUrl);
+
+ const rl = readline.createInterface({
+ input: process.stdin,
+ output: process.stdout,
+ });
+
+ rl.question('Enter the code from that page here: ', code => {
+ rl.close();
+ client.getToken(code, (err, token) => {
+ if (err) return reject(err);
+ fs.writeFile(tokenPath, JSON.stringify(token), err => err ? console.error(err) : 0);
+ client.setCredentials(token);
+ resolve(client);
+ });
+ });
+ }
+ else {
+ client.setCredentials(JSON.parse(data.toString()));
+ resolve(client);
+ }
+ });
+ });
+});
+
+
+const calendarPromise = clientPromise.then(auth => google.calendar({version: 'v3', auth}));
+
+
+export class GoogleCalendarSink implements ISink {
+ private _calendarId: string;
+
+ constructor(calendarId = 'primary') {
+ this._calendarId = calendarId;
+ }
+
+ createEvent(event: IEvent): Promise<void> {
+ const googleEvent = {
+ summary: event.summary,
+ description: event.description,
+ location: event.location,
+ start: {
+ dateTime: event.start.toISOString()
+ },
+ end: {
+ dateTime: event.end.toISOString()
+ },
+ reminders: {
+ useDefault: false
+ }
+ };
+
+ return calendarPromise.then(calendar => {
+ return new Promise<void>((resolve, reject) => {
+ calendar.events.insert({
+ calendarId: this._calendarId,
+ resource: googleEvent,
+ }, function (err, event) {
+ if (err) return reject(err);
+ resolve();
+ });
+ });
+ });
+ }
+
+ commit(): Promise<void> {
+ return Promise.resolve();
+ }
+}
diff --git a/src/sinks/ISink.ts b/src/sinks/ISink.ts
new file mode 100644
index 0000000..aaacf35
--- /dev/null
+++ b/src/sinks/ISink.ts
@@ -0,0 +1,7 @@
+import {IEvent} from '../core/IEvent';
+
+export interface ISink {
+ createEvent(event: IEvent): Promise<void>;
+
+ commit(): Promise<void>
+}
diff --git a/src/sinks/IcalSink.ts b/src/sinks/IcalSink.ts
new file mode 100644
index 0000000..efb94ac
--- /dev/null
+++ b/src/sinks/IcalSink.ts
@@ -0,0 +1,46 @@
+import {createHash} from 'crypto';
+import {writeFile} from 'fs';
+
+import * as ical from 'ical-generator';
+
+import {ISink} from './ISink';
+import {IEvent} from '../core/IEvent';
+
+
+const sha256 = (x) => createHash('sha256').update(x, 'utf8').digest('hex');
+
+
+// ref. https://www.npmjs.com/package/ical-generator
+export class IcalSink implements ISink {
+ private _cal = ical();
+ private _targetFile: string;
+
+ constructor(targetFile: string) {
+ this._targetFile = targetFile;
+ }
+
+ createEvent(event: IEvent): Promise<void> {
+ // TODO better duplicate detection and resolve conflicts lol
+ const eventId = sha256(JSON.stringify(event)).substr(0, 16);
+
+ const icalEvent = this._cal.createEvent({
+ uid: eventId,
+ start: event.start.toISOString(),
+ end: event.end.toISOString(),
+ timestamp: new Date(),
+ summary: event.summary,
+ description: event.description,
+ });
+
+ return Promise.resolve();
+ }
+
+ commit(): Promise<void> {
+ return new Promise<void>((resolve, reject) => {
+ writeFile(this._targetFile, this._cal.toString(), err => {
+ if (err) return reject(err);
+ resolve();
+ });
+ });
+ }
+}