GithubHelp home page GithubHelp logo

greghilston / simple-slack-bot Goto Github PK

View Code? Open in Web Editor NEW
24.0 3.0 9.0 172 KB

Simple Python library for creating Slack bots.

Home Page: https://greghilston.github.io/Simple-Slack-Bot/

License: MIT License

Makefile 4.86% Python 95.14%
slack bot simple python api

simple-slack-bot's Introduction

Simple Slack Bot

<ORG_NAME> codecov PyPI version

Simple Slack Bot makes writing your next Slack bot incredibly easy. By factoring out common functionality all Slack Bots require, you can focus on writing your business logic.

Installing

Pip

Run:

$ pip3 install simple_slack_bot

From Source

To install, simply clone the source, which will allow you to import SimpleSlackBot.

Configuration

To configure, set a single environment variable

SLACK_BOT_TOKEN with your Slack Bot's API token

Finding Your Slack Bot API Token

To generate or locate your Slack Bot Token, visit

https://[YOUR SLACK TEAM NAME HERE].slack.com/apps/manage/custom-integrations

and click

Bots

If you already have a bot created, you should see it listed here, otherwise you should be able to click

Add Configuration

to create one.

Once you have a bot find it listed in the configurations and click the

Edit

icon. You'll be brought to a page that lists your API token. This is what you'll use with Simple Slack Bot.

Examples

Youtube Video Example

Video of creating the ping pong bot

Code Examples

For full examples, see the examples directory

To integrate with Simple Slack Bot, simply create an instance of it and register for notifications using a Python decorator.

This can be seen with the following code below. Our Simple Slack Bot will reply to every message of "Ping", with "Pong", to every channel it's a part of:

ping_pong.py

from simple_slack_bot.simple_slack_bot import SimpleSlackBot

simple_slack_bot = SimpleSlackBot(debug=True)


@simple_slack_bot.register("message")
def pong_callback(request):
    if request.message and request.message.lower() == "ping":
        request.write("Pong")


def main():
    simple_slack_bot.start()


if __name__ == "__main__":
    main()

At this point, your callback functions will be executed every time Simple Slack Bot receives the appropriate event.

Debug Mode

Note: Simple Slack Bot can be initialized with debug mode turned on, which will display all debug messages out to stdout and stderr.

To enable this simply pass debug=True when initializing Simple Slack Bot. As seen below:

simple_slack_bot = SimpleSlackBot(debug=True)

Additional Logging Control

If you want more control on the routing of your logging, instead of passing debug=True when initializing Simple Slack Bot, you can configure the global logging variable in your own application.

An example:

import logging
from simple_slack_bot.simple_slack_bot import SimpleSlackBot

dict_config = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': {
        'default': {
            'level': 'INFO',
            'formatter': 'standard',
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        '': {
            'handlers': ['default'],
            'level': 'INFO',
            'propagate': True
        },
        'django.request': {
            'handlers': ['default'],
            'level': 'WARN',
            'propagate': False
        },
    }
}

simple_slack_bot = SimpleSlackBot()
logging.config.dictConfig(dict_config)

Where you'd create your own dictConfig based on your own needs.

Supported Events

Simple Slack Bot handles all of the parsing and routing of Slack events. To be informed of new slack events, you must register a callback function with Simple Slack Bot for each event. All Slack Events are registered to and can be seen here.

The request Object

Each method you decorate in your Simple Slack Bot will need to take in a request. The contents of the request will differ depending on the event(s) you register to.

For each event you register for, take a look at the event here, as this is where the contents of the request will be defined.

For convenience, I've added the following attributes to all request objects:

  • type - type of event
  • channel - the channel from the underlying SlackEvent
    • Note: This can be an empty String. For example, this will be an empty String for the 'Hello' event.
  • message - the received message

Helper Functions & Callbacks Making Callbacks

