diff --git a/index.js b/index.js index 9697279..e7c4caa 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,18 @@ - var ChatMessages = function (privateClient, publicClient) { +function pad (num) { + num = String(num); + if (num.length === 1) { num = "0" + num; } + return num; +}; +function parseDate (date) { + return { + year: date.getUTCFullYear(), + month: pad( date.getUTCMonth() + 1 ), + day: pad( date.getUTCDate() ) + }; +}; + +const ChatMessages = function (privateClient, publicClient) { /** * Schema: chat-messages/daily * @@ -139,7 +152,7 @@ * Example for IRC: * * (start code) - * var archive = new chatMessages.DailyArchive({ + * const archive = new chatMessages.DailyArchive({ * server: { * type: 'irc', * name: 'freenode', @@ -154,7 +167,7 @@ * Example for XMPP: * * (start code) - * var archive = new chatMessages.DailyArchive({ + * const archive = new chatMessages.DailyArchive({ * server: { * type: 'xmpp', * name: '5apps', @@ -166,125 +179,125 @@ * }); * (end code) */ - var DailyArchive = function DailyArchive(options) { - // - // Defaults - // - options.isPublic = options.isPublic || false; + class DailyArchive { + constructor (options) { + // + // Defaults + // + options.isPublic = options.isPublic || false; - // - // Validate options - // - if (typeof options !== "object") { - throw "options must be an object"; - } - if (typeof options.server !== "object" || - typeof options.server.type !== "string" || - typeof options.server.name !== "string") { - throw "server must be an object containing at least server \"type\" and \"name\""; - } - if (typeof options.channelName !== "string") { - throw "channelName must be a string"; - } - if (!(options.date instanceof Date)) { - throw "date must be a date object"; - } - if (typeof options.isPublic !== "boolean") { - throw "isPublic must be a boolean value"; + // + // Validate options + // + if (typeof options !== "object") { + throw "options must be an object"; + } + if (typeof options.server !== "object" || + typeof options.server.type !== "string" || + typeof options.server.name !== "string") { + throw "server must be an object containing at least server \"type\" and \"name\""; + } + if (typeof options.channelName !== "string") { + throw "channelName must be a string"; + } + if (!(options.date instanceof Date)) { + throw "date must be a date object"; + } + if (typeof options.isPublic !== "boolean") { + throw "isPublic must be a boolean value"; + } + + /** + * Property: server + * + * Contains information about the chat server/network + * + * Properties: + * type - Type of server/protocol (e.g. "irc", "xmpp", "campfire", "slack") + * name - Shortname/id/alias of network/server (e.g. "freenode", "mycompanyname") + * ircURI - (optional) IRC URI of network (e.g. "irc://irc.freenode.net/") + * xmppMUC - (optional) XMPP MUC service host (e.g. "conference.jabber.org") + */ + this.server = options.server; + + /** + * Property: channelName + * + * Name of the IRC channel (e.g. "#kosmos") + */ + this.channelName = options.channelName; + + /** + * Property: date + * + * Date of the archive's content + */ + this.date = options.date; + + /** + * Property: isPublic + * + * `true` for public archives, `false` for private ones + */ + this.isPublic = options.isPublic; + + /** + * Property: parsedDate + * + * Object containing padded year, month and day of date + */ + this.parsedDate = parseDate(this.date); + + /** + * Property: dateId + * + * Date string in the form of YYYY/MM/DD + */ + this.dateId = this.parsedDate.year+'/'+this.parsedDate.month+'/'+this.parsedDate.day; + + /** + * Property: path + * + * Document path of the archive file + */ + switch (this.server.type) { + case 'irc': + if (this.channelName.match(/^#/)) { + // normal chatroom + const channelName = this.channelName.replace(/^#/,''); + this.path = `${this.server.name}/channels/${channelName}/${this.dateId}`; + } else { + // user direct message + this.path = `${this.server.name}/users/${this.channelName}/${this.dateId}`; + } + break; + default: + this.path = `${this.server.name}/${this.channelName}/${this.dateId}`; + break; + } + + /** + * Property: client + * + * Public or private BaseClient, depending on isPublic + */ + this.client = this.isPublic ? publicClient : privateClient; + + /** + * Property: previous + * + * Date of previous log file as YYYY/MM/DD + */ + this.previous = options.previous; + + /** + * Property: next + * + * Date of next log file as YYYY/MM/DD + */ + this.next = options.next; } - /** - * Property: server - * - * Contains information about the chat server/network - * - * Properties: - * type - Type of server/protocol (e.g. "irc", "xmpp", "campfire", "slack") - * name - Shortname/id/alias of network/server (e.g. "freenode", "mycompanyname") - * ircURI - (optional) IRC URI of network (e.g. "irc://irc.freenode.net/") - * xmppMUC - (optional) XMPP MUC service host (e.g. "conference.jabber.org") - */ - this.server = options.server; - - /** - * Property: channelName - * - * Name of the IRC channel (e.g. "#kosmos") - */ - this.channelName = options.channelName; - - /** - * Property: date - * - * Date of the archive's content - */ - this.date = options.date; - - /** - * Property: isPublic - * - * `true` for public archives, `false` for private ones - */ - this.isPublic = options.isPublic; - - /** - * Property: parsedDate - * - * Object containing padded year, month and day of date - */ - this.parsedDate = parseDate(this.date); - - /** - * Property: dateId - * - * Date string in the form of YYYY/MM/DD - */ - this.dateId = this.parsedDate.year+'/'+this.parsedDate.month+'/'+this.parsedDate.day; - - /** - * Property: path - * - * Document path of the archive file - */ - switch (this.server.type) { - case 'irc': - if (this.channelName.match(/^#/)) { - // normal chatroom - var channelName = this.channelName.replace(/^#/,''); - this.path = `${this.server.name}/channels/${channelName}/${this.dateId}`; - } else { - // user direct message - this.path = `${this.server.name}/users/${this.channelName}/${this.dateId}`; - } - break; - default: - this.path = `${this.server.name}/${this.channelName}/${this.dateId}`; - break; - } - - /** - * Property: client - * - * Public or private BaseClient, depending on isPublic - */ - this.client = this.isPublic ? publicClient : privateClient; - - /** - * Property: previous - * - * Date of previous log file as YYYY/MM/DD - */ - this.previous = options.previous; - - /** - * Property: next - * - * Date of next log file as YYYY/MM/DD - */ - this.next = options.next; - }; - - DailyArchive.prototype = { /* * Method: addMessage * @@ -294,7 +307,7 @@ * text - The message itself * type - Type of message (one of text, join, leave, action) */ - addMessage: function addMessage(message) { + addMessage (message) { if (this.isPublic && !this.channelName.match(/^#/)) { return Promise.resolve(false); } @@ -308,7 +321,7 @@ return this._createDocument(message); } }); - }, + } /* * Method: addMessages @@ -321,7 +334,7 @@ * overwrite - If true, creates a new archive file and overwrites the * old one. Defaults to false. */ - addMessages: function addMessage(messages, overwrite) { + addMessages (messages, overwrite) { if (this.isPublic && !this.channelName.match(/^#/)) { return Promise.resolve(false); } @@ -343,23 +356,23 @@ } }); } - }, + } /* * Method: remove * * Deletes the entire archive document from storage */ - remove: function() { + remove () { return this.client.remove(this.path); - }, + } /* * Method: _updateDocument * * Updates and writes an existing archive document */ - _updateDocument: function(archive, messages) { + _updateDocument (archive, messages) { console.debug('[chat-messages] Updating archive document', archive); if (Array.isArray(messages)) { @@ -371,16 +384,16 @@ } return this._sync(archive); - }, + } /* * Method: _createDocument * * Creates and writes a new archive document */ - _createDocument: function(messages) { + _createDocument (messages) { console.debug('[chat-messages] Creating new archive document'); - let archive = this._buildArchiveObject(); + const archive = this._buildArchiveObject(); if (Array.isArray(messages)) { messages.forEach((message) => { @@ -405,17 +418,17 @@ return this._sync(archive); }); } - }, + } /* * Method: _buildArchiveObject * * Builds the object to be stored in remote storage */ - _buildArchiveObject: function() { - let roomName = this.channelName.replace(/#/,''); + _buildArchiveObject () { + const roomName = this.channelName.replace(/#/,''); - let archive = { + const archive = { "@id": "chat-messages/"+this.server.name+"/channels/"+roomName+"/", "@type": "ChatChannel", "name": this.channelName, @@ -440,18 +453,18 @@ } return archive; - }, + } /* * Method: _updatePreviousArchive * * Finds the previous archive document and updates its today.next value */ - _updatePreviousArchive: function() { + _updatePreviousArchive () { return this._findPreviousArchive().then((archive) => { if (typeof archive === 'object' && archive.today) { archive.today.next = this.dateId; - let path = this.path.substring(0, this.path.length-this.dateId.length)+archive.today['@id']; + const path = this.path.substring(0, this.path.length-this.dateId.length)+archive.today['@id']; return this.client.storeObject('daily-archive', path, archive).then(() => { console.debug('[chat-messages] Previous archive written to remote storage', path, archive); @@ -462,60 +475,60 @@ return false; } }); - }, + } /* * Method: _findPreviousArchive * * Returns the previous archive document */ - _findPreviousArchive: function() { + _findPreviousArchive () { const monthPath = this.path.substring(0, this.path.length-2); const yearPath = this.path.substring(0, this.path.length-5); const basePath = this.path.substring(0, this.path.length-10); return this.client.getListing(monthPath).then((listing) => { - let days = Object.keys(listing).map((i) => parseInt(i)).map((i) => { + const days = Object.keys(listing).map((i) => parseInt(i)).map((i) => { return (i < parseInt(this.parsedDate.day)) ? i : null; }).filter(function(i){ return i != null; }); if (days.length > 0) { - let day = pad(Math.max(...days).toString()); + const day = pad(Math.max(...days).toString()); return this.client.getObject(monthPath+day); } // Find last day in previous month return this.client.getListing(yearPath).then((listing) => { - let months = Object.keys(listing).map((i) => parseInt(i.substr(0,2))).map((i) => { + const months = Object.keys(listing).map((i) => parseInt(i.substr(0,2))).map((i) => { return (i < parseInt(this.parsedDate.month)) ? i : null; }).filter(function(i){ return i != null; }); if (months.length > 0) { - let month = pad(Math.max(...months).toString()); + const month = pad(Math.max(...months).toString()); return this.client.getListing(yearPath+month+'/').then((listing) => { - let days = Object.keys(listing).map((i) => parseInt(i)); - let day = pad(Math.max(...days).toString()); + const days = Object.keys(listing).map((i) => parseInt(i)); + const day = pad(Math.max(...days).toString()); return this.client.getObject(yearPath+month+'/'+day); }); } else { // Find last month and day in previous year return this.client.getListing(basePath).then((listing) => { - let years = Object.keys(listing).map((i) => parseInt(i.substr(0,4))).map((i) => { + const years = Object.keys(listing).map((i) => parseInt(i.substr(0,4))).map((i) => { return (i < parseInt(this.parsedDate.year)) ? i : null; }).filter(function(i){ return i != null; }); if (years.length > 0) { - let year = Math.max(...years).toString(); + const year = Math.max(...years).toString(); return this.client.getListing(basePath+year+'/').then((listing) => { - let months = Object.keys(listing).map((i) => parseInt(i.substr(0,2))); - let month = pad(Math.max(...months).toString()); + const months = Object.keys(listing).map((i) => parseInt(i.substr(0,2))); + const month = pad(Math.max(...months).toString()); return this.client.getListing(basePath+year+'/'+month+'/').then((listing) => { - let days = Object.keys(listing).map((i) => parseInt(i)); - let day = pad(Math.max(...days).toString()); + const days = Object.keys(listing).map((i) => parseInt(i)); + const day = pad(Math.max(...days).toString()); return this.client.getObject(basePath+year+'/'+month+'/'+day); }); }); @@ -526,14 +539,14 @@ } }); }); - }, + } /* * Method: _sync * * Write archive document */ - _sync: function(obj) { + _sync (obj) { console.debug('[chat-messages] Writing archive object', obj); return this.client.storeObject('daily-archive', this.path, obj).then(function(){ @@ -546,29 +559,13 @@ } }; - var pad = function(num) { - num = String(num); - if (num.length === 1) { num = "0" + num; } - return num; + return { + exports: { + DailyArchive, + privateClient, + publicClient + } }; - - var parseDate = function(date) { - return { - year: date.getUTCFullYear(), - month: pad( date.getUTCMonth() + 1 ), - day: pad( date.getUTCDate() ) - }; - }; - - var exports = { - DailyArchive: DailyArchive, - privateClient: privateClient, - publicClient: publicClient - }; - - // Return public functions - return { exports: exports }; - }; export default { name: 'chat-messages', builder: ChatMessages };