488 lines
15 KiB
JavaScript
488 lines
15 KiB
JavaScript
const request = require('request')
|
|
const log4js = require('log4js')
|
|
const logger = log4js.getLogger()
|
|
const STRING = require('string')
|
|
let util = require('util')
|
|
const Elapsed = require('elapsed')
|
|
require('sugar-date');
|
|
|
|
function processICAL(ical) {
|
|
'use strict';
|
|
logger.info('+ processICAL');
|
|
let workingBlock = []
|
|
const segments = {
|
|
meetingStartID: 'DTSTART;TZID=Europe/London:',
|
|
meetingStartAlt: 'DTSTART:',
|
|
meetingStartAltOther: 'DTSTART;VALUE=DATE:',
|
|
meetingEndID: 'DTEND;TZID=Europe/London:',
|
|
meetingEndAlt: 'DTEND:',
|
|
meetingEndAltOther: 'DTEND;VALUE=DATE:',
|
|
meetingDescID: 'DESCRIPTION:',
|
|
summaryID: 'SUMMARY:',
|
|
begin: 'BEGIN:VEVENT',
|
|
end: 'END:VEVENT',
|
|
beginAlarm: 'BEGIN:VALARM',
|
|
endAlarm: 'END:VALARM',
|
|
recur: 'RRULE:'
|
|
}
|
|
|
|
const rules = ['FREQ', 'WKST', 'UNTIL', 'BYMONTH', 'BYMONTHDAY', 'INTERVAL', 'BYDAY']
|
|
|
|
function nThDayOfMonth(monthsAhead, wantedDay) {
|
|
const now = new Date()
|
|
|
|
for(let t=0; t < monthsAhead; t++) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
function processRecurrence(workBlock) {
|
|
let _workBlock = workBlock
|
|
// logger.debug('Processing recurrence...');
|
|
// logger.debug('Processing recurrence...');
|
|
const weekBits = {'SU': 0, 'MO': 1, 'TU': 2, 'WE': 3, 'TH': 4, 'FR': 5, 'SA': 6}
|
|
|
|
const now = new Date()
|
|
const day = now.getDate()
|
|
const dayNum = now.getDay()
|
|
const month = now.getMonth()
|
|
const year = now.getFullYear()
|
|
|
|
let recurSettings = {freq: null, wkst: null, until: null, bymonth: null, bymonthday: null, interval: null, byday: null}
|
|
|
|
const firstSplit = _workBlock.recur.split(';')
|
|
|
|
for (let t=0; t< firstSplit.length; t++)
|
|
{
|
|
const ws = firstSplit[t].split('=')
|
|
if (rules.indexOf(ws[0]) > -1) {
|
|
recurSettings[ws[0].toLowerCase()] = ws[1];
|
|
}
|
|
}
|
|
|
|
// if all null discard..
|
|
|
|
if (recurSettings.freq === null && recurSettings.wkst === null && recurSettings.until === null && recurSettings.byday === null && recurSettings.bymonth === null && recurSettings.bymonthday === null && recurSettings.interval === null) {
|
|
return null;
|
|
}
|
|
|
|
if (recurSettings.until !== null) {
|
|
// have we expired?
|
|
//var _until = Date.create(recurSettings.until).isPast();
|
|
return null;
|
|
}
|
|
|
|
if (recurSettings.freq !== null) {
|
|
|
|
// logger.debug(_workBlock);
|
|
let origStart, origEnd, distance, newStart, newEnd
|
|
|
|
origStart = Date.create(_workBlock.dtstart);
|
|
origEnd = Date.create(_workBlock.dtend);
|
|
const _d = origStart.getDate()
|
|
const _m = origStart.getMonth()
|
|
const _h = origStart.getHours()
|
|
const _min = origStart.getMinutes()
|
|
const _secs = origStart.getSeconds()
|
|
distance = origEnd - origStart;
|
|
|
|
if (recurSettings.freq === 'YEARLY') {
|
|
|
|
if (recurSettings.bymonth !== null && recurSettings.bymonthday !== null) {
|
|
// ok, a day and month.
|
|
newStart = Date.create().set({year:year, month: recurSettings.bymonth - 1 , day: recurSettings.bymonthday, hour:_h, minutes:_min, seconds:_secs});
|
|
newEnd = Date.create(newStart).addMilliseconds(distance);
|
|
_workBlock.dtstart = newStart;
|
|
_workBlock.dtend = newEnd;
|
|
|
|
} else if (recurSettings.bymonth === null && recurSettings.bymonthday === null) {
|
|
// extract month and year from dtstart
|
|
newStart = Date.create().set({year:year, month: _m , day: _d, hour:_h, minutes:_min, seconds:_secs});
|
|
newEnd = Date.create(newStart).addMilliseconds(distance);
|
|
_workBlock.dtstart = newStart;
|
|
_workBlock.dtend = newEnd;
|
|
|
|
}
|
|
|
|
return _workBlock;
|
|
}
|
|
|
|
if (recurSettings.freq === 'MONTHLY') {
|
|
if (recurSettings.bymonthday !== null) {
|
|
// ok, a day and month.
|
|
newStart = Date.create().set({year:year, month: month , day: recurSettings.bymonthday, hour:_h, minutes:_min, seconds:_secs});
|
|
newEnd = Date.create(newStart).addMilliseconds(distance);
|
|
|
|
_workBlock.dtstart = newStart;
|
|
_workBlock.dtend = newEnd;
|
|
|
|
}
|
|
}
|
|
|
|
if (recurSettings.freq === 'WEEKLY' && recurSettings.interval === null) {
|
|
const byDayBit = recurSettings.byday.split(',')[0]
|
|
const byDayNumber = weekBits[byDayBit]
|
|
if (byDayNumber >= dayNum) {
|
|
const daysAdded = byDayNumber - dayNum
|
|
newStart = Date.create().set({year:year, month: month , day: day, hour:_h, minutes:_min, seconds:_secs}).addDays(daysAdded);
|
|
newEnd = Date.create(newStart).addMilliseconds(distance);
|
|
_workBlock.dtstart = newStart;
|
|
_workBlock.dtend = newEnd;
|
|
}
|
|
}
|
|
}
|
|
|
|
// if we get here we've skipped everything just return the _workblock
|
|
|
|
return _workBlock;
|
|
}
|
|
|
|
function processBlock(block) {
|
|
let _wb
|
|
let workBlock = {
|
|
summary: '',
|
|
dtstart: null,
|
|
dtend: null,
|
|
description: '',
|
|
timeStart: null,
|
|
timeEnd: null,
|
|
duration: 0,
|
|
combined: '',
|
|
recur: null
|
|
}
|
|
let alarmFlag = false, ws, blockStep
|
|
for (let step = 0; step < block.length; step++) {
|
|
blockStep = block[step];
|
|
if (blockStep.indexOf(segments.recur) >= 0) {
|
|
workBlock.recur = STRING(block[step].split(segments.recur)[1]).collapseWhitespace().s;
|
|
//logger.debug(workBlock.recur);
|
|
}
|
|
|
|
if (blockStep.indexOf(segments.summaryID) >= 0) {
|
|
workBlock.summary = STRING(block[step].split(segments.summaryID)[1]).collapseWhitespace().s;
|
|
}
|
|
if (blockStep.indexOf(segments.meetingStartID) >= 0) {
|
|
ws = STRING(block[step].split(segments.meetingStartID)[1]).collapseWhitespace().s;
|
|
workBlock.dtstart = Date.create(ws);
|
|
}
|
|
if (blockStep.indexOf(segments.meetingEndID) >= 0) {
|
|
ws = STRING(block[step].split(segments.meetingEndID)[1]).collapseWhitespace().s;
|
|
workBlock.dtend = Date.create(ws);
|
|
}
|
|
if (blockStep.indexOf(segments.meetingStartAlt) >= 0) {
|
|
ws = STRING(block[step].split(segments.meetingStartAlt)[1]).collapseWhitespace().s;
|
|
workBlock.dtstart = Date.create(ws);
|
|
}
|
|
if (blockStep.indexOf(segments.meetingEndAlt) >= 0) {
|
|
ws = STRING(block[step].split(segments.meetingEndAlt)[1]).collapseWhitespace().s;
|
|
workBlock.dtend = Date.create(ws);
|
|
}
|
|
|
|
if (blockStep.indexOf(segments.meetingStartAltOther) >= 0) {
|
|
ws = STRING(block[step].split(segments.meetingStartAltOther)[1]).collapseWhitespace().s;
|
|
workBlock.dtstart = Date.create(ws);
|
|
}
|
|
if (blockStep.indexOf(segments.meetingEndAltOther) >= 0) {
|
|
ws = STRING(block[step].split(segments.meetingEndAltOther)[1]).collapseWhitespace().s;
|
|
workBlock.dtend = Date.create(ws);
|
|
}
|
|
|
|
if (blockStep.indexOf(segments.meetingDescID) >= 0) {
|
|
if (!alarmFlag) {
|
|
workBlock.description = STRING(block[step].split(segments.meetingDescID)[1]).collapseWhitespace().s;
|
|
}
|
|
}
|
|
if (blockStep.indexOf(segments.beginAlarm) >= 0) {
|
|
alarmFlag = true;
|
|
}
|
|
}
|
|
|
|
// We have to check recuring stuff before the cron stuff is processed.
|
|
|
|
if (workBlock.recur !== null) {
|
|
|
|
_wb = processRecurrence(workBlock);
|
|
// logger.warn('returning:', _wb);
|
|
if (_wb !== null) {
|
|
if (!Array.isArray(_wb)) {
|
|
workBlock = _wb;
|
|
} else {
|
|
logger.error('We made an array');
|
|
}
|
|
|
|
}
|
|
}
|
|
//logger.debug(workBlock);
|
|
if (workBlock.dtstart !== null) {
|
|
workBlock.timeStart = workBlock.dtstart.format('{24hr}:{mm}:{ss}');
|
|
workBlock.combined = `<em>${workBlock.timeStart}</em> - '`;
|
|
workBlock.long = `<em>${workBlock.dtstart.format('{Weekday}')}, ${workBlock.timeStart}</em> - `;
|
|
}
|
|
workBlock.combined = workBlock.combined + workBlock.summary;
|
|
workBlock.longcombined = workBlock.long + workBlock.summary;
|
|
if (workBlock.dtend !== null) {
|
|
workBlock.timeEnd = workBlock.dtend.format('{24hr}:{mm}:{ss}');
|
|
}
|
|
if (workBlock.dtstart !== null && workBlock.dtend !== null) {
|
|
const elapsedTime = new Elapsed(workBlock.dtstart, workBlock.dtend)
|
|
workBlock.duration = elapsedTime.optimal;
|
|
workBlock.combined = workBlock.combined + ', ' + elapsedTime.optimal;
|
|
workBlock.longcombined = workBlock.longcombined + ', ' + elapsedTime.optimal;
|
|
}
|
|
|
|
return workBlock;
|
|
}
|
|
|
|
const lines = ical.split('\r\n'), l = lines.length
|
|
let counter = 0
|
|
|
|
let alarmed = false
|
|
while (counter < l) {
|
|
if (lines[counter].indexOf(segments.begin) < 0) {
|
|
counter++;
|
|
} else {
|
|
let subcounter = 0
|
|
const subBlock = []
|
|
alarmed = false;
|
|
while (subcounter < 75) {
|
|
if (lines[counter + subcounter].indexOf(segments.end) < 0) {
|
|
|
|
if (lines[counter + subcounter].indexOf(segments.beginAlarm) > -1) {
|
|
alarmed = true;
|
|
}
|
|
if (!alarmed) {
|
|
subBlock.push(lines[counter + subcounter]);
|
|
}
|
|
if (lines[counter + subcounter].indexOf(segments.endAlarm) > -1) {
|
|
alarmed = false;
|
|
}
|
|
|
|
subcounter++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
counter = counter + subcounter;
|
|
const b = processBlock(subBlock)
|
|
if (Array.isArray(b)) {
|
|
logger.error('!returned an array...');
|
|
} else {
|
|
if (b.dtstart !== null) {
|
|
workingBlock.push(b);
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
logger.info('- processICAL');
|
|
// If (workingBlock.dtstart == null) return {};
|
|
|
|
return workingBlock;
|
|
}
|
|
|
|
module.exports = {
|
|
calendars: ['https://calendar.google.com/calendar/ical/martind2000%40gmail.com/private-40cfebc9f7dcfa7fde6b9bf2f0092c93/basic.ics',
|
|
'https://calendar.google.com/calendar/ical/mt5pgdhknvgoc8usfnrso9vkv0%40group.calendar.google.com/private-58876002af9f302a593acfa6fa792dcf/basic.ics',
|
|
'https://www.tripit.com/feed/ical/private/DB96E4BB-94A9BD8F9CC1CF51C6CC0D920840F4F5/tripit.ics',
|
|
'https://calendar.google.com/calendar/ical/en.uk%23holiday%40group.v.calendar.google.com/public/basic.ics',
|
|
'https://calendar.google.com/calendar/ical/i8dglj12p5nuv20sbjmun5s588%40group.calendar.google.com/private-c8adccb41e56d6a2f285078aaed313f5/basic.ics'],
|
|
jsonBlock: [],
|
|
getTodaysSimple: function() {
|
|
'use strict';
|
|
logger.info('+ getTodaysSimple');
|
|
const today = {
|
|
entries: []
|
|
}
|
|
|
|
for (let t = 0; t < this.jsonBlock.length; t++) {
|
|
if (this.jsonBlock[t].dtstart.isToday()) {
|
|
|
|
today.entries.push(this.jsonBlock[t]);
|
|
}
|
|
}
|
|
logger.info('- getTodaysSimple');
|
|
return today;
|
|
},
|
|
getTomorrow: function() {
|
|
'use strict';
|
|
logger.info('+ getTomorrow');
|
|
const today = {
|
|
entries: []
|
|
}
|
|
|
|
for (let t = 0; t < this.jsonBlock.length; t++) {
|
|
if (this.jsonBlock[t].dtstart.isTomorrow()) {
|
|
|
|
today.entries.push(this.jsonBlock[t]);
|
|
}
|
|
}
|
|
logger.info('- getTomorrow');
|
|
return today;
|
|
},
|
|
getWeek: function() {
|
|
'use strict';
|
|
logger.info('+ getWeek');
|
|
const today = {
|
|
entries: []
|
|
}
|
|
let now, twoDays, sevenDays
|
|
|
|
now = Date.create('today');
|
|
// logger.debug(now);
|
|
twoDays = Date.create(now).addDays(2).beginningOfDay();
|
|
// logger.debug(twoDays);
|
|
sevenDays = Date.create(twoDays).addDays(5).beginningOfDay();
|
|
|
|
// logger.debug(now, twoDays, sevenDays);
|
|
|
|
for (let t = 0; t < this.jsonBlock.length; t++) {
|
|
if (this.jsonBlock[t].dtstart.isBetween(twoDays, sevenDays)) {
|
|
|
|
today.entries.push(this.jsonBlock[t]);
|
|
}
|
|
}
|
|
logger.info('- getWeek');
|
|
return today;
|
|
},
|
|
getTodaysMeetings: function() {
|
|
'use strict';
|
|
logger.info('+ getTodaysMeetings');
|
|
const today = {
|
|
previous: [], upcoming: [], current: {}
|
|
}
|
|
const now = new Date()
|
|
|
|
for (let t = 0; t < this.jsonBlock.length; t++) {
|
|
if (this.jsonBlock[t].dtstart.isToday()) {
|
|
|
|
if (this.jsonBlock[t].dtstart.isAfter(now)) {
|
|
today.upcoming.push(this.jsonBlock[t]);
|
|
} else {
|
|
today.previous.push(this.jsonBlock[t]);
|
|
}
|
|
|
|
if (now.isBetween(this.jsonBlock[t].dtstart, this.jsonBlock[t].dtend)) {
|
|
today.current = this.jsonBlock[t];
|
|
}
|
|
}
|
|
}
|
|
// logger.debug(today);
|
|
logger.info('- getTodaysMeetings');
|
|
return today;
|
|
}, getSimpleCalV2: function(url, cb) {
|
|
'use strict';
|
|
const self = this
|
|
|
|
// Var calJson = [];
|
|
try {
|
|
request(url, function(err, res, body) {
|
|
if (err) {
|
|
logger.error('Get remote Calendar Request failed');
|
|
// Callback.call(null, new Error('Request failed'));
|
|
return;
|
|
}
|
|
|
|
self.jsonBlock = processICAL(body);
|
|
|
|
// logger.debug(self.jsonBlock);
|
|
const st = self.getTodaysSimple()
|
|
|
|
if (typeof cb === 'function') {
|
|
cb(st);
|
|
}
|
|
}, function(error, response, body) {
|
|
if (response.statusCode !== 200) {
|
|
logger.error(response.statusCode);
|
|
logger.error(body);
|
|
}
|
|
});
|
|
} catch (e) {
|
|
console.log(e);
|
|
}
|
|
|
|
}, getSimpleCalV3: function(url) {
|
|
'use strict';
|
|
const self = this
|
|
|
|
return new Promise(function(resolve, reject) {
|
|
try {
|
|
request(url, function(err, res, body) {
|
|
if (err) {
|
|
// logger.error(err);
|
|
return reject(err);
|
|
// Throw err;
|
|
}
|
|
|
|
self.jsonBlock = processICAL(body);
|
|
|
|
// logger.debug(self.jsonBlock);
|
|
const st = self.getTodaysSimple()
|
|
|
|
return resolve(st);
|
|
}, function(error, response, body) {
|
|
if (response.statusCode !== 200) {
|
|
logger.error(response.statusCode);
|
|
logger.error(body);
|
|
return reject(error);
|
|
}
|
|
});
|
|
} catch (e) {
|
|
console.log(e);
|
|
return reject(e);
|
|
}
|
|
|
|
});
|
|
|
|
// Var calJson = [];
|
|
|
|
}, getAdvancedCalV3: function(url) {
|
|
'use strict';
|
|
const self = this
|
|
|
|
return new Promise(function(resolve, reject) {
|
|
try {
|
|
request(url, function(err, res, body) {
|
|
if (err) {
|
|
// logger.error(err);
|
|
return reject(err);
|
|
// Throw err;
|
|
}
|
|
|
|
self.jsonBlock = processICAL(body);
|
|
|
|
// logger.debug(self.jsonBlock);
|
|
const st = self.getTodaysSimple().entries
|
|
const tom = self.getTomorrow().entries
|
|
const week = self.getWeek().entries
|
|
|
|
const obj = {today: st, tomorrow: tom, week: week}
|
|
|
|
logger.debug(obj);
|
|
return resolve(obj);
|
|
}, function(error, response, body) {
|
|
if (response.statusCode !== 200) {
|
|
logger.error(response.statusCode);
|
|
logger.error(body);
|
|
return reject(error);
|
|
}
|
|
});
|
|
} catch (e) {
|
|
console.log(e);
|
|
return reject(e);
|
|
}
|
|
|
|
});
|
|
|
|
// Var calJson = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Created by Martin on 16/02/2016.
|
|
*/
|
|
};
|