Often times when writing a Slack Bot, you'll find yourself writing a few key functions that I found generic enough to include in Simple-Slack-Bot. The function names are pretty self explanatory but they are as follows:

  • helper_write(channel, content) - Writes a message to the channel as the bot
  • helper_get_public_channel_ids() - Gets all public channel ids
  • helper_get_private_channel_ids() - Gets all private channel ids
  • helper_get_user_ids() - Gets all user ids
  • helper_get_users_in_channel(channel_id) - Gets all users in a given channel
  • helper_name_to_channel_id(name) - Converts a channel name to its respected channel id
  • helper_user_name_to_user_id(name) - Converts a user name to its respected user id
  • helper_channel_id_to_channel_name(channel_id) - Converts a channel id to its respected channel name
  • helper_user_id_to_user_name(user_id) - Converts a user id to its respected user name

To gain access to these functions, simply call the appropriate function on your SimpleSlackBot instance.

Writing More Advanced Slack Bots

If you have found that Simple Slack Bot does not provide everything you are looking for, you can gain access to the underlying python Slack Client or SlackSocket object.

Running Local Development Version

If you want to run the local version of Simple Slack Bot and not the verison you downloaded through PyPi, you can run the following in the Simple-Slack-Bot directory:

python3 setup.py install

and then import it as usual

from simple_slack_bot.simple_slack_bot import SimpleSlackBot.

You'll also have to install Simple Slack Bot's dependencies using PyPi. A requirements.txt will be kept up to date, along side the setup.py for this use case and your convenience.

Don't Forget

The bot will only reply to channels that it is in. Don't forget to invite your bot into channels of interest!

Unit Tests

To run the unit test suite, execute

$ make test

To generate code coverage of the unit test suite, execute:

$ make test-and-generate-coverage

Simple Slack Bots

We'll be maintaining a list of Simple Slack Bots here.

If you have written a Simple Slack Bot, please contact me to have yours added!

Name Author Description
Ping Pong Bot Greg Hilston Ping Pong Bot was created to act as an example of how easy it is to create a bot using the open source Simple-Slack-Bot framework. Ping-Pong-Bot will look at every message sent to the channels that it is in, waiting for the case insensitive message "Ping". Once received Ping-Pong-Bot will write back to the very same channel "Pong".
The Office Bot Greg Hilston The Office Bot will look at every message sent to the channels that,it is in, waiting for a mention of the name of a character in the show, The Office, specifically the US version. Once received, The-Office-Bot will write back a random line that this character had throughout the show, including lines from deleted scenes.
Stan Bot Jahir Fiquitiva Stan Bot is a bot to help one with the SCRUM stand-up process.
Dice Bot Greg Hilston Dice Bot is used to perform simple dice rolls
DnD Bot Greg Hilston D and D Bot is used record small D&D sessions that take place in Slack, by recording the in game chat to a csv

simple-slack-bot's People

Contributors

andrew-boutin avatar davidharrigan avatar dependabot[bot] avatar greghilston avatar mupchrch avatar ramast avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

simple-slack-bot's Issues

Implement new register function for time based events, with ranges

We should allow a function of code to be registered for a time event, or range of time.

Basically imagine we wanted a function to execute every morning between x and y, we should make that easy to do.

It'd be help for periodic tasks like hitting an external API or reseeding some model or DB.

Implement Logging

Create log messages throughout execution. Each execution should generate a new file, by BOT_ID, time and date

Prevent bot crash

Could you add some error handling logic so the bot will log an error message and continue to process requests if an exception occurs in a callback?

Seems there are cases where text is not passed as part of the dictionary

2017-01-31 07:08:17,646 - INFO - private_channels {u'ok': True, u'groups': []}
2017-01-31 07:08:17,646 - WARNING - got no private channel ids
Traceback (most recent call last):
File "app.py", line 21, in
main()
File "app.py", line 17, in main
simple_slack_bot.start()
File "/home/user/simple_slack_bot/simple_slack_bot.py", line 112, in start
self.listen()
File "/home/user/simple_slack_bot/simple_slack_bot.py", line 168, in listen
self.route_dictionary_to_notify(dictionary)
File "/home/user/simple_slack_bot/simple_slack_bot.py", line 133, in route_dictionary_to_notify
self._logger.debug("printing user_name_mentions {} printing dictionary["text"] {}".format(self._user_name_mentions, dictionary["text"]))
KeyError: 'text'

