/** * Abstract class Message * @constructor * @param {*} e * @param {number} ts **/ function Message(e, ts) { /** @const @type {string} **/ this.userId = e["user"]; /** @type {string} */ this.username = e["username"]; /** @const @type {string} **/ this.id = e["id"] || e["ts"]; /** @const @type {number} **/ this.ts = parseFloat(e["ts"]); /** @type {string} */ this.text = ""; /** @type {Array.<*>} */ this.attachments = []; /** @type {boolean} */ this.starred = false; /** @type {boolean} */ this.pinned = false; /** @type {number|boolean} */ this.edited = false; /** @type {boolean} */ this.removed = false; /** * for each emoji code, an array of user id * @type {Object.>} **/ this.reactions = {}; /** @type {number} */ this.version = ts; this.update(e, ts); }; /** * @constructor * @extends {Message} **/ function MeMessage(e, ts) { Message.call(this, e, ts); }; /** * @constructor * @extends {Message} **/ function NoticeMessage(e, ts) { Message.call(this, e, ts); }; /** * @param {*} e * @param {number} ts **/ Message.prototype.update = function(e, ts) { if (e) { this.text = e["text"] || ""; if (e["attachments"]) this.attachments = e["attachments"]; this.starred = !!e["is_starred"]; this.pinned = false; // TODO this.edited = e["edited"] === undefined ? false : e["edited"]; this.removed = !!e["removed"]; if (e["reactions"]) { var reactions = {}; e["reactions"].forEach(function(r) { reactions[r["name"]] = []; r["users"].forEach(function(userId) { reactions[r["name"]].push(userId); }); }); this.reactions = reactions; } } else { this.removed = true; } this.version = ts; }; /** @return {*} */ Message.prototype.toStatic = function() { var reactions = []; for (var reaction in this.reactions) { reactions.push({ "name": reaction ,"users": this.reactions[reaction] }); } return { "id": this.id ,"user": this.userId ,"username": this.username ,"ts": this.ts ,"text": this.text ,"attachments": this.attachments.length ? this.attachments : undefined ,"is_starred": this.is_starred || undefined ,"edited": this.edited === false ? undefined : this.edited ,"removed": this.removed || undefined ,"reactions": reactions ,"isMeMessage": this instanceof MeMessage || undefined ,"isNotice": this instanceof NoticeMessage || undefined }; }; /** * @param {string} reaction * @param {string} userId * @param {number} ts **/ Message.prototype.addReaction = function(reaction, userId, ts) { if (!this.reactions[reaction]) this.reactions[reaction] = []; if (this.reactions[reaction].indexOf(userId) === -1) { this.reactions[reaction].push(userId); this.version = ts; return true; } return false; }; /** * @param {string} reaction * @param {string} userId * @param {number} ts **/ Message.prototype.removeReaction = function(reaction, userId, ts) { var updated = false; if (this.reactions[reaction]) { if (this.reactions[reaction].length === 1 && this.reactions[reaction][0] === userId) { delete this.reactions[reaction]; updated = true; } else { this.reactions[reaction] = this.reactions[reaction].filter(function(i) { if (i !== userId) return true; updated = true; return false; }); } } if (updated) this.version = ts; return updated; }; Message.prototype.hasReactionForUser = function(reaction, userId) { if (this.reactions[reaction]) return this.reactions[reaction].indexOf(userId) !== -1; return false; }; /** * @constructor * @param {Room|string} room or roomId * @param {number} keepMessages number of messages to keep in memory * @param {Array|undefined} evts * @param {number|undefined} now **/ function RoomHistory(room, keepMessages, evts, now) { /** @type {string} */ this.id = typeof room === "string" ? room : room.id; /** @type {Array.} */ this.messages = []; /** @type number */ this.v = 0; /** @const @type {number} */ this.keepMessages = keepMessages; if (evts) this.pushAll(evts, now); }; /** * @param {Array} evts * @return {number} biggest ts **/ RoomHistory.prototype.pushAll = function(evts, t) { var result = 0; evts.forEach(function(e) { result = Math.max(this.push(e, t), result); }.bind(this)); this.resort(); return result; }; /** * @param {*} ev * @param {number} ts * @return {Message} **/ RoomHistory.prototype.messageFactory = function(ev, ts) { if (ev["isMeMessage"] === true) return new MeMessage(ev, ts); if (ev["isNotice"] === true) return new NoticeMessage(ev, ts); return new Message(ev, ts); }; /** * @param {*} e * @return {number} t **/ RoomHistory.prototype.push = function(e, t) { var exists = false ,ts; for (var i =0, nbMsg = this.messages.length; i < nbMsg; i++) { var msgObj = this.messages[i]; if (msgObj.id === e["id"]) { ts = msgObj.update(e, t); exists = true; break; } } if (!exists) { var msgObj = this.messageFactory(e, t); this.messages.push(msgObj); ts = msgObj.ts; } while (this.messages.length > this.keepMessages) this.messages.shift(); return ts || 0; }; RoomHistory.prototype.lastMessage = function() { return this.messages[this.messages.length -1]; }; /** * @param {string} reaction * @param {string} userId * @param {string} msgId * @param {number} ts * @return {Message|null} **/ RoomHistory.prototype.addReaction = function(reaction, userId, msgId, ts) { var msg = this.getMessageById(msgId); if (msg) msg.addReaction(reaction, userId, ts); return msg; }; /** * @param {string} reaction * @param {string} userId * @param {string} msgId * @param {number} ts * @return {Message|null} **/ RoomHistory.prototype.removeReaction = function(reaction, userId, msgId, ts) { var msg = this.getMessageById(msgId); if (msg) msg.removeReaction(reaction, userId, ts); return msg; }; /** * @param {number} ts * @return {Message|null} **/ RoomHistory.prototype.getMessage = function(ts) { for (var i =0, nbMessages = this.messages.length; i < nbMessages && ts >= this.messages[i].ts; i++) { if (this.messages[i].ts === ts) return this.messages[i]; } return null; }; /** * @param {string} id * @return {Message|null} **/ RoomHistory.prototype.getMessageById = function(id) { for (var i =0, nbMessages = this.messages.length; i < nbMessages; i++) { if (this.messages[i].id == id) return this.messages[i]; } return null; }; /** * @return {Array.<*>} **/ RoomHistory.prototype.toStatic = function(knownVersion) { var result = []; for (var i = this.messages.length -1; i >= 0; i--) if (this.messages[i].version > knownVersion) result.push(this.messages[i].toStatic()); return result; }; RoomHistory.prototype.resort = function() { this.messages.sort(function(a, b) { return a.ts -b.ts; }); }; MeMessage.prototype = Object.create(Message.prototype); MeMessage.prototype.constructor = MeMessage; NoticeMessage.prototype = Object.create(Message.prototype); NoticeMessage.prototype.constructor = NoticeMessage; /** @suppress {undefinedVars,checkTypes} */ (function() { if (typeof module !== "undefined") module.exports = { Message: Message ,MeMessage: MeMessage ,NoticeMessage: NoticeMessage ,RoomHistory: RoomHistory } })();