slackData.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  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. }
  33. SlackTeam.prototype.update = function(teamData) {
  34. this.name = teamData["name"];
  35. this.domain = teamData["domain"];
  36. this.callApp = teamData["prefs"]["calling_app_id"];
  37. this.callAppName = teamData["prefs"]["calling_app_name"];
  38. this.fileUploadPermission = teamData["prefs"]["disable_file_uploads"];
  39. this.fileEditPermission = teamData["prefs"]["disable_file_editing"];
  40. this.fileDeletePermission = teamData["prefs"]["disable_file_deleting"];
  41. this.icons.image_34 = teamData["icon"]["image_34"];
  42. this.icons.image_44 = teamData["icon"]["image_44"];
  43. this.icons.image_68 = teamData["icon"]["image_68"];
  44. this.icons.image_88 = teamData["icon"]["image_88"];
  45. this.icons.image_102 = teamData["icon"]["image_102"];
  46. this.icons.image_132 = teamData["icon"]["image_132"];
  47. this.icons.image_230 = teamData["icon"]["image_230"];
  48. this.icons.image_default = teamData["icon"]["image_default"];
  49. }
  50. /**
  51. * @constructor
  52. **/
  53. function SlackChan(chanId) {
  54. /** @const @type {string} */
  55. this.id = chanId;
  56. /** @type {string} */
  57. this.name;
  58. /** @type {string} */
  59. this.created;
  60. /** @type {SlackUser|SlackBot} */
  61. this.creator;
  62. /** @type {boolean} */
  63. this.archived;
  64. /** @type {boolean} */
  65. this.isMember;
  66. /** @type {number} */
  67. this.lastRead;
  68. /** @type {Object.<string, SlackBot|SlackUser>} */
  69. this.members = {};
  70. /** @type {string|undefined} */
  71. this.topic;
  72. /** @type {number|undefined} */
  73. this.topicTs;
  74. /** @type {SlackUser|SlackBot|undefined} */
  75. this.topicCreator;
  76. /** @type {string|undefined} */
  77. this.purpose;
  78. /** @type {number|undefined} */
  79. this.purposeTs;
  80. /** @type {SlackUser|SlackBot|undefined} */
  81. this.purposeCreator;
  82. }
  83. /**
  84. * @param {*} chanData
  85. * @param {SlackData} slackData
  86. **/
  87. SlackChan.prototype.update = function(chanData, slackData) {
  88. this.name = chanData["name"];
  89. this.created = chanData["created"];
  90. this.creator = slackData.getMember(chanData["creator"]);
  91. this.archived = chanData["is_archived"];
  92. this.isMember = chanData["is_member"];
  93. this.lastRead = parseFloat(chanData["last_read"]);
  94. this.members = {};
  95. if (chanData["members"]) for (var i =0, nbMembers = chanData["members"].length; i < nbMembers; i++) {
  96. var member = slackData.getMember(chanData["members"][i]);
  97. this.members[member.id] = member;
  98. member.channels[this.id] = this;
  99. }
  100. if (chanData["topic"]) {
  101. this.topic = chanData["topic"]["value"];
  102. this.topicCreator = slackData.getMember(chanData["topic"]["creator"]);
  103. this.topicTs = chanData["topic"]["last_set"];
  104. }
  105. if (chanData["purpose"]) {
  106. this.purpose = chanData["purpose"]["value"];
  107. this.purposeCreator = slackData.getMember(chanData["purpose"]["creator"]);
  108. this.purposeTs = chanData["purpose"]["last_set"];
  109. }
  110. }
  111. /**
  112. * @constructor
  113. * @param {string} id
  114. **/
  115. function SlackGroup(id) {
  116. /** @const @type {string} */
  117. this.id = id;
  118. /** @type {Object.<string, SlackUser|SlackBot>} */
  119. this.members = {};
  120. /** @type {string} */
  121. this.name;
  122. /** @type {number} */
  123. this.created;
  124. /** @type {SlackUser|SlackBot} */
  125. this.creator;
  126. /** @type {boolean} */
  127. this.archived;
  128. /** @type {number} */
  129. this.lastRead;
  130. /** @type {string|undefined} */
  131. this.topic;
  132. /** @type {number|undefined} */
  133. this.topicTs;
  134. /** @type {SlackUser|SlackBot|undefined} */
  135. this.topicCreator;
  136. /** @type {string|undefined} */
  137. this.purpose;
  138. /** @type {number|undefined} */
  139. this.purposeTs;
  140. /** @type {SlackUser|SlackBot|undefined} */
  141. this.purposeCreator;
  142. }
  143. /**
  144. * @param {SlackData} slack
  145. * @param {*} groupData
  146. **/
  147. SlackGroup.prototype.update = function(slack, groupData) {
  148. var memberNames = [];
  149. /** @type {Object.<string, SlackUser|SlackBot>} */
  150. this.members = {};
  151. for (var i =0, nbMembers = groupData["members"].length; i < nbMembers; i++) {
  152. var member = slack.getMember(groupData["members"][i]);
  153. this.members[groupData["members"][i]] = member;
  154. member.channels[this.id] = this;
  155. memberNames.push(member.name);
  156. }
  157. this.name = memberNames.join(", ");
  158. this.created = groupData["created"];
  159. this.creator = slack.getMember(groupData["creator"]);
  160. this.archived = groupData["is_archived"];
  161. this.lastRead = parseFloat(groupData["last_read"]);
  162. if (groupData["topic"]) {
  163. this.topic = groupData["topic"]["value"];
  164. this.topicCreator = slack.getMember(groupData["topic"]["creator"]);
  165. this.topicTs = groupData["topic"]["last_set"];
  166. }
  167. if (groupData["purpose"]) {
  168. this.purpose = groupData["purpose"]["value"];
  169. this.purposeCreator = slack.getMember(groupData["purpose"]["creator"]);
  170. this.purposeTs = groupData["purpose"]["last_set"];
  171. }
  172. }
  173. /**
  174. * @constructor
  175. * @param {string} id
  176. * @param {SlackUser|SlackBot} user
  177. **/
  178. function SlackIms(id, user) {
  179. /** @const @type {string} */
  180. this.id = id;
  181. /** @type {number} */
  182. this.created;
  183. /** @type {SlackUser|SlackBot} */
  184. this.user = user;
  185. /** @type {number} */
  186. this.lastRead;
  187. /** @type {boolean} */
  188. this.archived;
  189. }
  190. /**
  191. * @param {SlackUser|SlackBot} user
  192. * @param {*} imsData
  193. **/
  194. SlackIms.prototype.update = function(user, imsData) {
  195. this.created = imsData["created"];
  196. this.lastRead = parseFloat(imsData["last_read"]);
  197. this.archived = user.deleted;
  198. }
  199. /**
  200. * @constructor
  201. **/
  202. function SlackUser(id) {
  203. /** @const @type {string} */
  204. this.id = id;
  205. /** @type {string} */
  206. this.name;
  207. /** @type {boolean} */
  208. this.deleted;
  209. /** @type {string} */
  210. this.status;
  211. /** @type {string} */
  212. this.realName;
  213. /** @type {boolean} */
  214. this.presence;
  215. /** @type {Object.<string, string>} */
  216. this.icons = {
  217. image_24: ""
  218. ,image_32: ""
  219. ,image_48: ""
  220. ,image_72: ""
  221. ,image_192: ""
  222. ,image_512: ""
  223. };
  224. /** @type {string} */
  225. this.email;
  226. /** @type {string} */
  227. this.firstName;
  228. /** @type {string} */
  229. this.lastName;
  230. /** @type {!Object.<string, SlackChan|SlackGroup>} */
  231. this.channels = {};
  232. /** @type {SlackIms} */
  233. this.ims = null;
  234. /** @type {SelfPreferences|null} */
  235. this.prefs = null;
  236. }
  237. /**
  238. * @param {*} userData
  239. **/
  240. SlackUser.prototype.update = function(userData) {
  241. this.name = userData["name"];
  242. this.deleted = userData["deleted"];
  243. this.status = userData["status"];
  244. this.realName = userData["real_name"] || userData["profile"]["real_name"];
  245. this.presence = userData["presence"] !== 'away';
  246. this.icons.image_24 = userData["profile"]["image_24"];
  247. this.icons.image_32 = userData["profile"]["image_32"];
  248. this.icons.image_48 = userData["profile"]["image_48"];
  249. this.icons.image_72 = userData["profile"]["image_72"];
  250. this.icons.image_192 = userData["profile"]["image_192"];
  251. this.icons.image_512 = userData["profile"]["image_512"];
  252. this.email = userData["profile"]["email"];
  253. this.firstName = userData["profile"]["first_name"];
  254. this.lastName = userData["profile"]["last_name"];
  255. }
  256. /**
  257. * @constructor
  258. **/
  259. function SelfPreferences() {
  260. /** @type {Object.<string, number>} */
  261. this.favoriteEmojis = {};
  262. /** @type {Array.<string>} */
  263. this.highlights = [];
  264. }
  265. /**
  266. * @param {*} prefs
  267. **/
  268. SelfPreferences.prototype.update = function(prefs) {
  269. this.favoriteEmojis = /** @type {Object<string,number>} */ (JSON.parse(prefs["emoji_use"]));
  270. if (prefs["highlight_words"])
  271. this.highlights = (prefs["highlight_words"]||"").split(',').filter(function(i) {
  272. return i.trim() !== '';
  273. });
  274. else if (prefs["highlights"])
  275. this.highlights = prefs["highlights"];
  276. }
  277. /**
  278. * @constructor
  279. **/
  280. function SlackBot(id) {
  281. /** @const @type {string} */
  282. this.id = id;
  283. /** @type {boolean} */
  284. this.deleted;
  285. /** @type {string} */
  286. this.name;
  287. /** @type {string} */
  288. this.appId;
  289. /** @type {Object.<string, string>} */
  290. this.icons = {
  291. image_36: ""
  292. ,image_48: ""
  293. ,image_72: ""
  294. };
  295. /** @type {!Object.<string, SlackGroup|SlackChan>} */
  296. this.channels;
  297. /** @type {SlackIms|null} */
  298. this.ims = null;
  299. /** @type {SelfPreferences|null} */
  300. this.prefs = null;
  301. }
  302. /** @param {*} botData */
  303. SlackBot.prototype.update = function(botData) {
  304. this.deleted = botData["deleted"];
  305. this.name = botData["name"];
  306. this.appId = botData["app_id"];
  307. this.icons.image_36 = botData["icons"]["image_36"]
  308. this.icons.image_48 = botData["icons"]["image_48"]
  309. this.icons.image_72 = botData["icons"]["image_72"]
  310. }
  311. /**
  312. * @constructor
  313. **/
  314. function SlackData(slack) {
  315. /** @type {SlackTeam} */
  316. this.team = null;
  317. /** @type {Object.<string, SlackChan>} */
  318. this.channels = {};
  319. /** @type {Object.<string, SlackGroup>} */
  320. this.groups = {};
  321. /** @type {Object.<string, SlackIms>} */
  322. this.ims = {};
  323. /** @type {Object.<string, SlackUser>} */
  324. this.users = {};
  325. /** @type {SlackUser|SlackBot} */
  326. this.self = null;
  327. /** @type {Object.<string, SlackBot>} */
  328. this.bots = {};
  329. /** @type {Object.<string, string>} */
  330. this.emojis = {};
  331. /**
  332. * Node serv handler
  333. * @type {*}
  334. **/
  335. this.slack = slack;
  336. /** @type {number} */
  337. this.staticV = 0;
  338. /** @type {number} */
  339. this.liveV = 0;
  340. }
  341. /**
  342. * @return {Object}
  343. **/
  344. SlackTeam.prototype.toStatic = function() {
  345. return {
  346. "id": this.id
  347. ,"name": this.name
  348. ,"domain": this.domain
  349. ,"prefs": {
  350. "calling_app_id": this.callApp
  351. ,"calling_app_name": this.callAppName
  352. ,"disable_file_uploads": this.fileUploadPermission
  353. ,"disable_file_editing": this.fileEditPermission
  354. ,"disable_file_deleting": this.fileDeletePermission
  355. }
  356. ,"icon": this.icons
  357. };
  358. };
  359. /**
  360. * @return {Object}
  361. **/
  362. SlackChan.prototype.toStatic = function() {
  363. var res = {
  364. "id": this.id
  365. ,"name": this.name
  366. ,"created": this.created
  367. ,"creator": this.creator.id
  368. ,"is_archived": this.archived
  369. ,"is_member": this.isMember
  370. ,"last_read": this.lastRead
  371. };
  372. if (this.isMember) {
  373. res["members"] = this.members ? Object.keys(this.members) : [];
  374. res["topic"] = {
  375. "value": this.topic
  376. ,"creator": this.topicCreator ? this.topicCreator.id : null
  377. ,"last_set": this.topicTs
  378. }
  379. res["purpose"] = {
  380. "value": this.purpose
  381. ,"creator": this.purposeCreator ? this.purposeCreator.id : null
  382. ,"last_set": this.purposeTs
  383. }
  384. }
  385. return res;
  386. };
  387. /**
  388. * @return {Object}
  389. **/
  390. SlackUser.prototype.toStatic = function() {
  391. return {
  392. "id": this.id
  393. ,"name": this.name
  394. ,"deleted": this.deleted
  395. ,"status": this.status
  396. ,"real_name": this.realName
  397. ,"profile": {
  398. "email": this.email
  399. ,"first_name": this.firstName
  400. ,"last_name": this.lastName
  401. ,"image_24": this.icons.image_24
  402. ,"image_32": this.icons.image_32
  403. ,"image_48": this.icons.image_48
  404. ,"image_72": this.icons.image_72
  405. ,"image_192": this.icons.image_192
  406. ,"image_512": this.icons.image_512
  407. }
  408. };
  409. };
  410. SlackGroup.prototype.toStatic = function() {
  411. var res = {
  412. "id": this.id
  413. ,"members": []
  414. ,"created": this.created
  415. ,"creator": this.creator.id
  416. ,"is_archived": this.archived
  417. ,"last_read": this.lastRead
  418. };
  419. for (var mId in this.members) {
  420. res["members"].push(mId);
  421. }
  422. if (this.topic) {
  423. res["topic"] = {
  424. "value": this.topic
  425. ,"creator": this.topicCreator.id
  426. ,"last_set": this.topicTs
  427. };
  428. }
  429. if (this.purpose) {
  430. res["purpose"] = {
  431. "value": this.purpose
  432. ,"creator": this.purposeCreator.id
  433. ,"last_set": this.purposeTs
  434. };
  435. }
  436. return res;
  437. };
  438. SlackIms.prototype.toStatic = function() {
  439. return {
  440. "id": this.id
  441. ,"created": this.created
  442. ,"user": this.user.id
  443. ,"last_read": this.lastRead
  444. };
  445. }
  446. SlackBot.prototype.toStatic = function() {
  447. return {
  448. "id": this.id
  449. ,"deleted": this.deleted
  450. ,"name": this.name
  451. ,"app_id": this.appId
  452. ,"icons": {
  453. "image_36": this.icons.image_36
  454. ,"image_48": this.icons.image_48
  455. ,"image_72": this.icons.image_72
  456. }
  457. };
  458. }
  459. /**
  460. * @param {*} data
  461. **/
  462. SlackData.prototype.updateStatic = function(data) {
  463. if (data["bots"]) for (var i =0, nbBots = data["bots"].length; i < nbBots; i++) {
  464. var botObj = this.bots[data["bots"][i]["id"]];
  465. if (!botObj)
  466. botObj = this.bots[data["bots"][i]["id"]] = new SlackBot(data["bots"][i]["id"]);
  467. botObj.update(data["bots"][i]);
  468. }
  469. if (data["users"]) for (var i =0, nbUsers = data["users"].length; i < nbUsers; i++) {
  470. var userObj = this.users[data["users"][i]["id"]];
  471. if (!userObj)
  472. userObj = this.users[data["users"][i]["id"]] = new SlackUser(data["users"][i]["id"]);
  473. userObj.update(data["users"][i]);
  474. }
  475. if (data["ims"]) for (var i =0, nbIms = data["ims"].length; i < nbIms; i++) {
  476. var user = this.getMember(data["ims"][i]["user"]);
  477. if (user) {
  478. if (!user.ims)
  479. this.ims[data["ims"][i]["id"]] = user.ims = new SlackIms(data["ims"][i]["id"], user);
  480. user.ims.update(user, data["ims"][i]);
  481. }
  482. }
  483. if (data["channels"]) for (var i =0, nbChan = data["channels"].length; i < nbChan; i++) {
  484. var chanObj = this.channels[data["channels"][i]["id"]];
  485. if (!chanObj)
  486. chanObj = this.channels[data["channels"][i]["id"]] = new SlackChan(data["channels"][i]["id"]);
  487. chanObj.update(data["channels"][i], this);
  488. }
  489. for (var i =0, nbGroups = data["groups"].length; i < nbGroups; i++) {
  490. var groupObj = this.groups[data["groups"][i]["id"]];
  491. if (!groupObj)
  492. groupObj = this.groups[data["groups"][i]["id"]] = new SlackGroup(data["groups"][i]["id"]);
  493. groupObj.update(this, data["groups"][i]);
  494. }
  495. if (data["emojis"]) this.emojis = data["emojis"];
  496. if (!this.team) this.team = new SlackTeam(data["team"]["id"]);
  497. this.team.update(data["team"]);
  498. this.staticV = parseFloat(data["latest_event_ts"]);
  499. if (data["self"]) {
  500. this.self = this.getMember(data["self"]["id"]);
  501. if (!this.self.prefs) this.self.prefs = new SelfPreferences();
  502. this.self.prefs.update(data["self"]["prefs"]);
  503. }
  504. };
  505. SelfPreferences.prototype.toStatic = function() {
  506. return {
  507. "emoji_use": JSON.stringify(this.favoriteEmojis)
  508. ,"highlights": this.highlights
  509. };
  510. }
  511. /**
  512. * @param {string} appId
  513. * @return {Array.<SlackBot>}
  514. **/
  515. SlackData.prototype.getBotsByAppId = function(appId) {
  516. var bots = [];
  517. for (var botId in this.bots) {
  518. if (this.bots[botId].appId === appId) {
  519. bots.push(this.bots[botId]);
  520. }
  521. }
  522. return bots;
  523. };
  524. /**
  525. * @param {string} mId
  526. * @return {SlackUser|SlackBot|null}
  527. **/
  528. SlackData.prototype.getMember = function(mId) {
  529. return this.users[mId] || this.bots[mId] || null;
  530. };
  531. /**
  532. * @param {string} chanId
  533. * @return {SlackChan|SlackGroup|SlackIms|null}
  534. **/
  535. SlackData.prototype.getChannel = function(chanId) {
  536. return this.channels[chanId] || this.ims[chanId] || this.groups[chanId] || null;
  537. };
  538. /** @return {Object} */
  539. SlackData.prototype.buildStatic = function() {
  540. var res = {
  541. "team": this.team.toStatic()
  542. ,"channels": []
  543. ,"groups": []
  544. ,"ims": []
  545. ,"users": []
  546. ,"bots": []
  547. ,"self": {
  548. "id": this.self.id
  549. ,"prefs": this.self.prefs.toStatic()
  550. }
  551. ,"emojis": this.emojis
  552. };
  553. for (var chanId in this.channels) {
  554. res["channels"].push(this.channels[chanId].toStatic());
  555. }
  556. for (var userId in this.users) {
  557. res["users"].push(this.users[userId].toStatic());
  558. res["ims"].push(this.users[userId].ims.toStatic());
  559. }
  560. for (var botId in this.bots) {
  561. res["bots"].push(this.bots[botId].toStatic());
  562. }
  563. for (var groupId in this.groups) {
  564. res["groups"].push(this.groups[groupId].toStatic());
  565. }
  566. return res;
  567. };
  568. /**
  569. * @param {Object} msg
  570. * @return {boolean}
  571. **/
  572. SlackData.prototype.onMessage = function(msg) {
  573. //TODO
  574. return false;
  575. };
  576. /**
  577. * @param {number} knownVersion
  578. * @return {Object|undefined}
  579. **/
  580. SlackData.prototype.getUpdates = function(knownVersion) {
  581. return (this.staticV > knownVersion) ? this.buildStatic() : undefined;
  582. };
  583. /** @suppress {undefinedVars,checkTypes} */
  584. (function() {
  585. if (typeof module !== "undefined") {
  586. module.exports.SlackData = SlackData;
  587. }
  588. })();