slackData.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. const ChatContext = require('./context.js').ChatContext
  2. ,ChatInfo = require('./context.js').ChatInfo
  3. ,Command = require('./context.js').Command
  4. ,Room = require('./room.js').Room
  5. ,Chatter = require('./chatter.js').Chatter
  6. ,PrivateMessageRoom = require('./room.js').PrivateMessageRoom;
  7. /**
  8. * @constructor
  9. * @extends {ChatInfo}
  10. **/
  11. function SlackTeam(teamId) {
  12. ChatInfo.call(this, teamId);
  13. /** @type {string} */
  14. this.domain;
  15. /** @type {string} */
  16. this.callApp;
  17. /** @type {string} */
  18. this.callAppName;
  19. /** @type {boolean} */
  20. this.fileUploadPermission;
  21. /** @type {boolean} */
  22. this.fileEditPermission;
  23. /** @type {boolean} */
  24. this.fileDeletePermission;
  25. /** @type {string} */
  26. this.icons = {
  27. small: ""
  28. ,large: ""
  29. };
  30. };
  31. SlackTeam.prototype = Object.create(ChatInfo.prototype);
  32. SlackTeam.prototype.constructor = SlackTeam;
  33. SlackTeam.prototype.toStatic = function(t) {
  34. var res = ChatInfo.prototype.toStatic.call(this, t);
  35. if (res) {
  36. res["domain"] = this.domain
  37. res["prefs"] = {
  38. "calling_app_id": this.callApp
  39. ,"calling_app_name": this.callAppName
  40. ,"disable_file_uploads": this.fileUploadPermission
  41. ,"disable_file_editing": this.fileEditPermission
  42. ,"disable_file_deleting": this.fileDeletePermission
  43. }
  44. res["icon"] = {
  45. "small": this.icons.small
  46. ,"large": this.icons.large
  47. };
  48. }
  49. return res;
  50. };
  51. SlackTeam.prototype.update = function(teamData, t) {
  52. ChatInfo.prototype.update.call(this, teamData, t);
  53. if (teamData["domain"] !== undefined) this.domain = teamData["domain"];
  54. if (teamData["prefs"]) {
  55. this.callApp = teamData["prefs"]["calling_app_id"];
  56. this.callAppName = teamData["prefs"]["calling_app_name"];
  57. this.fileUploadPermission = teamData["prefs"]["disable_file_uploads"];
  58. this.fileEditPermission = teamData["prefs"]["disable_file_editing"];
  59. this.fileDeletePermission = teamData["prefs"]["disable_file_deleting"];
  60. }
  61. if (teamData["icon"]) {
  62. this.icons.small = teamData["icon"]["image_34"];
  63. this.icons.large = teamData["icon"]["image_230"];
  64. }
  65. };
  66. /**
  67. * @constructor
  68. **/
  69. function SlackChan(teamId, chanId, isGroup) {
  70. Room.call(this, teamId +chanId);
  71. /** @const @type {string} */
  72. this.remoteId = chanId;
  73. this.isPrivate = isGroup;
  74. };
  75. SlackChan.prototype = Object.create(Room.prototype);
  76. SlackChan.prototype.constructor = SlackChan;
  77. SlackChan.prototype.setNameFromMembers = function() {
  78. var userNames = [];
  79. for (var i in this.users)
  80. if (!this.users[i].deleted)
  81. userNames.push(this.users[i].name);
  82. userNames.sort();
  83. this.name = userNames.join(", ");
  84. };
  85. /**
  86. * @constructor
  87. * @extends {PrivateMessageRoom}
  88. * @param {string} id
  89. * @param {SlackChatter} user
  90. **/
  91. function SlackIms(teamId, id, user) {
  92. PrivateMessageRoom.call(this, teamId +id, user);
  93. /** @const @type {string} */
  94. this.remoteId = id;
  95. };
  96. SlackIms.prototype = Object.create(PrivateMessageRoom.prototype);
  97. SlackIms.prototype.constructor = SlackIms;
  98. /**
  99. * @constructor
  100. * @extends {Chatter}
  101. **/
  102. function SlackChatter(teamId, id) {
  103. Chatter.call(this, teamId +id);
  104. /** @type {string} */
  105. this.remoteId = id;
  106. /** @type {Object.<string, string>} */
  107. this.icons = {
  108. small: ""
  109. ,large: ""
  110. };
  111. };
  112. SlackChatter.prototype = Object.create(Chatter.prototype);
  113. SlackChatter.prototype.constructor = SlackChatter;
  114. SlackChatter.prototype.setPresence = function(presenceStr, t) {
  115. this.presence = presenceStr !== 'away';
  116. this.version = Math.max(t, this.version);
  117. };
  118. SlackChatter.prototype.update = function(userData, t) {
  119. Chatter.prototype.update.call(this, userData, t);
  120. if (userData["profile"]) {
  121. this.email = userData["profile"]["email"];
  122. this.firstName = userData["profile"]["first_name"];
  123. this.lastName = userData["profile"]["last_name"];
  124. }
  125. };
  126. /**
  127. * @constructor
  128. * @extends {SlackChatter}
  129. **/
  130. function SlackUser(teamId, id) {
  131. SlackChatter.call(this, teamId, id);
  132. };
  133. SlackUser.prototype = Object.create(SlackChatter.prototype);
  134. SlackUser.prototype.constructor = SlackUser;
  135. SlackUser.prototype.update = function(userData, t) {
  136. SlackChatter.prototype.update.call(this, userData, t);
  137. if (userData["profile"]) {
  138. this.icons.small = userData["profile"]["image_48"] || this.icons.small;
  139. this.icons.large = userData["profile"]["image_512"] || this.icons.large;
  140. }
  141. };
  142. /**
  143. * @constructor
  144. * @extends {SlackChatter}
  145. **/
  146. function SlackBot(teamId, id) {
  147. SlackChatter.call(this, teamId, id);
  148. /** @type {string} */
  149. this.appId;
  150. this.isBot = true;
  151. };
  152. SlackBot.prototype = Object.create(SlackChatter.prototype);
  153. SlackBot.prototype.constructor = SlackBot;
  154. /** @param {*} botData */
  155. SlackBot.prototype.update = function(botData, t) {
  156. SlackChatter.prototype.update.call(this, botData, t);
  157. if (botData["app_id"] !== undefined) this.appId = botData["app_id"];
  158. this.isBot = true;
  159. if (botData["icons"]) {
  160. this.icons.small = botData["icons"]["image_48"] || this.icons.small;
  161. this.icons.large = botData["icons"]["image_72"] || this.icons.large;
  162. }
  163. };
  164. /**
  165. * @constructor
  166. **/
  167. function SlackData(slack) {
  168. ChatContext.call(this);
  169. /**
  170. * Node serv handler
  171. * @type {*}
  172. **/
  173. this.slack = slack;
  174. };
  175. SlackData.prototype = Object.create(ChatContext.prototype);
  176. SlackData.prototype.constructor = SlackData;
  177. /**
  178. * @param {*} data
  179. **/
  180. SlackData.prototype.updateStatic = function(data, t) {
  181. if (data["team"] && !this.team) this.team = this.teamFactory(data["team"]["id"]);
  182. if (data["bots"]) for (var i =0, nbBots = data["bots"].length; i < nbBots; i++) {
  183. var botObj = this.users[this.team.id +'|' +data["bots"][i]["id"]];
  184. if (!botObj)
  185. botObj = this.users[this.team.id +'|' +data["bots"][i]["id"]] = new SlackBot(this.team.id +'|', data["bots"][i]["id"]);
  186. botObj.update(data["bots"][i], t);
  187. }
  188. ChatContext.prototype.updateStatic.call(this, data, t, this.team.id +'|');
  189. if (data["ims"]) for (var i =0, nbIms = data["ims"].length; i < nbIms; i++) {
  190. var user = this.users[this.team.id +'|' +data["ims"][i]["user"]];
  191. if (user) {
  192. if (!this.channels[this.team.id +'|' +data["ims"][i]["id"]])
  193. this.channels[this.team.id +'|' +data["ims"][i]["id"]] = new SlackIms(this.team.id +'|', data["ims"][i]["id"], user);
  194. this.channels[this.team.id +'|' +data["ims"][i]["id"]].update(data["ims"][i], this, t, this.team.id +'|');
  195. }
  196. }
  197. for (var i =0, nbGroups = data["groups"].length; i < nbGroups; i++) {
  198. var groupData = data["groups"][i]
  199. ,groupObj = this.channels[this.team.id +'|' +groupData["id"]];
  200. if (!groupObj)
  201. groupObj = this.channels[this.team.id +'|' +groupData["id"]] = new SlackChan(this.team.id +'|', groupData["id"], true);
  202. groupObj.update(groupData, this, t, this.team.id +'|');
  203. groupObj.archived |= groupData["is_open"] === false;
  204. groupObj.isMember = true;
  205. if (groupData["is_mpim"])
  206. groupObj.setNameFromMembers();
  207. }
  208. };
  209. SlackData.prototype.teamFactory = function(id) {
  210. return new SlackTeam('SLACK|' +id);
  211. };
  212. SlackData.prototype.userFactory = function(userData) {
  213. return new SlackUser(this.team.id +'|', userData["id"]);
  214. };
  215. SlackData.prototype.roomFactory = function(roomData) {
  216. return new SlackChan(this.team.id +'|', roomData["id"], false);
  217. };
  218. SlackData.prototype.commandFactory = function(data) {
  219. var getServiceName = (function() {
  220. if (data["service_name"])
  221. return data["service_name"];
  222. else if (data["app"]) {
  223. for (var i in this.users)
  224. if (this.users[i].appId === data["app"] && this.users[i].name)
  225. return this.users[i].name;
  226. console.error("Unknown app " +data["app"]);
  227. return "";
  228. }
  229. return "Slack";
  230. }).bind(this);
  231. data["category"] = data["category"] || getServiceName();
  232. return new Command(data);
  233. };
  234. /**
  235. * @param {*} msg
  236. * @param {number} t
  237. **/
  238. SlackData.prototype.onMessage = function(msg, t) {
  239. if (msg["type"] === "presence_change") {
  240. var member = this.users[this.team.id +'|' +msg["user"]];
  241. if (member)
  242. member.setPresence(msg["presence"], t);
  243. this.staticV = Math.max(this.staticV, t);
  244. } else if (msg["type"] === "user_typing") {
  245. this.typing[this.team.id +'|' +msg["channel"]] = this.typing[this.team.id +'|' +msg["channel"]] || {};
  246. this.typing[this.team.id +'|' +msg["channel"]][this.team.id +'|' +msg["user"]] = t;
  247. this.staticV = Math.max(this.staticV, t);
  248. } else if (msg["type"] === "im_marked" || msg["type"] === "channel_marked" || msg["type"] === "group_marked") {
  249. var channel = this.channels[this.team.id +'|' +msg["channel"]];
  250. if (channel) {
  251. channel.lastRead = parseFloat(msg["ts"]);
  252. this.staticV = channel.version = Math.max(channel.version, t);
  253. }
  254. }
  255. };
  256. /**
  257. * @param {number} knownVersion
  258. * @param {number} now time at update check
  259. * @return {Object|undefined}
  260. **/
  261. SlackData.prototype.getUpdates = function(knownVersion, now) {
  262. if (this.staticV > knownVersion)
  263. return this.toStatic(knownVersion, now);
  264. return undefined;
  265. };
  266. /** @suppress {undefinedVars,checkTypes} */
  267. (function() {
  268. if (typeof module !== "undefined") {
  269. module.exports.SlackData = SlackData;
  270. }
  271. })();