Author SHA1 Message Date
basti dcf117e1dd Add a couple of message properties 2022-01-04 13:34:30 -06:00
basti a0bec9a12c WIP Introduce Channel class
This is a breaking change, introducing a new Channel class to hold the
channel meta information, and functions to open either the last
DailyArchive, or one for a specified date.
2022-01-04 13:13:21 -06:00
basti 189cd1f86d 2.1.0 2021-11-13 21:59:53 +01:00
basti 8db448c4a0 Make log less verbose 2021-11-13 21:59:34 +01:00
raucao 84613ed3a3 Merge pull request 'Add/store channel archive metadata document' (#8) from feature/7-archive_metadata into master
Reviewed-on: #8
2021-11-13 20:56:18 +00:00
bastiandgalfert f83ef92adc Remove superfluous sort function
#8 (comment)

Co-authored-by: Garret Alfert <alfert@wevelop.de>
2021-11-13 21:53:56 +01:00
basti 54352e09e8 Store meta document with first/last archive ID 2021-11-08 12:55:42 +01:00
basti cd93cd4167 Add archive metadata schema, RS type 2021-11-04 13:18:55 +01:00
basti 9f477ba14b Update badge link 2021-09-13 14:31:04 +02:00
basti 328be7ed75 2.0.0 2021-09-13 14:08:10 +02:00
raucao cf8c43bede Merge pull request 'Add proper README' (#6) from docs/readme into master
Reviewed-on: #6
2021-09-13 12:06:56 +00:00
basti 188b45e778 Add proper README
* Document usage
* Update communication options for support/issues
2021-09-13 14:03:41 +02:00
raucao d331af7256 Merge pull request 'Various pre-release fixes' (#5) from dev/prerelease_fixes into master
Reviewed-on: #5
2021-09-13 11:43:27 +00:00
basti 9ba618f38e Update repo URL, add website 2021-09-13 13:40:24 +02:00
basti 0b517400b1 Remove noise from logs 2021-09-13 13:18:25 +02:00
basti 15af899e1d Document isPublic argument as optional 2021-09-13 13:17:51 +02:00
basti bf896a076c Update context version 2021-09-13 13:17:32 +02:00
basti a5a547d40d Fix build config to work with node.js 2021-09-13 13:16:40 +02:00
raucao 21cb5a02c8 Merge pull request 'Update data model, documentation' (#4) from feature/2-update_data_model into master
Reviewed-on: #4
2021-09-10 12:34:40 +00:00
basti c42e0a37a8 Update build 2021-09-05 15:59:10 +02:00
raucao 2a73816e56 Merge branch 'master' into feature/2-update_data_model 2021-09-05 13:58:28 +00:00
raucao 74680ad42b Merge pull request 'Update JS syntax' (#3) from chore/modern_js into master
Reviewed-on: #3
2021-09-05 13:57:09 +00:00
basti dd1bfd08ea Update data model, documentation
* Port NaturalDocs code documentation to JSDoc
* server --> service,
  server.name --> service.domain,
  server.type --> service.protocol
* Remove ircURI and xmppURI in favor of service.protocol
* Add channel type ("room" or "person")
* Change document path to use service domain instead of custom id/name
2021-09-05 15:56:17 +02:00
basti e803a1e799 Move source to src directory 2021-09-05 14:05:06 +02:00
basti 54f5d903d0 Update JS syntax 2021-09-04 14:11:37 +02:00
raucao a270d5f9d6 Merge pull request 'Update development environment (Webpack)' (#1) from chore/update_dev_env into master
Reviewed-on: #1
2021-09-04 11:46:25 +00:00
basti 603fd507bf Update development environment (Webpack) 2021-09-04 13:45:15 +02:00
basti 6b95652a76 Update package meta 2021-09-04 12:57:47 +02:00
basti 89c4ee229a 1.0.1 2017-10-24 17:04:21 +02:00
basti 990b081b3d Use standard logger instead of RS.log 2017-10-24 17:03:54 +02:00
basti 4ce2b90351 1.0.0 2017-10-24 16:51:45 +02:00
basti 2a22d0f399 Update to new RS module API 2017-10-24 16:51:37 +02:00
8 changed files with 3427 additions and 623 deletions

No files matched your search

+30 -12
View File
@@ -1,22 +1,40 @@
[![Release](https://img.shields.io/npm/v/remotestorage-module-chat-messages.svg?style=flat)](https://github.com/67P/remotestorage-module-chat-messages/releases)
[![Release](https://img.shields.io/npm/v/remotestorage-module-chat-messages.svg?style=flat)](https://www.npmjs.com/package/remotestorage-module-chat-messages)
# remoteStorage Module: Chat Messages
Stores chat messages in daily archive documents.
Please feel free to open GitHub issues for questions, feature requests,
protocol proposals, and whatever else you like.
## Usage
## Protocols
Open a daily archive and write messages to it:
### Currently supported
```js
const RemoteStorage = require("remotestoragejs");
const ChatMessages = require("remotestorage-module-chat-messages");
const remoteStorage = new RemoteStorage({ modules: [ ChatMessages ] });
* IRC
* XMPP
const archive = new remoteStorage.chatMessages.DailyArchive({
service: {
protocol: 'IRC',
domain: 'irc.libera.chat'
},
channelName: '#kosmos',
date: new Date(),
isPublic: true // Channel logs will be written to public folder
});
### Planned
const messages = [
{ "date": "2015-06-05T17:35:28.454Z", "user": "jimmy", "text": "knock knock" },
{ "date": "2015-06-05T17:36:05.123Z", "user": "walter", "text": "who's there?" }
];
* Mattermost
* Matrix
* Slack
* ...
archive.addMessages(messages);
```
See the inline source code documentation (JSDoc) for usage details and function
arguments. For a real-world integration example, see
[hubot-remotestorage-logger](https://github.com/67P/hubot-remotestorage-logger/).
## Support, bugs, feedback, questions
Come and chat with us: https://wiki.kosmos.org/Main_Page#Chat
+2 -1
View File
@@ -1 +1,2 @@
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("remotestoragejs"));else if("function"==typeof define&&define.amd)define(["remotestoragejs"],e);else{var n=e("object"==typeof exports?require("remotestoragejs"):t.RemoteStorage);for(var r in n)("object"==typeof exports?exports:t)[r]=n[r]}}(this,function(t){return function(t){function e(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return t[r].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";function r(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e<t.length;e++)n[e]=t[e];return n}return Array.from(t)}var i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},s=n(1);s.defineModule("chat-messages",function(t,e){var n={type:"object",properties:{"@context":{type:"string",default:"https://kosmos.org/ns/v1",enum:["https://kosmos.org/ns/v1"]},"@id":{type:"string",required:!0},"@type":{type:"string",default:"ChatChannel",enum:["ChatChannel"]},name:{type:"string",required:!0},ircURI:{type:"string",format:"uri"},xmppURI:{type:"string",format:"uri"},today:{type:"object",properties:{"@id":{type:"string",pattern:"^[0-9]{4}/[0-9]{2}/[0-9]{2}$",required:!0},"@type":{type:"string",default:"ChatLog",pattern:"^ChatLog$"},messageType:{type:"string",default:"InstantMessage",pattern:"^InstantMessage$"},previous:{type:"string",pattern:"^[0-9]{4}/[0-9]{2}/[0-9]{2}$"},next:{type:"string",pattern:"^[0-9]{4}/[0-9]{2}/[0-9]{2}$"},messages:{type:"array",required:!0,items:{type:"object",properties:{date:{type:"string",format:"date-time"},user:{type:"string"},text:{type:"string"},type:"string",default:"text",enum:["text","join","leave","action"]}}}}}},required:[]};t.declareType("daily-archive","https://kosmos.org/ns/v1",n),e.declareType("daily-archive","https://kosmos.org/ns/v1",n);var a=function(n){if(n.isPublic=n.isPublic||!1,"object"!==("undefined"==typeof n?"undefined":i(n)))throw"options must be an object";if("object"!==i(n.server)||"string"!=typeof n.server.type||"string"!=typeof n.server.name)throw'server must be an object containing at least server "type" and "name"';if("string"!=typeof n.channelName)throw"channelName must be a string";if(!(n.date instanceof Date))throw"date must be a date object";if("boolean"!=typeof n.isPublic)throw"isPublic must be a boolean value";switch(this.server=n.server,this.channelName=n.channelName,this.date=n.date,this.isPublic=n.isPublic,this.parsedDate=h(this.date),this.dateId=this.parsedDate.year+"/"+this.parsedDate.month+"/"+this.parsedDate.day,this.server.type){case"irc":if(this.channelName.match(/^#/)){var r=this.channelName.replace(/^#/,"");this.path=this.server.name+"/channels/"+r+"/"+this.dateId}else this.path=this.server.name+"/users/"+this.channelName+"/"+this.dateId;break;default:this.path=this.server.name+"/"+this.channelName+"/"+this.dateId}this.client=this.isPublic?e:t,this.previous=n.previous,this.next=n.next};a.prototype={addMessage:function(t){var e=this;return this.isPublic&&!this.channelName.match(/^#/)?Promise.resolve(!1):(t.type=t.type||"text",this.client.getObject(this.path).then(function(n){return"object"===("undefined"==typeof n?"undefined":i(n))?e._updateDocument(n,t):e._createDocument(t)}))},addMessages:function(t,e){var n=this;return this.isPublic&&!this.channelName.match(/^#/)?Promise.resolve(!1):(e=e||!1,t.forEach(function(t){t.type=t.type||"text"}),e?this._createDocument(t):this.client.getObject(this.path).then(function(e){return"object"===("undefined"==typeof e?"undefined":i(e))?n._updateDocument(e,t):n._createDocument(t)}))},remove:function(){return this.client.remove(this.path)},_updateDocument:function(t,e){return s.log("[chat-messages] Updating archive document",t),Array.isArray(e)?e.forEach(function(e){t.today.messages.push(e)}):t.today.messages.push(e),this._sync(t)},_createDocument:function(t){var e=this;s.log("[chat-messages] Creating new archive document");var n=this._buildArchiveObject();return Array.isArray(t)?t.forEach(function(t){n.today.messages.push(t)}):n.today.messages.push(t),this.previous||this.next?(this.previous&&(n.today.previous=this.previous),this.next&&(n.today.next=this.next),this._sync(n)):this._updatePreviousArchive().then(function(t){return"object"===("undefined"==typeof t?"undefined":i(t))&&(n.today.previous=t.today["@id"]),e._sync(n)})},_buildArchiveObject:function(){var t=this.channelName.replace(/#/,""),e={"@id":"chat-messages/"+this.server.name+"/channels/"+t+"/","@type":"ChatChannel",name:this.channelName,today:{"@id":this.dateId,"@type":"ChatLog",messageType:"InstantMessage",messages:[]}};switch(this.server.type){case"irc":this.channelName.match(/^#/)||(e["@id"]="chat-messages/"+this.server.name+"/users/"+this.channelName+"/"),e.ircURI=this.server.ircURI+"/"+t;break;case"xmpp":e.xmppURI="xmpLine truncated
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("ChatMessages",[],e):"object"==typeof exports?exports.ChatMessages=e():t.ChatMessages=e()}(this,(function(){return(()=>{var t={666:t=>{var e=function(t){"use strict";var e,r=Object.prototype,n=r.hasOwnProperty,a="function"==typeof Symbol?Symbol:{},i=a.iterator||"@@iterator",o=a.asyncIterator||"@@asyncIterator",s=a.toStringTag||"@@toStringTag";function c(t,e,r){return Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{c({},"")}catch(t){c=function(t,e,r){return t[e]=r}}function u(t,e,r,n){var a=e&&e.prototype instanceof d?e:d,i=Object.create(a.prototype),o=new M(n||[]);return i._invoke=function(t,e,r){var n=l;return function(a,i){if(n===f)throw new Error("Generator is already running");if(n===y){if("throw"===a)throw i;return E()}for(r.method=a,r.arg=i;;){var o=r.delegate;if(o){var s=P(o,r);if(s){if(s===m)continue;return s}}if("next"===r.method)r.sent=r._sent=r.arg;else if("throw"===r.method){if(n===l)throw n=y,r.arg;r.dispatchException(r.arg)}else"return"===r.method&&r.abrupt("return",r.arg);n=f;var c=h(t,e,r);if("normal"===c.type){if(n=r.done?y:p,c.arg===m)continue;return{value:c.arg,done:r.done}}"throw"===c.type&&(n=y,r.method="throw",r.arg=c.arg)}}}(t,r,o),i}function h(t,e,r){try{return{type:"normal",arg:t.call(e,r)}}catch(t){return{type:"throw",arg:t}}}t.wrap=u;var l="suspendedStart",p="suspendedYield",f="executing",y="completed",m={};function d(){}function g(){}function v(){}var b={};c(b,i,(function(){return this}));var w=Object.getPrototypeOf,x=w&&w(w(C([])));x&&x!==r&&n.call(x,i)&&(b=x);var j=v.prototype=d.prototype=Object.create(b);function k(t){["next","throw","return"].forEach((function(e){c(t,e,(function(t){return this._invoke(e,t)}))}))}function L(t,e){function r(a,i,o,s){var c=h(t[a],t,i);if("throw"!==c.type){var u=c.arg,l=u.value;return l&&"object"==typeof l&&n.call(l,"__await")?e.resolve(l.__await).then((function(t){r("next",t,o,s)}),(function(t){r("throw",t,o,s)})):e.resolve(l).then((function(t){u.value=t,o(u)}),(function(t){return r("throw",t,o,s)}))}s(c.arg)}var a;this._invoke=function(t,n){function i(){return new e((function(e,a){r(t,n,e,a)}))}return a=a?a.then(i,i):i()}}function P(t,r){var n=t.iterator[r.method];if(n===e){if(r.delegate=null,"throw"===r.method){if(t.iterator.return&&(r.method="return",r.arg=e,P(t,r),"throw"===r.method))return m;r.method="throw",r.arg=new TypeError("The iterator does not provide a 'throw' method")}return m}var a=h(n,t.iterator,r.arg);if("throw"===a.type)return r.method="throw",r.arg=a.arg,r.delegate=null,m;var i=a.arg;return i?i.done?(r[t.resultName]=i.value,r.next=t.nextLoc,"return"!==r.method&&(r.method="next",r.arg=e),r.delegate=null,m):i:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,m)}function _(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function O(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function M(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(_,this),this.reset(!0)}function C(t){if(t){var r=t[i];if(r)return r.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var a=-1,o=function r(){for(;++a<t.length;)if(n.call(t,a))return r.value=t[a],r.done=!1,r;return r.value=e,r.done=!0,r};return o.next=o}}return{next:E}}function E(){return{value:e,done:!0}}return g.prototype=v,c(j,"constructor",v),c(v,"constructor",g),g.displayName=c(v,s,"GeneratorFunction"),t.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===g||"GeneratorFunction"===(e.displayName||e.name))},t.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,v):(t.__proto__=v,c(t,s,"GeneratorFunction")),t.prototype=Object.create(j),t},t.awrap=function(t){return{__await:t}},k(L.prototype),c(L.prototype,o,(function(){return this})),t.AsyncIterator=L,t.async=function(e,r,n,a,i){void 0===i&&(i=Promise);var o=new L(u(e,r,n,a),i);return t.isGeneratorFunction(r)?o:o.next().then((function(t){return t.done?t.value:o.next()}))},k(j),c(j,s,"Generator"),c(j,i,(function(){return this})),c(j,"toString",(function(){return"[object Generator]"})),t.keys=function(t){var e=[];for(var r in t)e.push(r);return e.reverse(),function r(){for(;e.length;){var n=e.pop();if(n in t)return r.value=n,r.done=!1,r}return r.done=!0,r}},t.values=C,M.prototype={constructor:M,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=e,this.done=!1,this.delegate=null,this.method="next",this.arg=e,this.tryEntries.forEach(O),!t)for(var r in this)"t"===r.charAt(0)&&n.call(this,r)&&!isNaN(+r.slice(1))&&(this[r]=e)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var r=this;function a(n,a){return s.type="throw",s.arg=t,r.next=n,a&&(r.method="next"Line truncated
//# sourceMappingURL=build.js.map
+1 -1
View File
@@ -1 +1 @@
{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap fea08dbeb235bc9f8782","webpack:///./index.js","webpack:///external {\"root\":\"RemoteStorage\",\"commonjs2\":\"remotestoragejs\",\"commonjs\":\"remotestoragejs\",\"amd\":\"remotestoragejs\"}"],"names":["RemoteStorage","require","defineModule","privateClient","publicClient","archiveSchema","declareType","DailyArchive","options","isPublic","server","type","name","channelName","date","Date","parsedDate","parseDate","dateId","year","month","day","match","replace","path","client","previous","next","prototype","addMessage","message","Promise","resolve","getObject","then","archive","_updateDocument","_createDocument","addMessages","messages","overwrite","forEach","remove","log","Array","isArray","today","push","_sync","_buildArchiveObject","_updatePreviousArchive","roomName","ircURI","xmppMUC","_findPreviousArchive","substring","length","storeObject","monthPath","yearPath","basePath","getListing","listing","days","Object","keys","map","i","parseInt","filter","pad","Math","max","toString","months","substr","years","obj","error","console","num","String","getUTCFullYear","getUTCMonth","getUTCDate","exports"],"mappings":"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 truncated
{"version":3,"file":"build.js","mappings":"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 truncated
-573
View File
@@ -1,573 +0,0 @@
var RemoteStorage = require('remotestoragejs');
RemoteStorage.defineModule("chat-messages", function (privateClient, publicClient) {
/**
* Schema: chat-messages/daily
*
* Represents one day of chat messages
*
* Example:
*
* (start code)
* {
* "@context": "https://kosmos.org/ns/v1",
* "@id": "chat-messages/freenode/channels/kosmos/",
* "@type": "ChatChannel",
* "name": "#kosmos",
* "ircURI": "irc://irc.freenode.net/kosmos",
* "today": {
* "@id": "2015/01/01",
* "@type": "ChatLog",
* "messageType": "InstantMessage",
* "previous": "2014/12/31",
* "next": "2015/01/02",
* "messages": [
* { "date": "2015-06-05T17:35:28.454Z", "user": "hal8000", "text": "knock knock" },
* { "date": "2015-06-05T17:37:42.123Z", "user": "raucao", "text": "who's there?" },
* { "date": "2015-06-05T17:55:01.235Z", "user": "hal8000", "text": "HAL" }
* ]
* }
* }
* (end code)
*/
const archiveSchema = {
"type": "object",
"properties": {
"@context": {
"type": "string",
"default": "https://kosmos.org/ns/v1",
"enum": ["https://kosmos.org/ns/v1"]
},
"@id": {
"type": "string",
"required": true
},
"@type": {
"type": "string",
"default": "ChatChannel",
"enum": ["ChatChannel"]
},
"name": {
"type": "string",
"required": true
},
"ircURI": {
"type": "string",
"format": "uri"
},
"xmppURI": {
"type": "string",
"format": "uri"
},
"today": {
"type": "object",
"properties": {
"@id": {
"type": "string",
"pattern": "^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$",
"required": true
},
"@type": {
"type": "string",
"default": "ChatLog",
"pattern": "^ChatLog$"
},
"messageType": {
"type": "string",
"default": "InstantMessage",
"pattern": "^InstantMessage$"
},
"previous": {
"type": "string",
"pattern": "^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$"
},
"next": {
"type": "string",
"pattern": "^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$"
},
"messages": {
"type": "array",
"required": true,
"items": {
"type": "object",
"properties": {
"date": {
"type": "string",
"format": "date-time"
},
"user": {
"type": "string"
},
"text": {
"type": "string"
},
"type": "string",
"default": "text",
"enum": [
"text",
"join",
"leave",
"action"
]
}
}
}
}
}
},
"required": []
};
privateClient.declareType("daily-archive", "https://kosmos.org/ns/v1", archiveSchema);
publicClient.declareType("daily-archive", "https://kosmos.org/ns/v1", archiveSchema);
/**
* Class: DailyArchive
*
* A daily archive stores IRC messages by day.
*
* Parameters (object):
* server - Chat server info (see <DailyArchive.server>)
* channelName - Name of room/channel
* date - Date of archive day
* isPublic - Store logs in public folder (defaults to false)
* previous - Date of previous log file as YYYY/MM/DD;
* looked up automatically when not given
* next - Date of next log file as YYYY/MM/DD;
* looked up automatically when not given
*
* Example for IRC:
*
* (start code)
* var archive = new chatMessages.DailyArchive({
* server: {
* type: 'irc',
* name: 'freenode',
* ircURI: 'irc://irc.freenode.net'
* },
* channelName: '#kosmos',
* date: new Date(),
* isPublic: true
* });
* (end code)
*
* Example for XMPP:
*
* (start code)
* var archive = new chatMessages.DailyArchive({
* server: {
* type: 'xmpp',
* name: '5apps',
* xmppMUC: 'muc.5apps.com'
* },
* channelName: 'watercooler',
* date: new Date(),
* isPublic: false
* });
* (end code)
*/
var DailyArchive = function DailyArchive(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";
}
/**
* 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
*
* Parameters (object):
* timestamp - Timestamp of the message
* from - The sender of the message
* text - The message itself
* type - Type of message (one of text, join, leave, action)
*/
addMessage: function addMessage(message) {
if (this.isPublic && !this.channelName.match(/^#/)) {
return Promise.resolve(false);
}
message.type = message.type || 'text';
return this.client.getObject(this.path).then((archive) => {
if (typeof archive === 'object') {
return this._updateDocument(archive, message);
} else {
return this._createDocument(message);
}
});
},
/*
* Method: addMessages
*
* Like <addMessage>, but for multiple messages at once. Useful for bulk
* imports of messages.
*
* Parameters:
* messages - Array of message objects (see params for addMessage)
* overwrite - If true, creates a new archive file and overwrites the
* old one. Defaults to false.
*/
addMessages: function addMessage(messages, overwrite) {
if (this.isPublic && !this.channelName.match(/^#/)) {
return Promise.resolve(false);
}
overwrite = overwrite || false;
messages.forEach(function(message) {
message.type = message.type || 'text';
});
if (overwrite) {
return this._createDocument(messages);
} else {
return this.client.getObject(this.path).then((archive) => {
if (typeof archive === 'object') {
return this._updateDocument(archive, messages);
} else {
return this._createDocument(messages);
}
});
}
},
/*
* Method: remove
*
* Deletes the entire archive document from storage
*/
remove: function() {
return this.client.remove(this.path);
},
/*
* Method: _updateDocument
*
* Updates and writes an existing archive document
*/
_updateDocument: function(archive, messages) {
RemoteStorage.log('[chat-messages] Updating archive document', archive);
if (Array.isArray(messages)) {
messages.forEach(function(message) {
archive.today.messages.push(message);
});
} else {
archive.today.messages.push(messages);
}
return this._sync(archive);
},
/*
* Method: _createDocument
*
* Creates and writes a new archive document
*/
_createDocument: function(messages) {
RemoteStorage.log('[chat-messages] Creating new archive document');
let archive = this._buildArchiveObject();
if (Array.isArray(messages)) {
messages.forEach((message) => {
archive.today.messages.push(message);
});
} else {
archive.today.messages.push(messages);
}
if (this.previous || this.next) {
// The app is handling previous/next keys itself
// That includes setting 'next' in the previous log file
if (this.previous) { archive.today.previous = this.previous; }
if (this.next) { archive.today.next = this.next; }
return this._sync(archive);
} else {
// Find and update previous archive, set 'previous' on this one
return this._updatePreviousArchive().then((previous) => {
if (typeof previous === 'object') {
archive.today.previous = previous.today['@id'];
}
return this._sync(archive);
});
}
},
/*
* Method: _buildArchiveObject
*
* Builds the object to be stored in remote storage
*/
_buildArchiveObject: function() {
let roomName = this.channelName.replace(/#/,'');
let archive = {
"@id": "chat-messages/"+this.server.name+"/channels/"+roomName+"/",
"@type": "ChatChannel",
"name": this.channelName,
"today": {
"@id": this.dateId,
"@type": "ChatLog",
"messageType": "InstantMessage",
"messages": []
}
};
switch (this.server.type) {
case 'irc':
if (!this.channelName.match(/^#/)) {
archive["@id"] = "chat-messages/"+this.server.name+"/users/"+this.channelName+"/";
}
archive["ircURI"] = this.server.ircURI+"/"+roomName;
break;
case 'xmpp':
archive["xmppURI"] = `xmpp:${this.channelName}@${this.server.xmppMUC}`;
break;
}
return archive;
},
/*
* Method: _updatePreviousArchive
*
* Finds the previous archive document and updates its today.next value
*/
_updatePreviousArchive: function() {
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'];
return this.client.storeObject('daily-archive', path, archive).then(() => {
RemoteStorage.log('[chat-messages] Previous archive written to remote storage', path, archive);
return archive;
});
} else {
RemoteStorage.log('[chat-messages] Previous archive not found');
return false;
}
});
},
/*
* Method: _findPreviousArchive
*
* Returns the previous archive document
*/
_findPreviousArchive: function() {
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) => {
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());
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) => {
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());
return this.client.getListing(yearPath+month+'/').then((listing) => {
let days = Object.keys(listing).map((i) => parseInt(i));
let 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) => {
return (i < parseInt(this.parsedDate.year)) ? i : null;
}).filter(function(i){ return i != null; });
if (years.length > 0) {
let 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());
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());
return this.client.getObject(basePath+year+'/'+month+'/'+day);
});
});
} else {
return false;
}
});
}
});
});
},
/*
* Method: _sync
*
* Write archive document
*/
_sync: function(obj) {
RemoteStorage.log('[chat-messages] Writing archive object', obj);
return this.client.storeObject('daily-archive', this.path, obj).then(function(){
RemoteStorage.log('[chat-messages] Archive written to remote storage');
return true;
},function(error){
console.log('[chat-messages] Error trying to store object', error);
return error;
});
}
};
var pad = function(num) {
num = String(num);
if (num.length === 1) { num = "0" + num; }
return num;
};
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 };
});
+2571
View File
File diff suppressed because it is too large. Load diff
+14 -12
View File
@@ -1,26 +1,28 @@
{
"name": "remotestorage-module-chat-messages",
"version": "0.8.0",
"version": "2.1.0",
"description": "Stores chat messages in daily archive files",
"main": "./dist/build.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "NODE_ENV=production webpack",
"dev": "webpack -w",
"build": "NODE_ENV=production webpack"
"start": "npm run dev",
"test": "echo \"Error: no test specified\" && exit 1",
"version": "npm run build && git add dist/"
},
"author": "Kosmos Developers <mail@kosmos.org> (https://kosmos.org)",
"contributors": [
"Sebastian Kippe <sebastian@kip.pe>"
],
"author": "Kosmos Contributors <mail@kosmos.org> (https://kosmos.org)",
"license": "MIT",
"homepage": "https://gitea.kosmos.org/kosmos/rs-module-chat-messages",
"repository": {
"type": "git",
"url": "https://github.com/67P/remotestorage-module-chat-messages.git"
"url": "https://gitea.kosmos.org/kosmos/rs-module-chat-messages.git"
},
"devDependencies": {
"babel-core": "^6.18.2",
"babel-loader": "^6.2.7",
"babel-preset-es2015": "^6.18.0",
"webpack": "^1.13.2"
"@babel/core": "^7.14.8",
"@babel/preset-env": "^7.14.9",
"babel-loader": "^8.2.2",
"webpack": "^5.48.0",
"webpack-cli": "^4.8.0",
"regenerator-runtime": "^0.13.9"
}
}
+784
View File
@@ -0,0 +1,784 @@
import 'regenerator-runtime/runtime';
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() )
};
};
function lowestNumberInListing(items) {
const sortedNumbers = Object.keys(items)
.map(i => parseInt(i))
.filter(i => !Number.isNaN(i))
.sort();
return sortedNumbers[0];
}
const ChatMessages = function (privateClient, publicClient) {
/**
* Schema: chat-messages/daily-archive
*
* Represents one calendar day of chat messages
*
* @example
* {
* "@context": "https://kosmos.org/ns/v2",
* "@id": "chat-messages/irc.libera.chat/channels/kosmos/",
* "@type": "ChatChannel",
* "service": {
* "domain": "irc.libera.chat",
* "protocol": "IRC",
* },
* "name": "#kosmos",
* "type": "room",
* "today": {
* "@id": "2015/01/01",
* "@type": "ChatLog",
* "messageType": "InstantMessage",
* "previous": "2014/12/31",
* "next": "2015/01/02",
* "messages": [
* { "date": "2015-06-05T17:35:28.454Z", "user": "hal8000", "text": "knock knock" },
* { "date": "2015-06-05T17:37:42.123Z", "user": "raucao", "text": "who's there?" },
* { "date": "2015-06-05T17:55:01.235Z", "user": "hal8000", "text": "HAL" }
* ]
* }
* }
*/
const archiveSchema = {
"type": "object",
"properties": {
"@context": {
"type": "string",
"default": "https://kosmos.org/ns/v2/chat-channel"
},
"@id": {
"type": "string",
"required": true
},
"@type": {
"type": "string",
"default": "ChatChannel",
"enum": ["ChatChannel"]
},
"service": {
"type": "object",
"properties": {
"domain": {
"type": "string",
"required": true
},
"protocol": {
"type": "string",
"required": true
}
}
},
"name": {
"type": "string",
"required": true
},
"type": {
"type": "string",
"required": true,
"enum": [ "room", "person" ]
},
"today": {
"type": "object",
"properties": {
"@id": {
"type": "string",
"pattern": "^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$",
"required": true
},
"@type": {
"type": "string",
"default": "ChatLog",
"pattern": "^ChatLog$"
},
"messageType": {
"type": "string",
"default": "InstantMessage",
"pattern": "^InstantMessage$"
},
"previous": {
"type": "string",
"pattern": "^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$"
},
"next": {
"type": "string",
"pattern": "^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$"
},
"messages": {
"type": "array",
"required": true,
"items": {
"type": "object",
"properties": {
"date": {
"type": "string",
"format": "date-time"
},
"user": {
"type": "string"
},
"text": {
"type": "string"
},
"type": "string",
"default": "text",
"enum": [
"text",
"join",
"leave",
"action"
]
}
}
}
}
}
},
"required": []
};
privateClient.declareType("daily-archive", "https://kosmos.org/ns/v2/chat-channel", archiveSchema);
publicClient.declareType("daily-archive", "https://kosmos.org/ns/v2/chat-channel", archiveSchema);
/**
* Schema: chat-messages/daily-archive-meta
*
* Stores meta information about the daily archives
*
* @example
* {
* "@context": "https://kosmos.org/ns/v2",
* "@id": "chat-messages/irc.libera.chat/channels/kosmos/meta",
* "@type": "ChatChannelMeta",
* "first": "2009/01/03",
* "last": "2021/11/05"
* }
* }
*/
const archiveMetaSchema = {
"type": "object",
"properties": {
"@context": {
"type": "string",
"default": "https://kosmos.org/ns/v2/chat-channel-meta"
},
"@id": {
"type": "string",
},
"@type": {
"type": "string",
"default": "ChatChannelMeta",
"enum": ["ChatChannelMeta"]
},
"first": {
"type": "string",
"pattern": "^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$"
},
"last": {
"type": "string",
"pattern": "^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$"
}
},
"required": ["@id", "first", "last"]
};
privateClient.declareType("daily-archive-meta", "https://kosmos.org/ns/v2/chat-channel-meta", archiveMetaSchema);
publicClient.declareType("daily-archive-meta", "https://kosmos.org/ns/v2/chat-channel-meta", archiveMetaSchema);
/**
* A chat channel
*
* @class
*/
class Channel {
/**
* @param {object} options
* @param {object} options.service
* @param {string} options.service.protocol - Type of chat service/protocol (e.g. "IRC", "XMPP", "Campfire", "Slack")
* @param {string} options.service.domain - Domain of the chat service (e.g. "irc.libera.chat", "kosmos.chat")
* @param {string} options.name - Name of room/channel (e.g. "#kosmos")
* @param {string} [options.type] - Type of channel ("room" or "person")
*
* @example
* // IRC channel:
* const channel = new remoteStorage.chatMessages.Channel({
* service: {
* protocol: 'IRC',
* domain: 'irc.libera.chat',
* },
* name: '#kosmos-dev',
* type: 'room'
* });
*
* // XMPP channel:
* const channel = new remoteStorage.chatMessages.Channel({
* service: {
* protocol: 'XMPP',
* domain: 'kosmos.chat',
* },
* name: 'kosmos-dev',
* type: 'room'
* });
*/
constructor (options) {
//
// Defaults
//
options.type = options.type || "room";
//
// Validate options
//
if (typeof options !== "object") {
throw "options must be an object";
}
if (typeof options.service !== "object" ||
typeof options.service.protocol !== "string" ||
typeof options.service.domain !== "string") {
throw "options.service must be an object containing at least service \"protocol\" and \"domain\"";
}
if (typeof options.name !== "string") {
throw "options.name must be a string";
}
/**
* @property {object} service
* @property {string} service.protocol - Type of chat service/protocol (e.g. "IRC", "XMPP", "campfire", "slack")
* @property {string} service.domain - Domain of the chat service (e.g. "irc.libera.chat", "kosmos.chat")
*/
this.service = options.service;
/**
* @property {string} name - Name of channel (e.g. "#kosmos")
*/
this.name = options.name;
/**
* @property {string} type - Type of channel ("room" or "person")
*/
this.type = options.type;
/**
* @property {string} path - Base directory path of the channel archives
*/
if (this.type === "room") {
// Normal chatroom
const name = this.name.replace(/#/,'');
this.path = `${this.service.domain}/channels/${name}`;
} else {
// User direct messages
this.path = `${this.service.domain}/users/${this.name}`;
}
/**
* @property {string} metaPath - Path of the channel's metadata document
*/
this.metaPath = `${this.path}/meta`;
}
/*
* Returns the last stored DailyArchive, or a new one for the current day.
*
* @param {object} options
* @param {boolean} [options.public] - Public or private archive. Defaults to 'false'.
*
* @returns {Promise}
*/
async openLastDailyArchive (options={}) {
const client = options.public ? publicClient : privateClient;
const meta = await client.getObject(this.metaPath);
if (meta && meta.last) {
return new DailyArchive({
channel: this,
date: new Date(meta.last.replace(/\//g,'-')),
isPublic: options.public
});
} else {
return new DailyArchive({
channel: this,
date: new Date(),
isPublic: options.public
});
}
}
/*
* Returns a DailyArchive for the given date
*
* @param {object} options
* @param {date} options.date - Date of archive day
* @param {boolean} [options.public] - Public or private archive. Defaults to 'false'.
*
* @returns {Promise}
*/
openDailyArchive (options={}) {
if (!(options.date instanceof Date)) {
throw 'options.date must be a date object';
}
return new DailyArchive({
channel: this,
date: options.date,
isPublic: options.public
});
}
}
/**
* A daily archive stores chat messages by calendar day.
*
* @class
*/
class DailyArchive {
/**
* @param {object} options
* @param {string} options.channel - A Channel instance
* @param {date} options.date - Date of archive day
* @param {boolean} [options.isPublic] - Store logs in public folder (defaults to false)
* @param {string} [options.previous] - Date of previous log file as `YYYY/MM/DD`. Looked up automatically when not given
* @param {string} [options.next] - Date of next log file as `YYYY/MM/DD`. Looked up automatically when not given
*
* @example
* const channel = new remoteStorage.chatMessages.Channel({ ...options })
* const archive = new chatMessages.DailyArchive({
* channel: channel,
* date: new Date(),
* isPublic: true
* });
*/
constructor (options) {
//
// Defaults
//
options.isPublic = options.isPublic || false;
//
// Validate options
//
if (typeof options !== "object") {
throw "options must be an object";
}
if (!(options.channel instanceof Channel)) {
throw "options.channel must be a Channel object";
}
if (!(options.date instanceof Date)) {
throw "options.date must be a date object";
}
if (typeof options.isPublic !== "boolean") {
throw "options.isPublic must be a boolean value";
}
/**
* @property {Channel} channel - A Channel instance
*/
this.channel = options.channel;
/**
* @property {string} date - Gregorian calendar date of the archive's content
*/
this.date = options.date;
/**
* @property {boolean} isPublic - `true` for public archives, `false` for private ones
*/
this.isPublic = options.isPublic || false;
/**
* @property {object} parsedDate - Contains padded year, month and day of date
* @property {string} year
* @property {string} month
* @property {string} day
*/
this.parsedDate = parseDate(this.date);
/**
* @property {string} dateId - Date string in the form of YYYY/MM/DD
*/
this.dateId = this.parsedDate.year+'/'+this.parsedDate.month+'/'+this.parsedDate.day;
/**
* @property {string} path - Path of the archive document
*/
this.path = `${this.channel.path}/${this.dateId}`;
/**
* @property {string} metaPath - Path of the channel's metadata document
*/
this.metaPath = `${this.channel.path}/meta`;
/**
* @property {object} client - Public or private remoteStorgage.js BaseClient
*/
this.client = this.isPublic ? publicClient : privateClient;
/**
* @property {string} previous - Date of previous log file as YYYY/MM/DD
*/
this.previous = options.previous;
/**
* @property {string} next - Date of next log file as YYYY/MM/DD
*/
this.next = options.next;
}
/*
* @param {object} message
* @param {string} message.timestamp - Timestamp of the message
* @param {string} message.from - The sender of the message
* @param {string} message.text - The message itself
* @param {string} message.type - Type of message (one of text, join, leave, action)
* @param {string} [message.id] - Unique ID of message.
* @param {string} [message.sid] - Unique stanza ID of message (XMPP only)
* @param {boolean} [message.edited] - If the message has been edited
*
* @returns {Promise}
*/
addMessage (message) {
if (this.isPublic && !this.channel.name.match(/^#/)) {
return Promise.resolve(false);
}
message.type = message.type || 'text';
return this.client.getObject(this.path).then((archive) => {
if (typeof archive === 'object') {
return this._updateDocument(archive, message);
} else {
return this._createDocument(message);
}
});
}
/*
* Like <addMessage>, but for multiple messages at once. Useful for bulk
* imports of messages.
*
* @param {Array} messages - Array of message objects (see params for addMessage)
* @param {boolean} overwrite - If true, creates a new archive file and overwrites the old one. Defaults to false.
*
* @returns {Promise}
*/
addMessages (messages, overwrite) {
if (this.isPublic && !this.channel.name.match(/^#/)) {
return Promise.resolve(false);
}
overwrite = overwrite || false;
messages.forEach(function(message) {
message.type = message.type || 'text';
});
if (overwrite) {
return this._createDocument(messages);
} else {
return this.client.getObject(this.path).then((archive) => {
if (typeof archive === 'object') {
return this._updateDocument(archive, messages);
} else {
return this._createDocument(messages);
}
});
}
}
/*
* Deletes the entire archive document from storage
*
* @returns {Promise}
*/
remove () {
// TODO when removing, if previous is set, but not next, it means the
// removed file is the last archive. Thus, set "last" to previous file.
return this.client.remove(this.path);
}
/*
* Updates and writes an existing archive document
*
* @returns {Promise}
*
* @private
*/
async _updateDocument (archive, messages) {
console.debug('[chat-messages] Updating archive document');
if (Array.isArray(messages)) {
messages.forEach(function(message) {
archive.today.messages.push(message);
});
} else {
archive.today.messages.push(messages);
}
return this._sync(archive);
}
/*
* Creates and writes a new archive document
*
* @returns {Promise}
*
* @private
*/
async _createDocument (messages) {
console.debug('[chat-messages] Creating new archive document');
const archive = this._buildArchiveObject();
if (Array.isArray(messages)) {
messages.forEach(message => {
archive.today.messages.push(message);
});
} else {
archive.today.messages.push(messages);
}
if (this.previous || this.next) {
// The app is handling previous/next keys itself
// That includes setting 'next' in the previous log file
if (this.previous) { archive.today.previous = this.previous; }
if (this.next) { archive.today.next = this.next; }
} else {
// Find and update previous archive, set 'previous' on this one
const previous = await this._updatePreviousArchive();
if (typeof previous === 'object') {
archive.today.previous = previous.today['@id'];
}
}
await this._sync(archive);
// TODO only write meta doc if argument is set on addMessages. This way
// we can avoid race conditions when syncing remote chat messages all at
// once for multiple days
await this._updateArchiveMetaDocument();
return;
}
/*
* Builds the object to be stored in remote storage
*
* @returns {object}
*
* @private
*/
_buildArchiveObject () {
const roomName = this.channel.name.replace(/#/,'');
const archive = {
"@id": "chat-messages/"+this.channel.service.domain+"/channels/"+roomName+"/",
"@type": "ChatChannel",
"service": this.channel.service,
"name": this.channel.name,
"type": this.channel.type,
"today": {
"@id": this.dateId,
"@type": "ChatLog",
"messageType": "InstantMessage",
"messages": []
}
};
switch (this.channel.service.protocol) {
case 'IRC':
if (!this.channel.name.match(/^#/)) {
archive["@id"] = "chat-messages/"+this.channel.service.domain+"/users/"+this.channel.name+"/";
}
break;
case 'XMPP':
// XMPP-specific adjustments
break;
}
return archive;
}
/*
* Finds the previous archive document and updates its today.next value
*
* @returns {boolean|Promise}
*
* @private
*/
_updatePreviousArchive () {
return this._findPreviousArchive().then((archive) => {
if (typeof archive === 'object' && archive.today) {
archive.today.next = this.dateId;
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 at', path);
return archive;
});
} else {
console.debug('[chat-messages] Previous archive not found');
return false;
}
});
}
/*
* Returns the previous archive document
*
* @returns {Promise}
*
* @private
*/
_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) => {
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) {
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) => {
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) {
const month = pad(Math.max(...months).toString());
return this.client.getListing(yearPath+month+'/').then((listing) => {
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) => {
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) {
const year = Math.max(...years).toString();
return this.client.getListing(basePath+year+'/').then((listing) => {
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) => {
const days = Object.keys(listing).map((i) => parseInt(i));
const day = pad(Math.max(...days).toString());
return this.client.getObject(basePath+year+'/'+month+'/'+day);
});
});
} else {
return false;
}
});
}
});
});
}
async _updateArchiveMetaDocument () {
const meta = await this.client.getObject(this.metaPath);
if (typeof meta !== 'object') {
return this._createArchiveMetaDocument();
}
// Only update document if current date is newer than known "last"
if (Date.parse(meta.last.replace('/','-')) > Date.parse(this.date)) {
console.debug('[chat-messages]', 'Updating meta document for channel');
meta.last = this.dateId;
await this.client.storeObject('daily-archive-meta', this.metaPath, meta);
}
return;
}
async _createArchiveMetaDocument () {
console.debug('[chat-messages]', 'Creating new meta document for channel');
// When creating a new meta doc, we need to find the oldest archive,
// because older versions of the module did not write a meta doc.
const first = await this._findFirstArchive();
const roomName = this.channel.name.replace(/#/,'');
const meta = {
'@id': `chat-messages/${this.channel.service.domain}/channels/${roomName}/meta`,
'@type': 'ChatChannelMeta',
first: first,
last: this.dateId // TODO might have to search for last?
};
return this.client.storeObject('daily-archive-meta', this.metaPath, meta)
.then(() => console.debug('[chat-messages]', 'Meta document written to remote storage'))
.catch(e => {
console.log('[chat-messages]', `Failed to store ${this.metaPath}`);
console.error(e);
});
}
async _findFirstArchive () {
console.debug('[chat-messages]', 'Finding first archive for channel');
const years = await this.client.getListing(`${this.channelPath}/`);
const year = lowestNumberInListing(years);
const months = await this.client.getListing(`${this.channelPath}/${year}/`);
const month = lowestNumberInListing(months);
const days = await this.client.getListing(`${this.channelPath}/${year}/${pad(month)}/`);
const day = lowestNumberInListing(days);
const firstId = `${year}/${pad(month)}/${pad(day)}`;
console.debug('[chat-messages]', 'First is', firstId);
return firstId;
}
/*
* Write archive document
*
* @returns {Promise}
*
* @private
*/
async _sync (obj) {
console.debug(`[chat-messages] Writing archive object with ${obj.today.messages.length} messages`);
return this.client.storeObject('daily-archive', this.path, obj).then(function(){
console.debug('[chat-messages] Archive written to remote storage');
return true;
},function(error){
console.warn('[chat-messages] Error trying to store object', error);
return error;
});
// TODO await this.client.startSync();
}
};
return {
exports: {
DailyArchive,
privateClient,
publicClient
}
};
};
export default { name: 'chat-messages', builder: ChatMessages };
+25 -24
View File
@@ -1,32 +1,33 @@
var webpack = require('webpack');
var isProd = (process.env.NODE_ENV === 'production');
// minimize only in production
var plugins = isProd ? [new webpack.optimize.UglifyJsPlugin({minimize: true })] : []
/* global __dirname */
const isProd = (process.env.NODE_ENV === 'production');
const path = require('path');
module.exports = {
entry: './index.js',
// source map not in production
devtool: !isProd && 'source-map',
entry: ['./src/chat-messages.js'],
output: {
filename: __dirname + '/dist/build.js',
libraryTarget: 'umd'
},
externals: {
"remotestoragejs": {
root: "RemoteStorage", // <script src='remotestorage.js'> will resolve in this.RemoteStorage
commonjs2: "remotestoragejs", // require('remotestoragejs')
commonjs: "remotestoragejs", // require('remotestoragejs')
amd: "remotestoragejs" // define(['remotestoragejs'], ...)
}
path: path.resolve(__dirname, 'dist'),
filename: 'build.js',
library: 'ChatMessages',
libraryTarget: 'umd',
libraryExport: 'default',
umdNamedDefine: true,
globalObject: 'this'
},
mode: isProd ? 'production' : 'development',
devtool: isProd ? 'source-map' : 'eval-source-map',
module: {
loaders: [
{ test: /\.js$/, exclude: '/node_modules|dist/', loader: 'babel?presets[]=es2015' },
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
]
},
resolve: {
extensions: ['', '.js']
},
plugins: plugins
// plugins: plugins
};