/util.py
Python | 151 lines | 98 code | 13 blank | 40 comment | 7 complexity | 3054a4db10854d9c42996fd1f8a91bd2 MD5 | raw file
- """This module holds utility functions used by some modules and the bot itself."""
- import config
- import requests_cache
- import logging
- import re
- from bs4 import BeautifulSoup
- from urllib.request import Request, urlopen
- from urllib.error import HTTPError, URLError
- import stopit
- import shlex
- logger = logging.getLogger(__name__)
- idregex = re.compile(r'\@([A-Z0-9]{9})', re.UNICODE)
- channelregex = re.compile(r'\#([A-Z0-9]{9})', re.UNICODE)
- urlregex = re.compile(r'\<(.*?)\>')
- def getUserdataForId(userId):
- """
- Get the json response from the slack api for the specified user id.
- API endpoint: https://api.slack.com/methods/users.info
- Arguments: userId, slack user id to fetch. Required.
- Returns: the json response for the id
- """
- logging.info("Fetching user data for id %s", userId)
- s = requests_cache.CachedSession(cache_name='namelookup_cache', backend='sqlite', expire_after=3600)
- payload = {"token": config.SLACK_TOKEN, "user": userId}
- req = s.get("https://slack.com/api/users.info", params=payload)
- logging.debug("User data for id %s was cached=%s", userId, req.from_cache)
- return req.json()
- def __replaceUserId(userId):
- """
- Get the username for the specified id.
- Will return the raw id if username could not be found.
- """
- logging.debug("found id %s", userId.group(1))
- data = getUserdataForId(userId.group(1))
- if not data["ok"]:
- logging.warning("%s for id %s", data["error"], userId.group(1))
- return userId.group(0)
- else:
- return "@" + data["user"]["name"]
- def getChanneldataForId(channelId):
- """
- Get the json response from the slack api for the specified channel id.
- API endpoint: https://api.slack.com/methods/channels.info
- Arguments: channelId, slack channel id to fetch. Required.
- Returns: the json response for the id
- """
- logging.info("Fetching channel data for id %s", channelId)
- s = requests_cache.CachedSession(cache_name='namelookup_cache', backend='sqlite', expire_after=3600)
- payload = {"token": config.SLACK_TOKEN, "channel": channelId}
- req = s.get("https://slack.com/api/channels.info", params=payload)
- logging.debug("Channel data for id %s was cached=%s", channelId, req.from_cache)
- return req.json()
- def __replaceChannelId(channelId):
- """
- Gets the channel name for the specified id.
- Will return the raw id if channel could not be found.
- """
- logging.debug("found id %s", channelId.group(1))
- data = getChanneldataForId(channelId.group(1))
- if not data["ok"]:
- logging.warning("%s for id %s", data["error"], channelId.group(1))
- return channelId.group(0)
- else:
- return "#" + data["channel"]["name"]
- def replaceIdsInMessage(message):
- """
- Replaces occurences of slack id's in messages with their human readable counterparts.
- """
- message = re.sub(channelregex, __replaceChannelId, message)
- return re.sub(idregex, __replaceUserId, message)
- @stopit.threading_timeoutable(default=None)
- def getTitle(url):
- """
- Fetch the <title> tag of the specified url.
- Returns a string if <title> could be found, else returns None.
- """
- try:
- headers = {'User-Agent': 'SlackBot %s V1.0' % config.BOT_NAME}
- req = Request(url, None, headers)
- response = urlopen(req)
- html = response.read()
- except HTTPError as e:
- print('The server couldn\'t fulfill the request.')
- print(('Error code: ', e.code))
- except URLError as e:
- print('We failed to reach a server.')
- print(('Reason: ', e.reason))
- except Exception as e:
- print(e)
- else:
- soup = BeautifulSoup(html, "lxml")
- if soup.title is not None:
- return soup.title.text.strip()
- return None
- def dict_of_key_value_pairs(arg):
- """ parse KEY=val,KEY2=val2 into {'KEY':'val', 'KEY2':'val2'}
- Quotes can be used to allow commas in the value
- This piece of code has been taken from:
- https://github.com/Supervisor/supervisor/blob/e4f3f0cad1697fdb76632dfe8a3935ae4540fbae/supervisor/datatypes.py#L80
- """
- lexer = shlex.shlex(arg)
- lexer.wordchars += '/.+-():'
- tokens = list(lexer)
- tokens_len = len(tokens)
- D = {}
- i = 0
- while i < tokens_len:
- k_eq_v = tokens[i:i+3]
- if len(k_eq_v) != 3 or k_eq_v[1] != '=':
- raise ValueError("Unexpected end of key/value pairs")
- D[k_eq_v[0]] = k_eq_v[2].strip('\'"')
- i += 4
- return D
- def replaceUrlTags(message):
- """Strip slacks url formatting out of the message"""
- matches = re.findall(urlregex, message)
- if matches:
- for match in matches:
- message = urlregex.sub(match.split("|")[0], message, count=1)
- return message