"not_allowed_token_type" error

I got it all to work perfectly. Then I made a new bot, created a new oAuth token, and now it doesn't work any more. I can't recall doing anything differently this time. Any idea of what might be wrong? I'm getting this:

slacksocket.errors.SlackAPIError: Error from slack api:
{"ok":false,"error":"not_allowed_token_type"}

Cache Becomes Stale

The username and userid cache becomes stale whenever there's a user change. These changes include

  • A new user joins the server
  • A user leaves the server
  • A user changes their name

This issue is noted and will be fixed at some future date. It is not in the scope of the push for version 1.0 as a bot restart will fix this.

Deploying to Heroku

Hello

Thanks for creating this awesome tool/lib ...

I want to deploy my slack bot to heroku but I don't know how to (new to Heroku), would you mind helping me with that?

Thanks in advance :)

Evaluate `ok` in response of every Slack API call and handle gracefully

See this link https://api.slack.com/web

All Web API responses contain a JSON object, which will always contain a top-level boolean property ok, indicating success or failure.

For failure results, the error property will contain a short machine-readable error code. In the case of problematic calls that could still be completed successfully, ok will be true and the warning property will contain a short machine-readable warning code (or comma-separated list of them, in the case of multiple warnings).

Question: Support for Slack threads?

How would I go about having the Slack bot respond in a Slack thread? I am familiar with the Slack API, but I'm not seeing a simple way to respond to a message in a thread.

Is that something that this simple-slack-bot framework is capable of doing?

EDIT: I modified that title to include reactions as in the comments section I have started a conversation about adding support for threads and reactions.

Deployment Patterns?

Hi --

Love the bot, great work, thank you for open-sourcing it. Really appreciate the code coverage and thorough usage of modern Python development tools.

Quick question -- what deployment pattern do you recommend for this? Is this something you typically export out as a Lambda behind API Gateway? Is there a simpler pattern?

Thanks!

Ankur

Write unit tests

We would like to avoid our users from crashing or not working, due to our library's fault.

Some unit tests we could write are:

  • Registering a function via our decorator
    • Does registered functions get notified when that event is received
  • Helper functions
    • Do they do what they say they're going to do?
  • Throwing an unexpected error and ensuring its caught at the top level

Errors when trying to run example_component.py

I am trying to run example_component.py and I have supplied a slack_bot_token.

I am getting the following error:

initialized. Ready to connect
registering callback hello_callback to event type hello
registering callback user_typing_callback to event type user_typing
registering callback pong_callback to event type message
Traceback (most recent call last):
  File "example_component.py", line 28, in <module>
    main()
  File "example_component.py", line 24, in main
    simple_slack_bot.start()
  File ".../Simple-Slack-Bot/simple_slack_bot/simple_slack_bot.py", line 182, in start
    ok = self._slacker.rtm.start().body["ok"]
AttributeError: 'NoneType' object has no attribute 'rtm'

I poked through the code a bit and I discovered that _slacker was None because the connect function hadn't been called yet.

So, I simply added a call to connect() before the call to start() and that fixed that error for me.

def main():
    simple_slack_bot.connect()
    simple_slack_bot.start()

Is this expected behavior? I notice that the example in the README doesn't call connect() before it calls start().

__init__() got an unexpected keyword argument 'translate'

