slackData.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894
  1. /**
  2. * @constructor
  3. **/
  4. function SlackTeam(teamId) {
  5. /** @const @type {string} */
  6. this.id = teamId;
  7. /** @type {string} */
  8. this.name;
  9. /** @type {string} */
  10. this.domain;
  11. /** @type {string} */
  12. this.callApp;
  13. /** @type {string} */
  14. this.callAppName;
  15. /** @type {boolean} */
  16. this.fileUploadPermission;
  17. /** @type {boolean} */
  18. this.fileEditPermission;
  19. /** @type {boolean} */
  20. this.fileDeletePermission;
  21. /** @type {Object.<string, string>} */
  22. this.icons = {
  23. image_34: ""
  24. ,image_44: ""
  25. ,image_68: ""
  26. ,image_88: ""
  27. ,image_102: ""
  28. ,image_132: ""
  29. ,image_230: ""
  30. ,image_default: ""
  31. };
  32. /** @type {number} */
  33. this.version = 0;
  34. }
  35. SlackTeam.prototype.update = function(teamData, t) {
  36. if (teamData["name"] !== undefined) this.name = teamData["name"];
  37. if (teamData["domain"] !== undefined) this.domain = teamData["domain"];
  38. if (teamData["prefs"]) {
  39. this.callApp = teamData["prefs"]["calling_app_id"];
  40. this.callAppName = teamData["prefs"]["calling_app_name"];
  41. this.fileUploadPermission = teamData["prefs"]["disable_file_uploads"];
  42. this.fileEditPermission = teamData["prefs"]["disable_file_editing"];
  43. this.fileDeletePermission = teamData["prefs"]["disable_file_deleting"];
  44. }
  45. if (teamData["icon"]) {
  46. this.icons.image_34 = teamData["icon"]["image_34"];
  47. this.icons.image_44 = teamData["icon"]["image_44"];
  48. this.icons.image_68 = teamData["icon"]["image_68"];
  49. this.icons.image_88 = teamData["icon"]["image_88"];
  50. this.icons.image_102 = teamData["icon"]["image_102"];
  51. this.icons.image_132 = teamData["icon"]["image_132"];
  52. this.icons.image_230 = teamData["icon"]["image_230"];
  53. this.icons.image_default = teamData["icon"]["image_default"];
  54. }
  55. this.version = Math.max(this.version, t);
  56. }
  57. /**
  58. * @constructor
  59. **/
  60. function SlackChan(chanId) {
  61. /** @const @type {string} */
  62. this.id = chanId;
  63. /** @type {string} */
  64. this.name;
  65. /** @type {string} */
  66. this.created;
  67. /** @type {SlackUser|SlackBot} */
  68. this.creator;
  69. /** @type {boolean} */
  70. this.archived;
  71. /** @type {boolean} */
  72. this.isMember;
  73. /** @type {number} */
  74. this.lastRead = 0;
  75. /** @type {number} */
  76. this.lastMsg = 0;
  77. /** @type {Object.<string, SlackBot|SlackUser>} */
  78. this.members = {};
  79. /** @type {string|undefined} */
  80. this.topic;
  81. /** @type {number|undefined} */
  82. this.topicTs;
  83. /** @type {SlackUser|SlackBot|undefined} */
  84. this.topicCreator;
  85. /** @type {string|undefined} */
  86. this.purpose;
  87. /** @type {number|undefined} */
  88. this.purposeTs;
  89. /** @type {SlackUser|SlackBot|undefined} */
  90. this.purposeCreator;
  91. /** @type {number} */
  92. this.version = 0;
  93. }
  94. /**
  95. * @param {*} chanData
  96. * @param {SlackData} slackData
  97. **/
  98. SlackChan.prototype.update = function(chanData, slackData, t) {
  99. if (chanData["name"] !== undefined) this.name = chanData["name"];
  100. if (chanData["created"] !== undefined) this.created = chanData["created"];
  101. if (chanData["creator"] !== undefined) this.creator = slackData.getMember(chanData["creator"]);
  102. if (chanData["is_archived"] !== undefined) this.archived = chanData["is_archived"];
  103. if (chanData["is_member"] !== undefined) this.isMember = chanData["is_member"];
  104. if (chanData["last_read"] !== undefined) this.lastRead = Math.max(parseFloat(chanData["last_read"]), this.lastRead);
  105. if (chanData["last_msg"] !== undefined) this.lastMsg = parseFloat(chanData["last_msg"]);
  106. if (chanData["latest"]) this.lastMsg = parseFloat(chanData["latest"]["ts"]);
  107. if (chanData["members"]) {
  108. this.members = {};
  109. if (chanData["members"]) for (var i =0, nbMembers = chanData["members"].length; i < nbMembers; i++) {
  110. var member = slackData.getMember(chanData["members"][i]);
  111. this.members[member.id] = member;
  112. member.channels[this.id] = this;
  113. }
  114. }
  115. if (chanData["topic"]) {
  116. this.topic = chanData["topic"]["value"];
  117. this.topicCreator = slackData.getMember(chanData["topic"]["creator"]);
  118. this.topicTs = chanData["topic"]["last_set"];
  119. }
  120. if (chanData["purpose"]) {
  121. this.purpose = chanData["purpose"]["value"];
  122. this.purposeCreator = slackData.getMember(chanData["purpose"]["creator"]);
  123. this.purposeTs = chanData["purpose"]["last_set"];
  124. }
  125. this.version = Math.max(this.version, t);
  126. }
  127. SlackChan.prototype.setLastMsg = function(lastMsg, t) {
  128. if (this.lastMsg < lastMsg) {
  129. this.lastMsg = lastMsg;
  130. this.version = t;
  131. return true;
  132. }
  133. return false;
  134. }
  135. /**
  136. * @constructor
  137. * @param {string} id
  138. **/
  139. function SlackGroup(id) {
  140. /** @const @type {string} */
  141. this.id = id;
  142. /** @type {Object.<string, SlackUser|SlackBot>} */
  143. this.members = {};
  144. /** @type {number} */
  145. this.nbMembers = 0;
  146. /** @type {string} */
  147. this.name;
  148. /** @type {number} */
  149. this.created;
  150. /** @type {SlackUser|SlackBot} */
  151. this.creator;
  152. /** @type {boolean} */
  153. this.archived;
  154. /** @type {number} */
  155. this.lastRead = 0;
  156. /** @type {number} */
  157. this.lastMsg = 0;
  158. /** @type {string|undefined} */
  159. this.topic;
  160. /** @type {number|undefined} */
  161. this.topicTs;
  162. /** @type {SlackUser|SlackBot|undefined} */
  163. this.topicCreator;
  164. /** @type {string|undefined} */
  165. this.purpose;
  166. /** @type {number|undefined} */
  167. this.purposeTs;
  168. /** @type {SlackUser|SlackBot|undefined} */
  169. this.purposeCreator;
  170. /** @type {number} version */
  171. this.version = 0;
  172. }
  173. /**
  174. * @param {SlackData} slack
  175. * @param {*} groupData
  176. **/
  177. SlackGroup.prototype.update = function(slack, groupData, t) {
  178. var memberNames = [];
  179. if (groupData["members"]) {
  180. /** @type {Object.<string, SlackUser|SlackBot>} */
  181. this.members = {};
  182. this.nbMembers = 0;
  183. for (var i =0, nbMembers = groupData["members"].length; i < nbMembers; i++) {
  184. var member = slack.getMember(groupData["members"][i]);
  185. this.members[groupData["members"][i]] = member;
  186. member.channels[this.id] = this;
  187. memberNames.push(member.name);
  188. this.nbMembers++;
  189. }
  190. this.name = memberNames.join(", ");
  191. }
  192. if (groupData["created"] !== undefined) this.created = groupData["created"];
  193. if (groupData["creator"] !== undefined) this.creator = slack.getMember(groupData["creator"]);
  194. if (groupData["is_archived"] !== undefined) this.archived = groupData["is_archived"] || groupData["is_open"] === false;
  195. if (groupData["last_read"] !== undefined) this.lastRead = Math.max(parseFloat(groupData["last_read"]), this.lastRead);
  196. if (groupData["last_msg"] !== undefined) this.lastMsg = parseFloat(groupData["last_msg"]);
  197. else if (groupData["latest"]) this.lastMsg = parseFloat(groupData["latest"]["ts"]);
  198. if (groupData["topic"]) {
  199. this.topic = groupData["topic"]["value"];
  200. this.topicCreator = slack.getMember(groupData["topic"]["creator"]);
  201. this.topicTs = groupData["topic"]["last_set"];
  202. }
  203. if (groupData["purpose"]) {
  204. this.purpose = groupData["purpose"]["value"];
  205. this.purposeCreator = slack.getMember(groupData["purpose"]["creator"]);
  206. this.purposeTs = groupData["purpose"]["last_set"];
  207. }
  208. this.version = Math.max(this.version, t);
  209. }
  210. SlackGroup.prototype.setLastMsg = function(lastMsg, t) {
  211. if (this.lastMsg < lastMsg) {
  212. this.lastMsg = lastMsg;
  213. this.version = t;
  214. return true;
  215. }
  216. return false;
  217. }
  218. /**
  219. * @constructor
  220. * @param {string} id
  221. * @param {SlackUser|SlackBot} user
  222. **/
  223. function SlackIms(id, user) {
  224. /** @const @type {string} */
  225. this.id = id;
  226. /** @type {number} */
  227. this.created;
  228. /** @type {SlackUser|SlackBot} */
  229. this.user = user;
  230. /** @type {number} */
  231. this.lastRead = 0;
  232. /** @type {number} */
  233. this.lastMsg = 0;
  234. /** @type {boolean} */
  235. this.archived;
  236. /** @type {number} */
  237. this.version = 0;
  238. }
  239. /**
  240. * @param {SlackUser|SlackBot} user
  241. * @param {*} imsData
  242. **/
  243. SlackIms.prototype.update = function(user, imsData, t) {
  244. if (imsData["created"] !== undefined) this.created = imsData["created"];
  245. if (imsData["last_read"] !== undefined) this.lastRead = Math.max(parseFloat(imsData["last_read"]), this.lastRead);
  246. if (imsData["last_msg"] !== undefined) this.lastMsg = parseFloat(imsData["last_msg"]);
  247. if (imsData["latest"]) this.lastMsg = parseFloat(imsData["latest"]["ts"]);
  248. this.archived = user.deleted;
  249. this.version = Math.max(this.version, t);
  250. }
  251. SlackIms.prototype.setLastMsg = function(lastMsg, t) {
  252. if (this.lastMsg < lastMsg) {
  253. this.lastMsg = lastMsg;
  254. this.version = t;
  255. return true;
  256. }
  257. return false;
  258. }
  259. /**
  260. * @constructor
  261. **/
  262. function SlackUser(id) {
  263. /** @const @type {string} */
  264. this.id = id;
  265. /** @type {string} */
  266. this.name;
  267. /** @type {boolean} */
  268. this.deleted;
  269. /** @type {string} */
  270. this.status;
  271. /** @type {string} */
  272. this.realName;
  273. /** @type {boolean} */
  274. this.presence;
  275. /** @type {Object.<string, string>} */
  276. this.icons = {
  277. image_24: ""
  278. ,image_32: ""
  279. ,image_48: ""
  280. ,image_72: ""
  281. ,image_192: ""
  282. ,image_512: ""
  283. };
  284. /** @type {string} */
  285. this.email;
  286. /** @type {string} */
  287. this.firstName;
  288. /** @type {string} */
  289. this.lastName;
  290. /** @type {!Object.<string, SlackChan|SlackGroup>} */
  291. this.channels = {};
  292. /** @type {SlackIms} */
  293. this.ims = null;
  294. /** @type {SelfPreferences|null} */
  295. this.prefs = null;
  296. /** @type {number} */
  297. this.version = 0;
  298. }
  299. /**
  300. * @param {*} userData
  301. **/
  302. SlackUser.prototype.update = function(userData, t) {
  303. if (userData["name"] !== undefined) this.name = userData["name"];
  304. if (userData["deleted"] !== undefined) this.deleted = userData["deleted"];
  305. if (userData["status"] !== undefined) this.status = userData["status"];
  306. if (userData["real_name"] !== undefined)
  307. this.realName = userData["real_name"];
  308. else if (userData["profile"] && userData["profile"]["real_name"] !== undefined)
  309. this.realName = userData["profile"]["real_name"];
  310. if (userData["presence"] !== undefined)
  311. this.presence = userData["presence"] !== 'away';
  312. if (userData["isPresent"] !== undefined)
  313. this.presence = userData["isPresent"];
  314. if (userData["profile"]) {
  315. this.icons.image_24 = userData["profile"]["image_24"];
  316. this.icons.image_32 = userData["profile"]["image_32"];
  317. this.icons.image_48 = userData["profile"]["image_48"];
  318. this.icons.image_72 = userData["profile"]["image_72"];
  319. this.icons.image_192 = userData["profile"]["image_192"];
  320. this.icons.image_512 = userData["profile"]["image_512"];
  321. this.email = userData["profile"]["email"];
  322. this.firstName = userData["profile"]["first_name"];
  323. this.lastName = userData["profile"]["last_name"];
  324. }
  325. this.version = Math.max(this.version, t);
  326. }
  327. SlackUser.prototype.setPresence = function(presenceStr, t) {
  328. this.presence = presenceStr !== 'away';
  329. this.version = Math.max(t, this.version);
  330. }
  331. /**
  332. * @constructor
  333. **/
  334. function SelfPreferences() {
  335. /** @type {Object.<string, number>} */
  336. this.favoriteEmojis = {};
  337. /** @type {Array.<string>} */
  338. this.highlights = [];
  339. }
  340. /**
  341. * @param {*} prefs
  342. **/
  343. SelfPreferences.prototype.update = function(prefs, t) {
  344. this.favoriteEmojis = /** @type {Object<string,number>} */ (JSON.parse(prefs["emoji_use"]));
  345. if (prefs["highlight_words"])
  346. this.highlights = (prefs["highlight_words"]||"").split(',').filter(function(i) {
  347. return i.trim() !== '';
  348. });
  349. else if (prefs["highlights"])
  350. this.highlights = prefs["highlights"];
  351. this.version = Math.max(this.version, t);
  352. }
  353. /**
  354. * @constructor
  355. **/
  356. function SlackBot(id) {
  357. /** @const @type {string} */
  358. this.id = id;
  359. /** @type {boolean} */
  360. this.deleted;
  361. /** @type {string} */
  362. this.name;
  363. /** @type {string} */
  364. this.appId;
  365. /** @type {Object.<string, string>} */
  366. this.icons = {
  367. image_36: ""
  368. ,image_48: ""
  369. ,image_72: ""
  370. };
  371. /** @type {!Object.<string, SlackGroup|SlackChan>} */
  372. this.channels;
  373. /** @type {SlackIms|null} */
  374. this.ims = null;
  375. /** @type {SelfPreferences|null} */
  376. this.prefs = null;
  377. /** @type {number} */
  378. this.version = 0;
  379. /** @type {boolean} */
  380. this.presence = false;
  381. }
  382. /** @param {*} botData */
  383. SlackBot.prototype.update = function(botData, t) {
  384. if (botData["deleted"] !== undefined) this.deleted = botData["deleted"];
  385. if (botData["name"] !== undefined) this.name = botData["name"];
  386. if (botData["app_id"] !== undefined) this.appId = botData["app_id"];
  387. if (botData["icons"]) {
  388. this.icons.image_36 = botData["icons"]["image_36"]
  389. this.icons.image_48 = botData["icons"]["image_48"]
  390. this.icons.image_72 = botData["icons"]["image_72"]
  391. }
  392. if (botData["presence"] !== undefined)
  393. this.presence = botData["presence"] !== 'away';
  394. if (botData["isPresent"] !== undefined)
  395. this.presence = botData["isPresent"];
  396. this.version = Math.max(this.version, t);
  397. }
  398. SlackBot.prototype.setPresence = function(presenceStr, t) {
  399. this.presence = presenceStr !== 'away';
  400. this.version = Math.max(t, this.version);
  401. }
  402. /**
  403. * @constructor
  404. * @param {*} data
  405. **/
  406. function SlackCommand(slack, data) {
  407. /** @const @type {string} */
  408. this.desc = data["desc"];
  409. /** @const @type {string} */
  410. this.name = data["name"];
  411. /** @const @type {string} */
  412. this.type = data["type"];
  413. /** @const @type {string} */
  414. this.usage = data["usage"];
  415. /** @const @type {string|null} */
  416. this.serviceName = SlackCommand.getServiceName(slack, data);
  417. }
  418. /**
  419. * @param {SlackData} slack
  420. * @param {*} data
  421. * @return {string|null}
  422. **/
  423. SlackCommand.getServiceName = function(slack, data) {
  424. if (data["service_name"])
  425. return data["service_name"];
  426. else if (data["app"]) {
  427. var bots = slack.getBotsByAppId(data["app"]);
  428. if (bots)
  429. for (var i =0; i < bots.length; i++)
  430. if (bots[i].name)
  431. return bots[i].name;
  432. console.log("Unknown app " +data["app"]);
  433. return "";
  434. }
  435. return "Slack";
  436. }
  437. /**
  438. * @param {number} t
  439. * @return {Object}
  440. **/
  441. SlackCommand.prototype.toStatic = function(t) {
  442. return {
  443. "desc": this.desc
  444. ,"name": this.name
  445. ,"type": this.type
  446. ,"usage": this.usage
  447. ,"service_name": this.serviceName
  448. };
  449. }
  450. /**
  451. * @constructor
  452. **/
  453. function SlackData(slack) {
  454. /** @type {SlackTeam} */
  455. this.team = null;
  456. /** @type {Object.<string, SlackChan>} */
  457. this.channels = {};
  458. /** @type {Object.<string, SlackGroup>} */
  459. this.groups = {};
  460. /** @type {Object.<string, SlackIms>} */
  461. this.ims = {};
  462. /** @type {Object.<string, SlackUser>} */
  463. this.users = {};
  464. /** @type {SlackUser|SlackBot} */
  465. this.self = null;
  466. /** @type {Object.<string, SlackBot>} */
  467. this.bots = {};
  468. /** @type {{version: number, data: Object.<string, string>}} */
  469. this.emojis = { version: 0, data: {} };
  470. /** @type {{version: number, data: Object.<string, SlackCommand>}} */
  471. this.commands = {version: 0, data: {} };
  472. /** @type {Object.<string, Object.<string, number>>} */
  473. this.typing = {};
  474. /**
  475. * Node serv handler
  476. * @type {*}
  477. **/
  478. this.slack = slack;
  479. /** @type {number} */
  480. this.staticV = 0;
  481. /** @type {number} */
  482. this.liveV = 0;
  483. }
  484. /**
  485. * @return {Object}
  486. **/
  487. SlackTeam.prototype.toStatic = function(t) {
  488. return t >= this.version ? {} : {
  489. "id": this.id
  490. ,"name": this.name
  491. ,"domain": this.domain
  492. ,"prefs": {
  493. "calling_app_id": this.callApp
  494. ,"calling_app_name": this.callAppName
  495. ,"disable_file_uploads": this.fileUploadPermission
  496. ,"disable_file_editing": this.fileEditPermission
  497. ,"disable_file_deleting": this.fileDeletePermission
  498. }
  499. ,"icon": this.icons
  500. };
  501. };
  502. /**
  503. * @return {Object}
  504. **/
  505. SlackChan.prototype.toStatic = function(t) {
  506. if (t >= this.version)
  507. return null;
  508. var res = {
  509. "id": this.id
  510. ,"name": this.name
  511. ,"created": this.created
  512. ,"creator": this.creator.id
  513. ,"is_archived": this.archived
  514. ,"is_member": this.isMember
  515. ,"last_read": this.lastRead
  516. ,"last_msg": this.lastMsg
  517. };
  518. if (this.isMember) {
  519. res["members"] = this.members ? Object.keys(this.members) : [];
  520. res["topic"] = {
  521. "value": this.topic
  522. ,"creator": this.topicCreator ? this.topicCreator.id : null
  523. ,"last_set": this.topicTs
  524. }
  525. res["purpose"] = {
  526. "value": this.purpose
  527. ,"creator": this.purposeCreator ? this.purposeCreator.id : null
  528. ,"last_set": this.purposeTs
  529. }
  530. }
  531. return res;
  532. };
  533. /**
  534. * @return {Object}
  535. **/
  536. SlackUser.prototype.toStatic = function(t) {
  537. return t >= this.version ? null : {
  538. "id": this.id
  539. ,"name": this.name
  540. ,"deleted": this.deleted
  541. ,"status": this.status
  542. ,"real_name": this.realName
  543. ,"isPresent": this.presence
  544. ,"profile": {
  545. "email": this.email
  546. ,"first_name": this.firstName
  547. ,"last_name": this.lastName
  548. ,"image_24": this.icons.image_24
  549. ,"image_32": this.icons.image_32
  550. ,"image_48": this.icons.image_48
  551. ,"image_72": this.icons.image_72
  552. ,"image_192": this.icons.image_192
  553. ,"image_512": this.icons.image_512
  554. }
  555. };
  556. };
  557. SlackGroup.prototype.toStatic = function(t) {
  558. if (t >= this.version)
  559. return null;
  560. var res = {
  561. "id": this.id
  562. ,"members": []
  563. ,"created": this.created
  564. ,"creator": this.creator.id
  565. ,"is_archived": this.archived
  566. ,"last_read": this.lastRead
  567. ,"last_msg": this.lastMsg
  568. };
  569. for (var mId in this.members) {
  570. res["members"].push(mId);
  571. }
  572. if (this.topic) {
  573. res["topic"] = {
  574. "value": this.topic
  575. ,"creator": this.topicCreator.id
  576. ,"last_set": this.topicTs
  577. };
  578. }
  579. if (this.purpose) {
  580. res["purpose"] = {
  581. "value": this.purpose
  582. ,"creator": this.purposeCreator.id
  583. ,"last_set": this.purposeTs
  584. };
  585. }
  586. return res;
  587. };
  588. SlackIms.prototype.toStatic = function(t) {
  589. return t >= this.version ? null: {
  590. "id": this.id
  591. ,"created": this.created
  592. ,"user": this.user.id
  593. ,"last_read": this.lastRead
  594. ,"last_msg": this.lastMsg
  595. };
  596. }
  597. SlackBot.prototype.toStatic = function(t) {
  598. return t >= this.version ? null : {
  599. "id": this.id
  600. ,"deleted": this.deleted
  601. ,"name": this.name
  602. ,"app_id": this.appId
  603. ,"isPresent": this.presence
  604. ,"icons": {
  605. "image_36": this.icons.image_36
  606. ,"image_48": this.icons.image_48
  607. ,"image_72": this.icons.image_72
  608. }
  609. };
  610. }
  611. /**
  612. * @param {*} data
  613. **/
  614. SlackData.prototype.updateStatic = function(data, t) {
  615. if (data["bots"]) for (var i =0, nbBots = data["bots"].length; i < nbBots; i++) {
  616. var botObj = this.bots[data["bots"][i]["id"]];
  617. if (!botObj)
  618. botObj = this.bots[data["bots"][i]["id"]] = new SlackBot(data["bots"][i]["id"]);
  619. botObj.update(data["bots"][i], t);
  620. }
  621. if (data["users"]) for (var i =0, nbUsers = data["users"].length; i < nbUsers; i++) {
  622. var userObj = this.users[data["users"][i]["id"]];
  623. if (!userObj)
  624. userObj = this.users[data["users"][i]["id"]] = new SlackUser(data["users"][i]["id"]);
  625. userObj.update(data["users"][i], t);
  626. }
  627. if (data["ims"]) for (var i =0, nbIms = data["ims"].length; i < nbIms; i++) {
  628. var user = this.getMember(data["ims"][i]["user"]);
  629. if (user) {
  630. if (!user.ims)
  631. this.ims[data["ims"][i]["id"]] = user.ims = new SlackIms(data["ims"][i]["id"], user);
  632. user.ims.update(user, data["ims"][i], t);
  633. }
  634. }
  635. if (data["channels"]) for (var i =0, nbChan = data["channels"].length; i < nbChan; i++) {
  636. var chanObj = this.channels[data["channels"][i]["id"]];
  637. if (!chanObj)
  638. chanObj = this.channels[data["channels"][i]["id"]] = new SlackChan(data["channels"][i]["id"]);
  639. chanObj.update(data["channels"][i], this, t);
  640. }
  641. for (var i =0, nbGroups = data["groups"].length; i < nbGroups; i++) {
  642. var groupObj = this.groups[data["groups"][i]["id"]];
  643. if (!groupObj)
  644. groupObj = this.groups[data["groups"][i]["id"]] = new SlackGroup(data["groups"][i]["id"]);
  645. groupObj.update(this, data["groups"][i], t);
  646. }
  647. if (data["emojis"]) {
  648. this.emojis.data = data["emojis"];
  649. this.emojis.version = t;
  650. }
  651. if (data["commands"] !== undefined){
  652. this.commands.data = {};
  653. for (var i in data["commands"]) {
  654. this.commands.data[i] = new SlackCommand(this, data["commands"][i]);
  655. }
  656. this.commands.version = t;
  657. }
  658. if (data["team"]) {
  659. if (!this.team) this.team = new SlackTeam(data["team"]["id"]);
  660. this.team.update(data["team"], t);
  661. }
  662. this.staticV = Math.max(this.staticV, t);
  663. if (data["self"]) {
  664. this.self = this.getMember(data["self"]["id"]);
  665. if (!this.self.prefs) this.self.prefs = new SelfPreferences();
  666. this.self.prefs.update(data["self"]["prefs"], t);
  667. }
  668. if (data["typing"] !== undefined) {
  669. this.typing = {};
  670. for (var i in data["typing"]) {
  671. this.typing[i] = {};
  672. for (var j in data["typing"][i])
  673. this.typing[i][j] = t;
  674. }
  675. }
  676. };
  677. SelfPreferences.prototype.toStatic = function(t) {
  678. return this.version > t ? null : {
  679. "emoji_use": JSON.stringify(this.favoriteEmojis)
  680. ,"highlights": this.highlights
  681. };
  682. }
  683. /**
  684. * @param {string} appId
  685. * @return {Array.<SlackBot>}
  686. **/
  687. SlackData.prototype.getBotsByAppId = function(appId) {
  688. var bots = [];
  689. for (var botId in this.bots) {
  690. if (this.bots[botId].appId === appId) {
  691. bots.push(this.bots[botId]);
  692. }
  693. }
  694. return bots;
  695. };
  696. /**
  697. * @param {string} mId
  698. * @return {SlackUser|SlackBot|null}
  699. **/
  700. SlackData.prototype.getMember = function(mId) {
  701. return this.users[mId] || this.bots[mId] || null;
  702. };
  703. /**
  704. * @param {string} chanId
  705. * @return {SlackChan|SlackGroup|SlackIms|null}
  706. **/
  707. SlackData.prototype.getChannel = function(chanId) {
  708. return this.channels[chanId] || this.ims[chanId] || this.groups[chanId] || null;
  709. };
  710. /**
  711. * @param {function((SlackGroup|SlackIms|SlackChan)):(boolean|undefined)} cb should return false to stop iterating
  712. * @return {boolean} true if iterated through all entities
  713. **/
  714. SlackData.prototype.forEachChans = function(cb) {
  715. for (var i in this.channels) {
  716. if (cb(this.channels[i]) === false) return false;
  717. }
  718. for (var i in this.ims) {
  719. if (!cb(this.ims[i]) === false) return false;
  720. }
  721. for (var i in this.groups) {
  722. if (!cb(this.groups[i]) === false) return false;
  723. }
  724. return true;
  725. }
  726. /** @return {Object} */
  727. SlackData.prototype.buildStatic = function(t, now) {
  728. var res = {
  729. "team": this.team.toStatic(t)
  730. ,"channels": []
  731. ,"groups": []
  732. ,"ims": []
  733. ,"users": []
  734. ,"bots": []
  735. ,"self": {
  736. "id": this.self.id
  737. ,"prefs": this.self.prefs.toStatic(t)
  738. }
  739. ,"emojis": this.emojis.version > t ? this.emojis.data : undefined
  740. ,"commands": undefined
  741. ,"typing": undefined
  742. };
  743. if (this.commands.version > t) {
  744. res["commands"] = {};
  745. for (var i in this.commands.data)
  746. res["commands"][i] = this.commands.data[i].toStatic(t);
  747. }
  748. for (var chanId in this.channels) {
  749. var chan = this.channels[chanId].toStatic(t);
  750. if (chan)
  751. res["channels"].push(chan);
  752. }
  753. for (var userId in this.users) {
  754. var user = this.users[userId].toStatic(t)
  755. ,ims = this.users[userId].ims.toStatic(t);
  756. if (user)
  757. res["users"].push(user);
  758. if (ims)
  759. res["ims"].push(ims);
  760. }
  761. for (var botId in this.bots) {
  762. var bot = this.bots[botId].toStatic(t);
  763. if (bot)
  764. res["bots"].push(bot);
  765. }
  766. for (var groupId in this.groups) {
  767. var group = this.groups[groupId].toStatic(t);
  768. if (group)
  769. res["groups"].push(group);
  770. }
  771. for (var typingChan in this.typing) {
  772. var tChan = null;
  773. for (var typingUser in this.typing[typingChan]) {
  774. if (this.typing[typingChan][typingUser] +3000 >= now) {
  775. if (!tChan) tChan = {};
  776. tChan[typingUser] = 1;
  777. } else {
  778. delete this.typing[typingChan][typingUser];
  779. }
  780. }
  781. if (tChan) {
  782. if (res["typing"] === undefined)
  783. res["typing"] = {};
  784. res["typing"][typingChan] = tChan;
  785. }
  786. else
  787. delete this.typing[typingChan];
  788. }
  789. return res;
  790. };
  791. SlackData.prototype.cleanTyping = function(t) {
  792. var updated = false;
  793. for (var typingChan in this.typing) {
  794. var chanEmpty = true;
  795. for (var typingUser in this.typing[typingChan]) {
  796. if (this.typing[typingChan][typingUser] +3000 < t) {
  797. delete this.typing[typingChan][typingUser];
  798. updated = true;
  799. } else {
  800. chanEmpty = false;
  801. }
  802. }
  803. if (chanEmpty) {
  804. delete this.typing[typingChan];
  805. updated = true;
  806. }
  807. }
  808. return updated;
  809. }
  810. /**
  811. * @param {*} msg
  812. * @param {number} t
  813. **/
  814. SlackData.prototype.onMessage = function(msg, t) {
  815. if (msg["type"] === "presence_change") {
  816. var member = this.getMember(msg["user"]);
  817. if (member)
  818. member.setPresence(msg["presence"], t);
  819. this.staticV = Math.max(this.staticV, t);
  820. } else if (msg["type"] === "user_typing") {
  821. this.typing[msg["channel"]] = this.typing[msg["channel"]] || {};
  822. this.typing[msg["channel"]][msg["user"]] = t;
  823. this.staticV = Math.max(this.staticV, t);
  824. } else if (msg["type"] === "im_marked" || msg["type"] === "channel_marked" || msg["type"] === "group_marked") {
  825. var channel = this.getChannel(msg["channel"]);
  826. if (channel) {
  827. channel.lastRead = parseFloat(msg["ts"]);
  828. this.staticV = channel.version = t;
  829. }
  830. }
  831. }
  832. /**
  833. * @param {number} knownVersion
  834. * @param {number} now time at update check
  835. * @return {Object|undefined}
  836. **/
  837. SlackData.prototype.getUpdates = function(knownVersion, now) {
  838. if (this.staticV > knownVersion)
  839. return this.buildStatic(knownVersion, now);
  840. return undefined;
  841. };
  842. /** @suppress {undefinedVars,checkTypes} */
  843. (function() {
  844. if (typeof module !== "undefined") {
  845. module.exports.SlackData = SlackData;
  846. }
  847. })();