slackData.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  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. }
  188. /**
  189. * @param {*} imsData
  190. **/
  191. SlackIms.prototype.update = function(imsData) {
  192. this.created = imsData["created"];
  193. this.lastRead = parseFloat(imsData["last_read"]);
  194. }
  195. /**
  196. * @constructor
  197. **/
  198. function SlackUser(id) {
  199. /** @const @type {string} */
  200. this.id = id;
  201. /** @type {string} */
  202. this.name;
  203. /** @type {boolean} */
  204. this.deleted;
  205. /** @type {string} */
  206. this.status;
  207. /** @type {string} */
  208. this.realName;
  209. /** @type {boolean} */
  210. this.presence;
  211. /** @type {Object.<string, string>} */
  212. this.icons = {
  213. image_24: ""
  214. ,image_32: ""
  215. ,image_48: ""
  216. ,image_72: ""
  217. ,image_192: ""
  218. ,image_512: ""
  219. };
  220. /** @type {string} */
  221. this.email;
  222. /** @type {string} */
  223. this.firstName;
  224. /** @type {string} */
  225. this.lastName;
  226. /** @type {!Object.<string, SlackChan|SlackGroup>} */
  227. this.channels = {};
  228. /** @type {SlackIms} */
  229. this.ims = null;
  230. /** @type {SelfPreferences|null} */
  231. this.prefs = null;
  232. }
  233. /**
  234. * @param {*} userData
  235. **/
  236. SlackUser.prototype.update = function(userData) {
  237. this.name = userData["name"];
  238. this.deleted = userData["deleted"];
  239. this.status = userData["status"];
  240. this.realName = userData["real_name"] || userData["profile"]["real_name"];
  241. this.presence = userData["presence"] !== 'away';
  242. this.icons.image_24 = userData["profile"]["image_24"];
  243. this.icons.image_32 = userData["profile"]["image_32"];
  244. this.icons.image_48 = userData["profile"]["image_48"];
  245. this.icons.image_72 = userData["profile"]["image_72"];
  246. this.icons.image_192 = userData["profile"]["image_192"];
  247. this.icons.image_512 = userData["profile"]["image_512"];
  248. this.email = userData["profile"]["email"];
  249. this.firstName = userData["profile"]["first_name"];
  250. this.lastName = userData["profile"]["last_name"];
  251. }
  252. /**
  253. * @constructor
  254. **/
  255. function SelfPreferences() {
  256. /** @type {Object.<string, number>} */
  257. this.favoriteEmojis = {};
  258. /** @type {Array.<string>} */
  259. this.highlights = [];
  260. }
  261. /**
  262. * @param {*} prefs
  263. **/
  264. SelfPreferences.prototype.update = function(prefs) {
  265. this.favoriteEmojis = /** @type {Object<string,number>} */ (JSON.parse(prefs["emoji_use"]));
  266. if (prefs["highlight_words"])
  267. this.highlights = (prefs["highlight_words"]||"").split(',').filter(function(i) {
  268. return i.trim() !== '';
  269. });
  270. else if (prefs["highlights"])
  271. this.highlights = prefs["highlights"];
  272. }
  273. /**
  274. * @constructor
  275. **/
  276. function SlackBot(id) {
  277. /** @const @type {string} */
  278. this.id = id;
  279. /** @type {boolean} */
  280. this.deleted;
  281. /** @type {string} */
  282. this.name;
  283. /** @type {string} */
  284. this.appId;
  285. /** @type {Object.<string, string>} */
  286. this.icons = {
  287. image_36: ""
  288. ,image_48: ""
  289. ,image_72: ""
  290. };
  291. /** @type {!Object.<string, SlackGroup|SlackChan>} */
  292. this.channels;
  293. /** @type {SlackIms|null} */
  294. this.ims = null;
  295. /** @type {SelfPreferences|null} */
  296. this.prefs = null;
  297. }
  298. /** @param {*} botData */
  299. SlackBot.prototype.update = function(botData) {
  300. this.deleted = botData["deleted"];
  301. this.name = botData["name"];
  302. this.appId = botData["app_id"];
  303. this.icons.image_36 = botData["icons"]["image_36"]
  304. this.icons.image_48 = botData["icons"]["image_48"]
  305. this.icons.image_72 = botData["icons"]["image_72"]
  306. }
  307. /**
  308. * @constructor
  309. **/
  310. function SlackData(slack) {
  311. /** @type {SlackTeam} */
  312. this.team = null;
  313. /** @type {Object.<string, SlackChan>} */
  314. this.channels = {};
  315. /** @type {Object.<string, SlackGroup>} */
  316. this.groups = {};
  317. /** @type {Object.<string, SlackIms>} */
  318. this.ims = {};
  319. /** @type {Object.<string, SlackUser>} */
  320. this.users = {};
  321. /** @type {SlackUser|SlackBot} */
  322. this.self = null;
  323. /** @type {Object.<string, SlackBot>} */
  324. this.bots = {};
  325. /** @type {Object.<string, string>} */
  326. this.emojis = {};
  327. /**
  328. * Node serv handler
  329. * @type {*}
  330. **/
  331. this.slack = slack;
  332. /** @type {number} */
  333. this.staticV = 0;
  334. /** @type {number} */
  335. this.liveV = 0;
  336. }
  337. /**
  338. * @return {Object}
  339. **/
  340. SlackTeam.prototype.toStatic = function() {
  341. return {
  342. "id": this.id
  343. ,"name": this.name
  344. ,"domain": this.domain
  345. ,"prefs": {
  346. "calling_app_id": this.callApp
  347. ,"calling_app_name": this.callAppName
  348. ,"disable_file_uploads": this.fileUploadPermission
  349. ,"disable_file_editing": this.fileEditPermission
  350. ,"disable_file_deleting": this.fileDeletePermission
  351. }
  352. ,"icon": this.icons
  353. };
  354. };
  355. /**
  356. * @return {Object}
  357. **/
  358. SlackChan.prototype.toStatic = function() {
  359. var res = {
  360. "id": this.id
  361. ,"name": this.name
  362. ,"created": this.created
  363. ,"creator": this.creator.id
  364. ,"is_archived": this.archived
  365. ,"is_member": this.isMember
  366. ,"last_read": this.lastRead
  367. };
  368. if (this.isMember) {
  369. res["members"] = this.members ? Object.keys(this.members) : [];
  370. res["topic"] = {
  371. "value": this.topic
  372. ,"creator": this.topicCreator ? this.topicCreator.id : null
  373. ,"last_set": this.topicTs
  374. }
  375. res["purpose"] = {
  376. "value": this.purpose
  377. ,"creator": this.purposeCreator ? this.purposeCreator.id : null
  378. ,"last_set": this.purposeTs
  379. }
  380. }
  381. return res;
  382. };
  383. /**
  384. * @return {Object}
  385. **/
  386. SlackUser.prototype.toStatic = function() {
  387. return {
  388. "id": this.id
  389. ,"name": this.name
  390. ,"deleted": this.deleted
  391. ,"status": this.status
  392. ,"real_name": this.realName
  393. ,"profile": {
  394. "email": this.email
  395. ,"first_name": this.firstName
  396. ,"last_name": this.lastName
  397. ,"image_24": this.icons.image_24
  398. ,"image_32": this.icons.image_32
  399. ,"image_48": this.icons.image_48
  400. ,"image_72": this.icons.image_72
  401. ,"image_192": this.icons.image_192
  402. ,"image_512": this.icons.image_512
  403. }
  404. };
  405. };
  406. SlackGroup.prototype.toStatic = function() {
  407. var res = {
  408. "id": this.id
  409. ,"members": []
  410. ,"created": this.created
  411. ,"creator": this.creator.id
  412. ,"is_archived": this.archived
  413. ,"last_read": this.lastRead
  414. };
  415. for (var mId in this.members) {
  416. res["members"].push(mId);
  417. }
  418. if (this.topic) {
  419. res["topic"] = {
  420. "value": this.topic
  421. ,"creator": this.topicCreator.id
  422. ,"last_set": this.topicTs
  423. };
  424. }
  425. if (this.purpose) {
  426. res["purpose"] = {
  427. "value": this.purpose
  428. ,"creator": this.purposeCreator.id
  429. ,"last_set": this.purposeTs
  430. };
  431. }
  432. return res;
  433. };
  434. SlackIms.prototype.toStatic = function() {
  435. return {
  436. "id": this.id
  437. ,"created": this.created
  438. ,"user": this.user.id
  439. ,"last_read": this.lastRead
  440. };
  441. }
  442. SlackBot.prototype.toStatic = function() {
  443. return {
  444. "id": this.id
  445. ,"deleted": this.deleted
  446. ,"name": this.name
  447. ,"app_id": this.appId
  448. ,"icons": {
  449. "image_36": this.icons.image_36
  450. ,"image_48": this.icons.image_48
  451. ,"image_72": this.icons.image_72
  452. }
  453. };
  454. }
  455. /**
  456. * @param {*} data
  457. **/
  458. SlackData.prototype.updateStatic = function(data) {
  459. if (data["bots"]) for (var i =0, nbBots = data["bots"].length; i < nbBots; i++) {
  460. var botObj = this.bots[data["bots"][i]["id"]];
  461. if (!botObj)
  462. botObj = this.bots[data["bots"][i]["id"]] = new SlackBot(data["bots"][i]["id"]);
  463. botObj.update(data["bots"][i]);
  464. }
  465. if (data["users"]) for (var i =0, nbUsers = data["users"].length; i < nbUsers; i++) {
  466. var userObj = this.users[data["users"][i]["id"]];
  467. if (!userObj)
  468. userObj = this.users[data["users"][i]["id"]] = new SlackUser(data["users"][i]["id"]);
  469. userObj.update(data["users"][i]);
  470. }
  471. if (data["ims"]) for (var i =0, nbIms = data["ims"].length; i < nbIms; i++) {
  472. var user = this.getMember(data["ims"][i]["user"]);
  473. if (user) {
  474. if (!user.ims)
  475. this.ims[data["ims"][i]["id"]] = user.ims = new SlackIms(data["ims"][i]["id"], user);
  476. user.ims.update(data["ims"][i]);
  477. }
  478. }
  479. if (data["channels"]) for (var i =0, nbChan = data["channels"].length; i < nbChan; i++) {
  480. var chanObj = this.channels[data["channels"][i]["id"]];
  481. if (!chanObj)
  482. chanObj = this.channels[data["channels"][i]["id"]] = new SlackChan(data["channels"][i]["id"]);
  483. chanObj.update(data["channels"][i], this);
  484. }
  485. for (var i =0, nbGroups = data["groups"].length; i < nbGroups; i++) {
  486. var groupObj = this.groups[data["groups"][i]["id"]];
  487. if (!groupObj)
  488. groupObj = this.groups[data["groups"][i]["id"]] = new SlackGroup(data["groups"][i]["id"]);
  489. groupObj.update(this, data["groups"][i]);
  490. }
  491. if (data["emojis"]) this.emojis = data["emojis"];
  492. if (!this.team) this.team = new SlackTeam(data["team"]["id"]);
  493. this.team.update(data["team"]);
  494. this.staticV = parseFloat(data["latest_event_ts"]);
  495. if (data["self"]) {
  496. this.self = this.getMember(data["self"]["id"]);
  497. if (!this.self.prefs) this.self.prefs = new SelfPreferences();
  498. this.self.prefs.update(data["self"]["prefs"]);
  499. }
  500. };
  501. SelfPreferences.prototype.toStatic = function() {
  502. return {
  503. "emoji_use": JSON.stringify(this.favoriteEmojis)
  504. ,"highlights": this.highlights
  505. };
  506. }
  507. /**
  508. * @param {string} appId
  509. * @return {Array.<SlackBot>}
  510. **/
  511. SlackData.prototype.getBotsByAppId = function(appId) {
  512. var bots = [];
  513. for (var botId in this.bots) {
  514. if (this.bots[botId].appId === appId) {
  515. bots.push(this.bots[botId]);
  516. }
  517. }
  518. return bots;
  519. };
  520. /**
  521. * @param {string} mId
  522. * @return {SlackUser|SlackBot|null}
  523. **/
  524. SlackData.prototype.getMember = function(mId) {
  525. return this.users[mId] || this.bots[mId] || null;
  526. };
  527. /**
  528. * @param {string} chanId
  529. * @return {SlackChan|SlackGroup|SlackIms|null}
  530. **/
  531. SlackData.prototype.getChannel = function(chanId) {
  532. return this.channels[chanId] || this.ims[chanId] || this.groups[chanId] || null;
  533. };
  534. /** @return {Object} */
  535. SlackData.prototype.buildStatic = function() {
  536. var res = {
  537. "team": this.team.toStatic()
  538. ,"channels": []
  539. ,"groups": []
  540. ,"ims": []
  541. ,"users": []
  542. ,"bots": []
  543. ,"self": {
  544. "id": this.self.id
  545. ,"prefs": this.self.prefs.toStatic()
  546. }
  547. ,"emojis": this.emojis
  548. };
  549. for (var chanId in this.channels) {
  550. res["channels"].push(this.channels[chanId].toStatic());
  551. }
  552. for (var userId in this.users) {
  553. res["users"].push(this.users[userId].toStatic());
  554. res["ims"].push(this.users[userId].ims.toStatic());
  555. }
  556. for (var botId in this.bots) {
  557. res["bots"].push(this.bots[botId].toStatic());
  558. }
  559. for (var groupId in this.groups) {
  560. res["groups"].push(this.groups[groupId].toStatic());
  561. }
  562. return res;
  563. };
  564. /**
  565. * @param {Object} msg
  566. * @return {boolean}
  567. **/
  568. SlackData.prototype.onMessage = function(msg) {
  569. //TODO
  570. return false;
  571. };
  572. /**
  573. * @param {number} knownVersion
  574. * @return {Object|undefined}
  575. **/
  576. SlackData.prototype.getUpdates = function(knownVersion) {
  577. return (this.staticV > knownVersion) ? this.buildStatic() : undefined;
  578. };
  579. /** @suppress {undefinedVars,checkTypes} */
  580. (function() {
  581. if (typeof module !== "undefined") {
  582. module.exports.SlackData = SlackData;
  583. }
  584. })();