/** * @constructor **/ function SlackTeam(teamId) { /** @const @type {string} */ this.id = teamId; /** @type {string} */ this.name; /** @type {string} */ this.domain; /** @type {string} */ this.callApp; /** @type {string} */ this.callAppName; /** @type {boolean} */ this.fileUploadPermission; /** @type {boolean} */ this.fileEditPermission; /** @type {boolean} */ this.fileDeletePermission; /** @type {Object.} */ this.icons = { image_34: "" ,image_44: "" ,image_68: "" ,image_88: "" ,image_102: "" ,image_132: "" ,image_230: "" ,image_default: "" }; /** @type {number} */ this.version = 0; } SlackTeam.prototype.update = function(teamData, t) { if (teamData["name"] !== undefined) this.name = teamData["name"]; if (teamData["domain"] !== undefined) this.domain = teamData["domain"]; if (teamData["prefs"]) { this.callApp = teamData["prefs"]["calling_app_id"]; this.callAppName = teamData["prefs"]["calling_app_name"]; this.fileUploadPermission = teamData["prefs"]["disable_file_uploads"]; this.fileEditPermission = teamData["prefs"]["disable_file_editing"]; this.fileDeletePermission = teamData["prefs"]["disable_file_deleting"]; } if (teamData["icon"]) { this.icons.image_34 = teamData["icon"]["image_34"]; this.icons.image_44 = teamData["icon"]["image_44"]; this.icons.image_68 = teamData["icon"]["image_68"]; this.icons.image_88 = teamData["icon"]["image_88"]; this.icons.image_102 = teamData["icon"]["image_102"]; this.icons.image_132 = teamData["icon"]["image_132"]; this.icons.image_230 = teamData["icon"]["image_230"]; this.icons.image_default = teamData["icon"]["image_default"]; } this.version = Math.max(this.version, t); } /** * @constructor **/ function SlackChan(chanId) { /** @const @type {string} */ this.id = chanId; /** @type {string} */ this.name; /** @type {string} */ this.created; /** @type {SlackUser|SlackBot} */ this.creator; /** @type {boolean} */ this.archived; /** @type {boolean} */ this.isMember; /** @type {number} */ this.lastRead; /** @type {Object.} */ this.members = {}; /** @type {string|undefined} */ this.topic; /** @type {number|undefined} */ this.topicTs; /** @type {SlackUser|SlackBot|undefined} */ this.topicCreator; /** @type {string|undefined} */ this.purpose; /** @type {number|undefined} */ this.purposeTs; /** @type {SlackUser|SlackBot|undefined} */ this.purposeCreator; /** @type {number} */ this.version = 0; } /** * @param {*} chanData * @param {SlackData} slackData **/ SlackChan.prototype.update = function(chanData, slackData, t) { if (chanData["name"] !== undefined) this.name = chanData["name"]; if (chanData["created"] !== undefined) this.created = chanData["created"]; if (chanData["creator"] !== undefined) this.creator = slackData.getMember(chanData["creator"]); if (chanData["is_archived"] !== undefined) this.archived = chanData["is_archived"]; if (chanData["is_member"] !== undefined) this.isMember = chanData["is_member"]; if (chanData["last_read"] !== undefined) this.lastRead = parseFloat(chanData["last_read"]); if (chanData["members"]) { this.members = {}; if (chanData["members"]) for (var i =0, nbMembers = chanData["members"].length; i < nbMembers; i++) { var member = slackData.getMember(chanData["members"][i]); this.members[member.id] = member; member.channels[this.id] = this; } } if (chanData["topic"]) { this.topic = chanData["topic"]["value"]; this.topicCreator = slackData.getMember(chanData["topic"]["creator"]); this.topicTs = chanData["topic"]["last_set"]; } if (chanData["purpose"]) { this.purpose = chanData["purpose"]["value"]; this.purposeCreator = slackData.getMember(chanData["purpose"]["creator"]); this.purposeTs = chanData["purpose"]["last_set"]; } this.version = Math.max(this.version, t); } /** * @constructor * @param {string} id **/ function SlackGroup(id) { /** @const @type {string} */ this.id = id; /** @type {Object.} */ this.members = {}; /** @type {number} */ this.nbMembers = 0; /** @type {string} */ this.name; /** @type {number} */ this.created; /** @type {SlackUser|SlackBot} */ this.creator; /** @type {boolean} */ this.archived; /** @type {number} */ this.lastRead; /** @type {string|undefined} */ this.topic; /** @type {number|undefined} */ this.topicTs; /** @type {SlackUser|SlackBot|undefined} */ this.topicCreator; /** @type {string|undefined} */ this.purpose; /** @type {number|undefined} */ this.purposeTs; /** @type {SlackUser|SlackBot|undefined} */ this.purposeCreator; /** @type {number} version */ this.version = 0; } /** * @param {SlackData} slack * @param {*} groupData **/ SlackGroup.prototype.update = function(slack, groupData, t) { var memberNames = []; if (groupData["members"]) { /** @type {Object.} */ this.members = {}; this.nbMembers = 0; for (var i =0, nbMembers = groupData["members"].length; i < nbMembers; i++) { var member = slack.getMember(groupData["members"][i]); this.members[groupData["members"][i]] = member; member.channels[this.id] = this; memberNames.push(member.name); this.nbMembers++; } this.name = memberNames.join(", "); } if (groupData["created"] !== undefined) this.created = groupData["created"]; if (groupData["creator"] !== undefined) this.creator = slack.getMember(groupData["creator"]); if (groupData["is_archived"] !== undefined) this.archived = groupData["is_archived"] || groupData["is_open"] === false; if (groupData["last_read"] !== undefined) this.lastRead = parseFloat(groupData["last_read"]); if (groupData["topic"]) { this.topic = groupData["topic"]["value"]; this.topicCreator = slack.getMember(groupData["topic"]["creator"]); this.topicTs = groupData["topic"]["last_set"]; } if (groupData["purpose"]) { this.purpose = groupData["purpose"]["value"]; this.purposeCreator = slack.getMember(groupData["purpose"]["creator"]); this.purposeTs = groupData["purpose"]["last_set"]; } this.version = Math.max(this.version, t); } /** * @constructor * @param {string} id * @param {SlackUser|SlackBot} user **/ function SlackIms(id, user) { /** @const @type {string} */ this.id = id; /** @type {number} */ this.created; /** @type {SlackUser|SlackBot} */ this.user = user; /** @type {number} */ this.lastRead; /** @type {boolean} */ this.archived; /** @type {number} */ this.version = 0; } /** * @param {SlackUser|SlackBot} user * @param {*} imsData **/ SlackIms.prototype.update = function(user, imsData, t) { this.created = imsData["created"]; this.lastRead = parseFloat(imsData["last_read"]); this.archived = user.deleted; this.version = Math.max(this.version, t); } /** * @constructor **/ function SlackUser(id) { /** @const @type {string} */ this.id = id; /** @type {string} */ this.name; /** @type {boolean} */ this.deleted; /** @type {string} */ this.status; /** @type {string} */ this.realName; /** @type {boolean} */ this.presence; /** @type {Object.} */ this.icons = { image_24: "" ,image_32: "" ,image_48: "" ,image_72: "" ,image_192: "" ,image_512: "" }; /** @type {string} */ this.email; /** @type {string} */ this.firstName; /** @type {string} */ this.lastName; /** @type {!Object.} */ this.channels = {}; /** @type {SlackIms} */ this.ims = null; /** @type {SelfPreferences|null} */ this.prefs = null; /** @type {number} */ this.version = 0; } /** * @param {*} userData **/ SlackUser.prototype.update = function(userData, t) { if (userData["name"] !== undefined) this.name = userData["name"]; if (userData["deleted"] !== undefined) this.deleted = userData["deleted"]; if (userData["status"] !== undefined) this.status = userData["status"]; if (userData["real_name"] !== undefined) this.realName = userData["real_name"]; else if (userData["profile"] && userData["profile"]["real_name"] !== undefined) this.realName = userData["profile"]["real_name"]; if (userData["presence"] !== undefined) this.presence = userData["presence"] !== 'away'; if (userData["isPresent"] !== undefined) this.presence = userData["isPresent"]; if (userData["profile"]) { this.icons.image_24 = userData["profile"]["image_24"]; this.icons.image_32 = userData["profile"]["image_32"]; this.icons.image_48 = userData["profile"]["image_48"]; this.icons.image_72 = userData["profile"]["image_72"]; this.icons.image_192 = userData["profile"]["image_192"]; this.icons.image_512 = userData["profile"]["image_512"]; this.email = userData["profile"]["email"]; this.firstName = userData["profile"]["first_name"]; this.lastName = userData["profile"]["last_name"]; } this.version = Math.max(this.version, t); } SlackUser.prototype.setPresence = function(presenceStr, t) { this.presence = presenceStr !== 'away'; this.version = Math.max(t, this.version); } /** * @constructor **/ function SelfPreferences() { /** @type {Object.} */ this.favoriteEmojis = {}; /** @type {Array.} */ this.highlights = []; } /** * @param {*} prefs **/ SelfPreferences.prototype.update = function(prefs, t) { this.favoriteEmojis = /** @type {Object} */ (JSON.parse(prefs["emoji_use"])); if (prefs["highlight_words"]) this.highlights = (prefs["highlight_words"]||"").split(',').filter(function(i) { return i.trim() !== ''; }); else if (prefs["highlights"]) this.highlights = prefs["highlights"]; this.version = Math.max(this.version, t); } /** * @constructor **/ function SlackBot(id) { /** @const @type {string} */ this.id = id; /** @type {boolean} */ this.deleted; /** @type {string} */ this.name; /** @type {string} */ this.appId; /** @type {Object.} */ this.icons = { image_36: "" ,image_48: "" ,image_72: "" }; /** @type {!Object.} */ this.channels; /** @type {SlackIms|null} */ this.ims = null; /** @type {SelfPreferences|null} */ this.prefs = null; /** @type {number} */ this.version = 0; /** @type {boolean} */ this.presence = false; } /** @param {*} botData */ SlackBot.prototype.update = function(botData, t) { if (botData["deleted"] !== undefined) this.deleted = botData["deleted"]; if (botData["name"] !== undefined) this.name = botData["name"]; if (botData["app_id"] !== undefined) this.appId = botData["app_id"]; if (botData["icons"]) { this.icons.image_36 = botData["icons"]["image_36"] this.icons.image_48 = botData["icons"]["image_48"] this.icons.image_72 = botData["icons"]["image_72"] } if (botData["presence"] !== undefined) this.presence = botData["presence"] !== 'away'; if (botData["isPresent"] !== undefined) this.presence = botData["isPresent"]; this.version = Math.max(this.version, t); } SlackBot.prototype.setPresence = function(presenceStr, t) { this.presence = presenceStr !== 'away'; this.version = Math.max(t, this.version); } /** * @constructor * @param {*} data **/ function SlackCommand(data) { /** @const @type {string} */ this.desc = data["desc"]; /** @const @type {string} */ this.name = data["name"]; /** @const @type {string} */ this.type = data["type"]; /** @const @type {string} */ this.usage = data["usage"]; } /** * @param {number} t * @return {Object} **/ SlackCommand.prototype.toStatic = function(t) { return { "desc": this.desc ,"name": this.name ,"type": this.type ,"usage": this.usage }; } /** * @constructor **/ function SlackData(slack) { /** @type {SlackTeam} */ this.team = null; /** @type {Object.} */ this.channels = {}; /** @type {Object.} */ this.groups = {}; /** @type {Object.} */ this.ims = {}; /** @type {Object.} */ this.users = {}; /** @type {SlackUser|SlackBot} */ this.self = null; /** @type {Object.} */ this.bots = {}; /** @type {{version: number, data: Object.}} */ this.emojis = { version: 0, data: {} }; /** @type {{version: number, data: Object.}} */ this.commands = {version: 0, data: {} }; /** @type {Object.>} */ this.typing = {}; /** * Node serv handler * @type {*} **/ this.slack = slack; /** @type {number} */ this.staticV = 0; /** @type {number} */ this.liveV = 0; } /** * @return {Object} **/ SlackTeam.prototype.toStatic = function(t) { return t >= this.version ? {} : { "id": this.id ,"name": this.name ,"domain": this.domain ,"prefs": { "calling_app_id": this.callApp ,"calling_app_name": this.callAppName ,"disable_file_uploads": this.fileUploadPermission ,"disable_file_editing": this.fileEditPermission ,"disable_file_deleting": this.fileDeletePermission } ,"icon": this.icons }; }; /** * @return {Object} **/ SlackChan.prototype.toStatic = function(t) { if (t >= this.version) return null; var res = { "id": this.id ,"name": this.name ,"created": this.created ,"creator": this.creator.id ,"is_archived": this.archived ,"is_member": this.isMember ,"last_read": this.lastRead }; if (this.isMember) { res["members"] = this.members ? Object.keys(this.members) : []; res["topic"] = { "value": this.topic ,"creator": this.topicCreator ? this.topicCreator.id : null ,"last_set": this.topicTs } res["purpose"] = { "value": this.purpose ,"creator": this.purposeCreator ? this.purposeCreator.id : null ,"last_set": this.purposeTs } } return res; }; /** * @return {Object} **/ SlackUser.prototype.toStatic = function(t) { return t >= this.version ? null : { "id": this.id ,"name": this.name ,"deleted": this.deleted ,"status": this.status ,"real_name": this.realName ,"isPresent": this.presence ,"profile": { "email": this.email ,"first_name": this.firstName ,"last_name": this.lastName ,"image_24": this.icons.image_24 ,"image_32": this.icons.image_32 ,"image_48": this.icons.image_48 ,"image_72": this.icons.image_72 ,"image_192": this.icons.image_192 ,"image_512": this.icons.image_512 } }; }; SlackGroup.prototype.toStatic = function(t) { if (t >= this.version) return null; var res = { "id": this.id ,"members": [] ,"created": this.created ,"creator": this.creator.id ,"is_archived": this.archived ,"last_read": this.lastRead }; for (var mId in this.members) { res["members"].push(mId); } if (this.topic) { res["topic"] = { "value": this.topic ,"creator": this.topicCreator.id ,"last_set": this.topicTs }; } if (this.purpose) { res["purpose"] = { "value": this.purpose ,"creator": this.purposeCreator.id ,"last_set": this.purposeTs }; } return res; }; SlackIms.prototype.toStatic = function(t) { return t >= this.version ? null: { "id": this.id ,"created": this.created ,"user": this.user.id ,"last_read": this.lastRead }; } SlackBot.prototype.toStatic = function(t) { return t >= this.version ? null : { "id": this.id ,"deleted": this.deleted ,"name": this.name ,"app_id": this.appId ,"isPresent": this.presence ,"icons": { "image_36": this.icons.image_36 ,"image_48": this.icons.image_48 ,"image_72": this.icons.image_72 } }; } /** * @param {*} data **/ SlackData.prototype.updateStatic = function(data, t) { if (data["bots"]) for (var i =0, nbBots = data["bots"].length; i < nbBots; i++) { var botObj = this.bots[data["bots"][i]["id"]]; if (!botObj) botObj = this.bots[data["bots"][i]["id"]] = new SlackBot(data["bots"][i]["id"]); botObj.update(data["bots"][i], t); } if (data["users"]) for (var i =0, nbUsers = data["users"].length; i < nbUsers; i++) { var userObj = this.users[data["users"][i]["id"]]; if (!userObj) userObj = this.users[data["users"][i]["id"]] = new SlackUser(data["users"][i]["id"]); userObj.update(data["users"][i], t); } if (data["ims"]) for (var i =0, nbIms = data["ims"].length; i < nbIms; i++) { var user = this.getMember(data["ims"][i]["user"]); if (user) { if (!user.ims) this.ims[data["ims"][i]["id"]] = user.ims = new SlackIms(data["ims"][i]["id"], user); user.ims.update(user, data["ims"][i], t); } } if (data["channels"]) for (var i =0, nbChan = data["channels"].length; i < nbChan; i++) { var chanObj = this.channels[data["channels"][i]["id"]]; if (!chanObj) chanObj = this.channels[data["channels"][i]["id"]] = new SlackChan(data["channels"][i]["id"]); chanObj.update(data["channels"][i], this, t); } for (var i =0, nbGroups = data["groups"].length; i < nbGroups; i++) { var groupObj = this.groups[data["groups"][i]["id"]]; if (!groupObj) groupObj = this.groups[data["groups"][i]["id"]] = new SlackGroup(data["groups"][i]["id"]); groupObj.update(this, data["groups"][i], t); } if (data["emojis"]) { this.emojis.data = data["emojis"]; this.emojis.version = t; } if (data["commands"] !== undefined){ this.commands.data = {}; for (var i in data["commands"]) { this.commands.data[i] = new SlackCommand(data["commands"][i]); } this.commands.version = t; } if (data["team"]) { if (!this.team) this.team = new SlackTeam(data["team"]["id"]); this.team.update(data["team"], t); } this.staticV = Math.max(this.staticV, t); if (data["self"]) { this.self = this.getMember(data["self"]["id"]); if (!this.self.prefs) this.self.prefs = new SelfPreferences(); this.self.prefs.update(data["self"]["prefs"], t); } if (data["typing"] !== undefined) { this.typing = data["typing"]; for (var i in this.typing) for (var j in this.typing[i]) this.typing[i][j] = t; } }; SelfPreferences.prototype.toStatic = function(t) { return this.version > t ? null : { "emoji_use": JSON.stringify(this.favoriteEmojis) ,"highlights": this.highlights }; } /** * @param {string} appId * @return {Array.} **/ SlackData.prototype.getBotsByAppId = function(appId) { var bots = []; for (var botId in this.bots) { if (this.bots[botId].appId === appId) { bots.push(this.bots[botId]); } } return bots; }; /** * @param {string} mId * @return {SlackUser|SlackBot|null} **/ SlackData.prototype.getMember = function(mId) { return this.users[mId] || this.bots[mId] || null; }; /** * @param {string} chanId * @return {SlackChan|SlackGroup|SlackIms|null} **/ SlackData.prototype.getChannel = function(chanId) { return this.channels[chanId] || this.ims[chanId] || this.groups[chanId] || null; }; /** @return {Object} */ SlackData.prototype.buildStatic = function(t, now) { var res = { "team": this.team.toStatic(t) ,"channels": [] ,"groups": [] ,"ims": [] ,"users": [] ,"bots": [] ,"self": { "id": this.self.id ,"prefs": this.self.prefs.toStatic(t) } ,"emojis": this.emojis.version > t ? this.emojis.data : undefined ,"commands": undefined ,"typing": undefined }; if (this.commands.version > t) { res["commands"] = {}; for (var i in this.commands.data) res["commands"][i] = this.commands.data[i].toStatic(t); } for (var chanId in this.channels) { var chan = this.channels[chanId].toStatic(t); if (chan) res["channels"].push(chan); } for (var userId in this.users) { var user = this.users[userId].toStatic(t) ,ims = this.users[userId].ims.toStatic(t); if (user) res["users"].push(user); if (ims) res["ims"].push(ims); } for (var botId in this.bots) { var bot = this.bots[botId].toStatic(t); if (bot) res["bots"].push(bot); } for (var groupId in this.groups) { var group = this.groups[groupId].toStatic(t); if (group) res["groups"].push(group); } for (var typingChan in this.typing) { var tChan; for (var typingUser in this.typing[typingChan]) { if (this.typing[typingChan][typingUser] +3000 >= now) { if (!tChan) tChan = {}; tChan[typingUser] = 1; } else { delete this.typing[typingChan][typingUser]; } } if (tChan) { if (res["typing"] === undefined) res["typing"] = {}; res["typing"][typingChan] = tChan; } else delete this.typing[typingChan]; } return res; }; SlackData.prototype.cleanTyping = function(t) { var updated = false; for (var typingChan in this.typing) { var chanEmpty = true; for (var typingUser in this.typing[typingChan]) { if (this.typing[typingChan][typingUser] +3000 < t) { delete this.typing[typingChan][typingUser]; updated = true; } else { chanEmpty = false; } } if (chanEmpty) { delete this.typing[typingChan]; updated = true; } } return updated; } /** * @param {*} msg * @param {number} t **/ SlackData.prototype.onMessage = function(msg, t) { if (msg["type"] === "presence_change") { var member = this.getMember(msg["user"]); if (member) member.setPresence(msg["presence"], t); this.staticV = Math.max(this.staticV, t); } else if (msg["type"] === "user_typing") { this.typing[msg["channel"]] = this.typing[msg["channel"]] || {}; this.typing[msg["channel"]][msg["user"]] = t; this.staticV = Math.max(this.staticV, t); } } /** * @param {number} knownVersion * @param {number} now time at update check * @return {Object|undefined} **/ SlackData.prototype.getUpdates = function(knownVersion, now) { if (this.staticV > knownVersion) return this.buildStatic(knownVersion, now); return undefined; }; /** @suppress {undefinedVars,checkTypes} */ (function() { if (typeof module !== "undefined") { module.exports.SlackData = SlackData; } })();