UNPKG

gcal-conf-free-api

Version:

An express API server that translates Google Calendar ical Free Busy information into a consumable JSON API

132 lines (102 loc) 3.65 kB
/*! This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* jshint strict: true, node: true */ 'use strict'; var ical = require('ical'), util = require('util'), express = require('express'), moment = require('moment'), _ = require('lodash'), config = require('config'), EventEmitter = require('events').EventEmitter; var debug = require('debug')('gcal-conf-free-api'); moment.locale('en', config.get('moment.en')); // how often to ping the calendar server in min var CALENDAR_INTERVAL = config.get('ics.calender-interval'); function FreeBusy() { FreeBusy.init.call(this); } FreeBusy.prototype.formatURL = function formatURL (url, room, now) { return util.format(url, encodeURIComponent(room.email), now.format("YYYYMMDD")); }; FreeBusy.init = function() { this.url = config.get('ics.url'); this.rooms = config.get('ics.rooms'); this.getAll(); // run every CALENDAR_INTERVAL min on the CALENDAR_INTERVAL setInterval(this.getAll, CALENDAR_INTERVAL * 1000); }; FreeBusy.prototype.free = function free() { return _.filter(this.rooms, function (room) { return room.current === null; }); }; FreeBusy.prototype.busy = function busy() { return _.filter(this.rooms, function (room) { return room.current !== null; }); }; FreeBusy.prototype.get = function get(room) { var now = moment(); var url = this.formatURL(this.url, room, now); debug(now.toDate(), url); var findToday = function(fb) { var eod = now.clone().endOf('day'); // starts later but today // || OR || // started before now but ends after now (runs through) return (moment(fb.start).isBetween(now, eod) || moment(fb.end).isBetween(now, eod)); }; // this function relies on an array sorted by start time var findNext = function(fb) { return !now.isBetween(fb.start, fb.end); }; var findNow = function(fb) { return now.isBetween(fb.start, fb.end); }; var sortStartTime = function(fb) { return moment(fb.start).valueOf(); }; ical.fromURL(url, {}, function(err, data) { if (err) { console.error(err); return err; } // debug(JSON.stringify(data,null," ")); // strip down the information to lists of Free Busy arrays var fbTypes = _.where(data, {type : 'VFREEBUSY'}); // debug('fbTypes', fbTypes); // Merge the arrays and convert the undefined items into empty arrays // Filter to only the data relevant to today room.freebusy = _.sortBy(_.filter(fbTypes, findToday), sortStartTime); debug('room.freebusy', room.freebusy); room.next = _.find(room.freebusy, findNext) || null; debug('room.next', room.next); room.current = _.find(room.freebusy, findNow) || null; debug('room.current', room.current); }, this); }; FreeBusy.prototype.getAll = function getAll() { _.each(this.rooms, this.get, this); }; // EXPRESS var app = module.exports.app = express(); var ffbb = new FreeBusy(); module.exports.fb = ffbb; // JSON API app.get('/api/rooms', function(req, res, next){ res.send({ rooms : ffbb.rooms }); }); app.get('/api/rooms/free', function(req, res, next){ res.send({ rooms : ffbb.free() }); }); app.get('/api/rooms/busy', function(req, res, next){ res.send({ rooms : ffbb.busy() }); }); if (!module.parent) { var server = app.listen(Number(process.env.PORT || 5000), function() { console.log('NODE_ENV=%s http://%s:%d', app.settings.env, server.address().address, server.address().port); }); }