I am trying to run this in a docker container and I am having issues. Can you please help?

 Traceback (most recent call last):
   File "run.py", line 3, in <module>
   File "run.py", line 3, in <module>
     simple_slack_bot = SimpleSlackBot(debug=True)
   File "/usr/local/lib/python3.8/site-packages/simple_slack_bot/simple_slack_bot.py", line 60, in __init__
     simple_slack_bot = SimpleSlackBot(debug=True)
   File "/usr/local/lib/python3.8/site-packages/simple_slack_bot/simple_slack_bot.py", line 60, in __init__
     self._slackSocket = SlackSocket(self._SLACK_BOT_TOKEN, translate=False)
 TypeError: __init__() got an unexpected keyword argument 'translate'
     self._slackSocket = SlackSocket(self._SLACK_BOT_TOKEN, translate=False)
 TypeError: __init__() got an unexpected keyword argument 'translate'

Here is the code I am running. I have set the environment variable.

from simple_slack_bot.simple_slack_bot import SimpleSlackBot

simple_slack_bot = SimpleSlackBot(debug=True)

@simple_slack_bot.register("message")
def pong_callback(request):
    if request.message and request.message.lower() == "ping":
        request.write("Pong")

def main():
    simple_slack_bot.start()

if __name__ == "__main__":
    main()

Python 3.8.0
pip freeze:

certifi==2019.11.28
chardet==3.0.4
idna==2.8
pendulum==2.0.5
python-dateutil==2.8.1
pytzdata==2019.3
PyYAML==5.3.1
requests==2.22.0
simple-slack-bot==1.3.0
six==1.14.0
slacker==0.14.0
slacksocket==1.0.1
urllib3==1.25.8
websocket-client==0.48.0

Exception after leaving bot running for days

After leaving bot running for few days, I came to find it terminated with this exception.
Line numbers may not match existing code because I've added lines to ignore messages coming from slack that doesn't contain the key "message" (a dirty fix for the previous issue)

Traceback (most recent call last):
File "app.py", line 21, in
main()
File "app.py", line 17, in main
simple_slack_bot.start()
File "/home/skor/simple_slack_bot/simple_slack_bot.py", line 112, in start
self.listen()
File "/home/skor/simple_slack_bot/simple_slack_bot.py", line 165, in listen
json_list = self._slack_client.rtm_read()
File "/home/skor/simple_slack_bot/env/local/lib/python2.7/site-packages/slackclient/_client.py", line 123, in rtm_read
json_data = self.server.websocket_safe_read()
File "/home/skor/simple_slack_bot/env/local/lib/python2.7/site-packages/slackclient/_server.py", line 141, in websocket_safe_read
data += "{0}\n".format(self.websocket.recv())
File "/home/skor/simple_slack_bot/env/local/lib/python2.7/site-packages/websocket/_core.py", line 293, in recv
opcode, data = self.recv_data()
File "/home/skor/simple_slack_bot/env/local/lib/python2.7/site-packages/websocket/_core.py", line 310, in recv_data
opcode, frame = self.recv_data_frame(control_frame)
File "/home/skor/simple_slack_bot/env/local/lib/python2.7/site-packages/websocket/_core.py", line 323, in recv_data_frame
frame = self.recv_frame()
File "/home/skor/simple_slack_bot/env/local/lib/python2.7/site-packages/websocket/_core.py", line 357, in recv_frame
return self.frame_buffer.recv_frame()
File "/home/skor/simple_slack_bot/env/local/lib/python2.7/site-packages/websocket/_abnf.py", line 336, in recv_frame
self.recv_header()
File "/home/skor/simple_slack_bot/env/local/lib/python2.7/site-packages/websocket/_abnf.py", line 286, in recv_header
header = self.recv_strict(2)
File "/home/skor/simple_slack_bot/env/local/lib/python2.7/site-packages/websocket/abnf.py", line 371, in recv_strict
bytes
= self.recv(min(16384, shortage))
File "/home/skor/simple_slack_bot/env/local/lib/python2.7/site-packages/websocket/_core.py", line 427, in _recv
return recv(self.sock, bufsize)
File "/home/skor/simple_slack_bot/env/local/lib/python2.7/site-packages/websocket/_socket.py", line 93, in recv
"Connection is already closed.")
websocket._exceptions.WebSocketConnectionClosedException: Connection is already closed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.