Skip to main content

A simple semi-conversational, multi-step workflow slack bot framework.

Project description

SlackBorg
=========

SlackBorg is a framework for semi-conversational, multi-step workflow
Slack Bots. We're just getting started. Have an idea? File an issue.
Have some code? Open a pull request.

Concepts
========

SlackBorg has two main things you should care about, the ``@command``
decorator and the ``Conversation`` class.

``@command``
------------

``@command`` is a decorator you place on a function you implement to
respond to a given command. A command can be ``multi_step``, which is to
say that its function is called on the given conversation each time a
new message comes in, until the conversation is explicitly closed. It's
up to you how you handle a multi-step conversation. As you'll see, the
``Conversation`` object includes all the data you need to make decisions
each time your handler is called. If your command is not ``multi_step``,
the conversation is closed immediately after your handler returns.

``@command`` parameters:
~~~~~~~~~~~~~~~~~~~~~~~~

- ``match_string``: A RegEx string that you would pass into
``re.compile``. *Required*
- ``flags``: Any flags from the ``re`` module you would pass into
``re.compile``.
- ``multi_step``: Set to ``True`` if your command is multi-step.
Default ``False``.

``Conversation``
----------------

The ``Conversation`` object is the sole parameter to your command
handler. Conversations are unique to a given user in a given channel.
When a message comes in, the conversation manager checks to see if a
conversation exists for the sending user in the channel it is posted to.
If it doesn't yet exist, a Conversation object is constructed and the
command manager attempts to match a command to the Conversation. If it
finds one, its handler is called on the conversation. If a conversation
exists, it is updated with the latest message and its command's handler
called on the updated Conversation.

``Conversation`` fields:
~~~~~~~~~~~~~~~~~~~~~~~~

- ``user_id``: the sender's Slack User ID
- ``user_data``: the sender's full Slack User Data (fetched when the
Conversation is first created)
- ``channel_id``: the Conversation's Slack Channel ID
- ``channel_data``: the Conversation's full Slack Channel Data (fetched
when the Conversation is first created -- **only set if it's a
channel and not a DM**)
- ``initial_message``: the message that was responsible for the
creation of this Conversation.
- ``messages``: the rest of the messages. *Does not include
``initial_message``*.
- ``latest_message``: the most recent message.
- ``context``: a dictionary that you can put any data you want to
persist in the conversation across messages. This is where the magic
is for doing a multi-step command across a conversation.

``Conversation`` methods:
~~~~~~~~~~~~~~~~~~~~~~~~~

- ``say(message)``: send a message to the channel.
- ``close()``: close the conversation.

Installation
============

Right now, I'd probably suggest spinning up a ``virtualenv`` and running
``python setup.py develop`` inside of it.

Usage
=====

Write yourself a script to declare your commands and run your bot, like
so:

::

import os
import random
import re
import time

from slackborg import *

# Get Bot ID and API Token from env -- make sure to put these in your env!
BOT_ID = os.environ.get('SLACK_BOT_ID')
BOT_TOKEN = os.environ.get('SLACK_BOT_TOKEN')

# Define a default response to any non-matching commands. The default default is to silently ignore the command and close the conversation.
@default_command
def default_cmd(conversation):
conversation.say("I see, sir {}".format(conversation.user_data['profile']['first_name']))

# Define a command by a regex string, and optionally any flags you'd give the re.compile method.
@command('hello', flags=re.IGNORECASE)
def hello(conversation):
conversation.say("Hello! I am C-3PO, human-cyborg relations!")

# By default, a command is single-step and auto-closes its conversation upon the handler returning.
# You can override this.
@command('sum', flags=re.IGNORECASE, multi_step=True)
def do_sum(c):
print c
operands = c.context.setdefault('operands', [])
if len(c.messages):
if 'done' in c.latest_message.lower():
c.say("The sum of {} = {}".format(
" + ".join(str(o) for o in operands),
str(sum(operands))
)
)
c.close()
else:
try:
operands.append(int(c.latest_message))
c.say("So far: {}...".format(
" + ".join(str(o) for o in operands)
))
except:
c.say("That input wasn't a number. Try again!")
else:
c.say("Just enter your operands, one by one, and then type `done` when you're done!")

def main():
borg = SlackBorg(BOT_ID, BOT_TOKEN)
borg.run()

if __name__ == '__main__':
main()

# End

Thanks
~~~~~~
Some of the patterns used in this framework borrow ideologies from _lins05/slackbot, so I thank the existing developers of that library for their prior work. Perhaps we can bring these two libraries together, eventually! Or keep them separate :D

.. _lins05/slackbot: https://github.com/lins05/slackbot

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

slackborg-0.0.2.tar.gz (5.7 kB view hashes)

Uploaded source

Supported by

AWS AWS Cloud computing Datadog Datadog Monitoring Facebook / Instagram Facebook / Instagram PSF Sponsor Fastly Fastly CDN Google Google Object Storage and Download Analytics Huawei Huawei PSF Sponsor Microsoft Microsoft PSF Sponsor NVIDIA NVIDIA PSF Sponsor Pingdom Pingdom Monitoring Salesforce Salesforce PSF Sponsor Sentry Sentry Error logging StatusPage StatusPage Status page