aboutsummaryrefslogtreecommitdiff
path: root/slack_parser.py
diff options
context:
space:
mode:
authorkd <kdam0@localhost.localdomain>2020-06-09 20:26:53 +0000
committerkd <kdam0@localhost.localdomain>2020-06-09 20:26:53 +0000
commit474fbe0850ba5dc6a7aa8eb06c60d229af674dcb (patch)
treea3404048efbbea06f5943999f2cd034c371ccdbf /slack_parser.py
initial commit
Diffstat (limited to 'slack_parser.py')
-rw-r--r--slack_parser.py169
1 files changed, 169 insertions, 0 deletions
diff --git a/slack_parser.py b/slack_parser.py
new file mode 100644
index 0000000..8756992
--- /dev/null
+++ b/slack_parser.py
@@ -0,0 +1,169 @@
+import os
+import json
+import re
+import time
+from jsonpath_ng import jsonpath, parse
+
+
+# jsonpath match will match in order of appearence.
+# This mapping defines which position in the RESULT of match to look for which key.
+# so. eg. at 0th position (of the match) will be the key "text", etc.
+key_orderings = {
+ "text": 0,
+ "ts": 1,
+ "name": 2
+}
+
+class SlackParser(object):
+
+ """Docstring for SlackParser. """
+
+ def __init__(self, messagesDir=None, usersFile=None, keys=None):
+
+ self.messagesDir = ""
+ self.usersFile = ""
+ self.keys = list()
+ if messagesDir is not None:
+ self.messagesDir += messagesDir
+ if usersFile is not None:
+ self.usersFile += usersFile
+ if keys is not None:
+ self.keys += keys
+
+ self.usersLib = None
+
+ def getSortedMessageFiles(self):
+ """Docstring for getSortedMessageFiles.
+ Get the files that contain channel data sorted.
+
+ :returns: a sorted list of json files names for the channel
+
+ """
+ files = sorted(os.listdir( self.messagesDir ))
+ return files
+
+ def getUsers(self):
+ """Docstring for getUsers
+ Get the parsed json that contains the raw user info.
+
+ :returns: a dict with all users infos
+
+ """
+ path = self.usersFile
+ # TODO: check for path validity
+ content = json.load(open(path))
+ return content
+
+
+ def buildUsersLibrary(self):
+ """Docstring for buildUsersLibrary
+ Build a Users dict that keeps only usersid to name mappings.
+
+ :returns: a dict user info
+
+ """
+ userLib = {}
+ for userjson in self.getUsers():
+ if "name" in userjson and "id" in userjson:
+ userLib[userjson["id"]] = userjson["name"]
+ self.setUsersLib(userLib)
+ return self
+
+ def setUsersLib(self, usersLib):
+ """Docstring for buildUsersLibrary
+ A setter method that sets the object lib to the given lib.
+
+ """
+ self.usersLib = usersLib
+
+ def getMessages(self, slackFile):
+ """Docstring for getMessages.
+ Given a file, get the messages in that file.
+
+ :slackFile: the json file name containing messages
+ :returns: a list of all messages in the file
+
+ """
+ path = self.messagesDir + "/" + slackFile
+ # TODO: check for path validity
+ content = json.load(open(path))
+ return content
+
+ def getKeyValues(self, slackMessage):
+ """Docstring for getKeyValues.
+ Get the value for each key (defined during init) from the mssg.
+
+ :slackMessage: the parsed json slack message
+ :returns: on success, a dict with only required keys and values
+ on failure, None
+
+ """
+ data = None
+ # we also check for "subtype" to filter out mssgs like:
+ # "s joined the channel", "x left the channel" etc.
+ if "type" in slackMessage and "subtype" not in slackMessage:
+ if slackMessage["type"] == "message" and slackMessage["text"] != "":
+ data = {}
+ jsonpath_expression = parse("$.." + str(self.keys))
+ # search slackMessage for each key, and add all matches (incl. dups.) in-order
+ match = jsonpath_expression.find(slackMessage)
+ #print(match[0])
+ for key in self.keys:
+ # TODO: validation for matches possible "index out of range" here.
+ data[key] = match[key_orderings[key]].value
+ # get the user id in the text
+ userIds = self.getUserIdsFromMessage(data["text"])
+ if userIds != []:
+ # find corresponding usernames from library
+ userNamesinMessageDict = self.getUserNamesFromIds(self.usersLib, userIds)
+ # inject usernames in the text replace userid
+ data["text"] = self.replaceMessageUserIdsWithNames(userNamesinMessageDict, data["text"])
+ # convert ts to a human readble time
+ data["ts"] = time.strftime( "%H:%M %b %d, %Y", time.localtime(float(data["ts"])) )
+
+ return data
+
+ @staticmethod
+ def getUserIdsFromMessage(text):
+ """Docstring for getUserIdsFromMessage.
+ A helper method that searches a text for Slack user ids. It maps:
+ "<@SLACKID1>adsfasdf <@SLACKID2>" -> ["SLACKID1", "SLACKID2"]
+
+ :text: raw text from Slack message json
+ :returns: a list of userids strings in the text in order of match
+
+ """
+ regex = r"<@(.+?)>"
+ matches = re.findall(regex, text)
+ return matches
+
+ @staticmethod
+ def getUserNamesFromIds(usersDict, userIds):
+ """Docstring for getUserNamesFromIds.
+ A helper method to search a dict for a keys, and get the values.
+
+ :usersDict: a dict library of userid and name mappings
+ :ids: a string list of userids
+ :returns: dict of each userid and its username
+
+ """
+ userMap = {}
+ for userId in userIds:
+ if userId in usersDict:
+ userMap[userId] = usersDict[userId]
+ return userMap
+
+ @staticmethod
+ def replaceMessageUserIdsWithNames(messageUsersDict, text):
+ """Docstring for replaceMessageUserIdsWithNames.
+ A helper method to replace all Slackuser id tags with their @username. So it maps:
+ { "USERID1" : "name1" , "USERID2": "name2" },"<@USERID1> blah blah <@USERID2>." -> "@name1 blah blah @name2."
+
+ :messageUsersDict: the dict containing userid to username mappings for this text
+ :text: the original string contianing Slack userids in it
+ :returns: a string with each Slack userid replaced with mapping value from dict.
+
+ """
+ for userId in messageUsersDict.keys():
+ text = re.sub( "<@{}>".format(userId), "<i style='color: #B18904;'>@{}</i>".format(messageUsersDict[userId]), text )
+ return text