slackHistory.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. const Message = require('./message.js').Message
  2. ,MeMessage = require('./message.js').MeMessage
  3. ,NoticeMessage = require('./message.js').NoticeMessage
  4. ,RoomHistory = require('./message.js').RoomHistory;
  5. /**
  6. * @constructor
  7. * @extends {RoomHistory}
  8. * @param {Slack} ctx
  9. * @param {string} serviceId
  10. * @param {Room|string} room or roomId
  11. * @param {string} idPrefix
  12. * @param {number} keepMessages number of messages to keep in memory
  13. * @param {number} maxAge number of messages to keep in memory
  14. * @param {Array=} evts
  15. * @param {number=} now
  16. **/
  17. function SlackHistory(ctx, remoteId, room, idPrefix, keepMessages, maxAge, evts, now) {
  18. RoomHistory.call(this, room, keepMessages, maxAge, evts, now);
  19. /** @const @type {string} */
  20. this.remoteId = remoteId;
  21. /** @const @type {string} */
  22. this.idPrefix = idPrefix;
  23. /** @const @type {Slack} */
  24. this.ctx = ctx;
  25. }
  26. SlackHistory.prototype = Object.create(RoomHistory.prototype);
  27. SlackHistory.prototype.constructor = SlackHistory;
  28. SlackHistory.prototype.prepareMessage = function(ev, targetId) {
  29. if (ev) {
  30. if (ev["edited"] && ev["edited"]["ts"])
  31. ev["edited"] = Math.round(parseFloat(ev["edited"]["ts"]) * 1000);
  32. if (ev["ts"])
  33. ev["ts"] = parseFloat(ev["ts"]) * 1000;
  34. if (!ev["id"])
  35. ev["id"] = targetId;
  36. if (ev["attachments"] && ev["attachments"].length)
  37. ev["attachments"].forEach((a) => {
  38. a.ts *= 1000;
  39. });
  40. }
  41. return ev;
  42. }
  43. SlackHistory.prototype.messageFactory = function(ev, ts) {
  44. if (!ev["user"]) {
  45. if (ev["bot_id"])
  46. ev["user"] = ev["bot_id"];
  47. if (ev["comment"] && ev["comment"]["user"])
  48. ev["user"] = ev["comment"]["user"];
  49. }
  50. ev["user"] = this.idPrefix +ev["user"];
  51. if (ev["reactions"]) {
  52. ev["reactions"].forEach((r) => {
  53. for (var i =0, nbUsers =r["users"].length; i < nbUsers; i++)
  54. r["users"][i] = this.idPrefix +r["users"][i];
  55. });
  56. }
  57. if (ev["is_ephemeral"] === true)
  58. return new NoticeMessage(ev, ts);
  59. if (ev["subtype"] === "me_message")
  60. return new MeMessage(ev, ts);
  61. return new Message(ev, ts);
  62. };
  63. /**
  64. * @param {Object} ev
  65. * @param {number} t
  66. * @return {number} ts
  67. **/
  68. SlackHistory.prototype.push = function(ev, t) {
  69. var msg;
  70. if (!ev["type"] || ev["type"] === "message") {
  71. var exists = false
  72. ,targetId = ev["ts"]
  73. ,modifArg = ev;
  74. if (ev["subtype"] === "message_changed") {
  75. if (ev["previous_message"])
  76. targetId = ev["previous_message"]["ts"];
  77. else if (ev["message"])
  78. targetId = ev["message"]["ts"];
  79. modifArg = ev["message"]
  80. } else if (ev["subtype"] === "message_deleted" && (ev["previous_message"] || ev["deleted_ts"])) {
  81. if (ev["previous_message"])
  82. targetId = ev["previous_message"]["ts"];
  83. else
  84. targetId = ev["deleted_ts"];
  85. modifArg = null;
  86. } else if (ev["subtype"] === "star_changed") {
  87. modifArg = ev["message"];
  88. targetId = ev["message"]["ts"];
  89. }
  90. var msg = this.getMessageById(targetId);
  91. if (msg) {
  92. msg.update(this.prepareMessage(modifArg), t);
  93. exists = true;
  94. } else {
  95. this.prepareMessage(ev["previous_message"], targetId);
  96. this.prepareMessage(ev["message"], targetId);
  97. var msgSource = ev["previous_message"] || ev["message"];
  98. if (msgSource) {
  99. msg = this.messageFactory(msgSource, t);
  100. msg.update(modifArg, t);
  101. } else {
  102. msg = this.messageFactory(this.prepareMessage(ev, targetId), t);
  103. }
  104. this.messages.push(msg);
  105. }
  106. } else if (ev["type"] === "reaction_added") {
  107. msg = this.addReaction(ev["reaction"], this.idPrefix +ev["user"], ev["item"]["ts"], t);
  108. if (!msg) {
  109. let self = this;
  110. this.ctx.fetchHistory(this.ctx.getChatContext().channels[this.id], (msg) => {
  111. if (msg && msg.length) {
  112. msg[0].version = t;
  113. self.messages.push(msg[0]);
  114. self.resort();
  115. self.v = Math.max(self.v, t);
  116. self.ctx.getChatContext().liveV = Math.max(self.ctx.getChatContext().liveV, t);
  117. }
  118. }, 1, ev["item"]["ts"]);
  119. }
  120. } else if (ev["type"] === "reaction_removed") {
  121. let self = this;
  122. msg = this.removeReaction(ev["reaction"], this.idPrefix +ev["user"], ev["item"]["ts"], t);
  123. if (!msg) {
  124. this.ctx.fetchHistory(this.ctx.getChatContext().channels[this.id], (msg) => {
  125. if (msg && msg.length) {
  126. msg[0].version = t;
  127. self.messages.push(msg[0]);
  128. self.resort();
  129. self.v = Math.max(self.v, t);
  130. self.ctx.getChatContext().liveV = Math.max(self.ctx.getChatContext().liveV, t);
  131. }
  132. }, 1, ev["item"]["ts"]);
  133. }
  134. } else if (ev["type"] === "star_added" || ev["type"] === "star_removed") {
  135. ev["item"]["subtype"] = "star_changed";
  136. return this.push(ev["item"], t);
  137. } else {
  138. return 0;
  139. }
  140. this.cleanOld(t);
  141. return msg ? msg.ts : 0;
  142. };
  143. SlackHistory.prototype.resort = function() {
  144. this.messages.sort(function(a, b) {
  145. return a.ts -b.ts;
  146. });
  147. };
  148. module.exports.SlackHistory = SlackHistory;