diff options
| author | Tim Schiewe <git@tforge.de> | 2018-04-30 19:18:46 +0200 |
|---|---|---|
| committer | Tim Schiewe <git@tforge.de> | 2018-04-30 19:18:46 +0200 |
| commit | ac85779f3b67ffc2953c17d0824be62b1f0acc86 (patch) | |
| tree | 5442df8297c3620ed72af7e3ece2a77ad58cce35 /src/sinks | |
| parent | 93b466df50d94d4c15715f5eb4d88a0be7d61c11 (diff) | |
| download | splus-ac85779f3b67ffc2953c17d0824be62b1f0acc86.tar.gz splus-ac85779f3b67ffc2953c17d0824be62b1f0acc86.zip | |
Implement interface/config based infrastructure
Fixes #2
Diffstat (limited to 'src/sinks')
| -rw-r--r-- | src/sinks/GoogleCalendarSink.ts | 100 | ||||
| -rw-r--r-- | src/sinks/ISink.ts | 7 | ||||
| -rw-r--r-- | src/sinks/IcalSink.ts | 46 |
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(); + }); + }); + } +} |
