I'd love thoughts on how to make this more elegant. I'm planning to add some additional functionality, but basically this is just my first pass at creating a pythonic Slack bot from scratch.
You need Slack API token to run it. I am deploying to Heroku, so I have it looking for an environment variable called API_TOKEN
which I set (in bash, anyway) export API_TOKEN='abc-1234xyzFakeTokenString'
There are two files, app.py
:
from slackclient import SlackClient
import time
import re
import datetime
class Bot(object):
def __init__(self, token, searches):
self.searches = searches
self.client = SlackClient(token)
self.username = {}
self.user_id = {}
def run(self):
if self.client.rtm_connect():
try:
self.user_id = self.client.api_call("auth.test")['user_id']
self.username = self.client.api_call("auth.test")['user']
self._log(self.username + ": " + self.user_id)
except:
print Exception
while True:
self.process_messages(self.client.rtm_read())
time.sleep(0.25)
else:
self._log("Connection failed.")
def _log(self, message, level=' DEBUG '):
"""
TODO this should actually put logs somewhere useful;
"""
print str(datetime.datetime.utcnow()) + level + message
def filter_speak(self, room, message):
"""
posts a message to a channel if it matches the call.
"""
for call in self.searches:
response = self.searches[call]
if re.search(call, message):
self.client.api_call("chat.postMessage", as_user="true",
channel=room, text=response)
def process_messages(self, messages):
for msg in messages:
# We're only interested in entries of type "message"
if msg['type'] == "message":
# TODO also check the text of expanded links.
if 'text' in msg:
body = msg['text']
elif 'subtype' in msg:
if msg['subtype'] == "message_changed":
body = msg['message']['text']
else:
self._log(msg + " didn't appear to have text or subtype?")
if 'user' in msg:
if msg['user'] != self.user_id:
self.filter_speak(message=body, room=msg['channel'])
And then in a separate run.py
file I have:
from app import Bot
from os import environ
pairs = {}
pairs["[kK]nock[, -]*[kK]nock"] = "Who's there?"
pope_bot = Bot(environ['API_TOKEN'], pairs)
pope_bot.run()
I'm hoping to add a bit more functionality -- I'd like it to chirp a few more things when prompted by a DM, for instance, but this works so I wanted feedback on how I could streamline it or what you might have done differently.
get()
method for dictionaries, which would go a long way towards tidying upprocess_messages
\$\endgroup\$ – Amanda Jun 30 '16 at 2:05