Project description

Slackbot

Create custom actions based on slack events

This project is to make it simple to have a single slackbot that can have different commands in different slack channels. This is done by having functions or classes that get added to a channel, and each function/method has a regex trigger that it is listening for in the channel it is in. If the trigger and channel match, then it will run that function.

How to use

First you need to create a Slack App with a bot user. You will find your Access Token under the OAuth & Permissions section (use the bot token).
With Slack apps, you need to give it permissions for what you want it to do. By default it needs at least these permissions to start:

users:read (needed to get the users in the team)

users.profile:read (needed to get the bot info and user emails)

conversations:read (needed to get the list of conversations the bot is in)

Remember that each time to edit the permissions you will need to re install the App to your team for the new/updated permissions to take affect.

Since slack apps work by hitting an api endpoint, you will need an public facing endpoint to test with. You can use ngrok or anything similar for development (see below for custom solution). The endpoint that you will be hitting on the server will always be example.com/slack/event. This will need to be added in the Event Subscriptions section of the App. Be sure to add Bot Events and Workspace Events otherwise slack will never hit your bot with an action. Bot Events should be used whenever possible as it limits the number of events you receive to just those that occur in the channels you've invited the bot to. Workspace Events notifications include all events of your selected types that occur in every public channel in your workspace and can get quite noisy. To get started try adding message.channels. For each event you add you will need to add the required permission too. In this case the permission channels:history will be added.

To add the app to a channel, go into the app settings and add to any channels that you would like it to be in.

To install, either run the setup.py install
or install via pip (recommended): pip install slack_actions

Basic Example (run.py):

importreimportloggingfromslack_actionsimportslack_controller,applogger=logging.getLogger(__name__)# This is going to listen for a message with the text foobar in it, case insensitive.@slack_controller.trigger(['message'],{'text':'foobar'},flags=re.IGNORECASE)@slack_controller.help_message(author_name="trigger:message",color="#3366ff",text="Type:\n> foobar")deffoobar(output,full_event):message_data={'text':'fn: foobar was triggered'}returnmessage_data# The token can also be set by an env var `SLACK_BOT_TOKEN`, which will be used first if it existsauth_token='xoxb-app-bot-token-here'# or it can be set in the script like soslack_controller.setup(slack_bot_token=auth_token)# Order of the commands in the channel list matter, the first match it finds it will stop# The order of the channels do not matter thoughcommands={'__direct_message__':[],# For direct messages between a user and the bot'__all__':[foobar],# Any channel that the bot is in'general':[],# Only in the channel named __general__}slack_controller.add_commands(commands)if__name__=='__main__':logger.critical("\nRun listener by doing (replace `run` with this filename):\n\tgunicorn -b 0.0.0.0:5000 run:app \n")

You can find more examples in the examples/ directory.
To run this basic example, type: gunicorn -b 0.0.0.0:5000 run:app, this will start the api web server that slack can post to.

In any channel, you can type the message help and the slack bot should return all the help messages for the commands in that channel.

How the decorators work:

Each function has a trigger and a help decorator from the slack_controller.

slack_controller.trigger

This is used to tell the function when to run. There are 2 positional arguments and 1 keyword argument:
@slack_controller.trigger(['message'], {'text': 'foobar'}, flags=re.IGNORECASE)

event_types: These are the name of the Slack event types sent by slack in the api call, it should be formatted as event_type.sub_type. It can be a single event type or a list of them (depending on the regex passed in too some may not play well together)

regex_parsers: This is a dictionary with its keys being fields in the Slack api data under the event key. The value is the regex that it needs to match in order to run the function. Nested keys can be formatted like so actions.value. If the next nested item is a list and not another dictionary then you can just jump to the next dict's keys or specify the index of the item you want. By default if no index is passed in it will use the first item in the list. For example, both of these will get the first item in the list: actions.0.value, actions.value.

other args or kwargs: Any other positional arguments or keyword arguments not mentioned above will be passed to the function you are decorating

slack_controller.help_message

This is used when the user types help in a channel to let them know what commands they have available to use. The named arguments map to the keys in the Slack message attachements. The examples in this repo all follow a similar formatting, but they can be any combination of argumenst to fit the functions help message needs.
@slack_controller.help_message(author_name="trigger:message", color="#3366ff", text="Type:\n> foobar")