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

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.3.tar.gz (5.7 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page