Giter Site home page Giter Site logo

dondebonair / slack-machine Goto Github PK

View Code? Open in Web Editor NEW
749.0 10.0 55.0 2.14 MB

A simple, yet powerful and extendable Slack bot

Home Page: https://dondebonair.github.io/slack-machine/

License: MIT License

Python 100.00%
slack slack-bot slackbot slack-api slackapi python ai bot bot-framework chatbot

slack-machine's Introduction

Slack Machine

Join the chat at Slack image image image CI Status image

Slack Machine is a simple, yet powerful and extendable Slack bot framework. More than just a bot, Slack Machine is a framework that helps you develop your Slack workspace into a ChatOps powerhouse. Slack Machine is built with an intuitive plugin system that lets you build bots quickly, but also allows for easy code organization. A plugin can look as simple as this:

from machine.plugins.base import MachineBasePlugin
from machine.plugins.message import Message
from machine.plugins.decorators import respond_to


class DeploymentPlugin(MachineBasePlugin):
    """Deployments"""

    @respond_to(r"deploy (?P<application>\w+) to (?P<environment>\w+)")
    async def deploy(self, msg: Message, application, environment):
        """deploy <application> <environment>: deploy application to target environment"""
        await msg.say(f"Deploying {application} to {environment}")

Breaking Changes

Plugin initialization is now async (v0.35.0)

The optional initialization method plugins can implement, which is run once when the plugin is loaded, should be an async method starting the upcoming v0.35.0. The reason for this is that this allows plugins to interact with Slack through the Slack Machine's plugin API - most of which methods are async.

Simply prefix your init() methods with async.

Dropped support for Python 3.7 (v0.34.0)

As of v0.34.0, support for Python 3.7 has been dropped. Python 3.7 has reached end-of-life on 2023-06-27.

AsyncIO (v0.30.0)

As of v0.30.0 Slack Machine dropped support for the old backend based on the RTM API. As such, Slack Machine is now fully based on AsyncIO. This means plugins written before the rewrite to asyncio aren't supported anymore. See here for a migration guide to get your old plugins working with the new version of Slack Machine.

It's really easy!

Features

  • Get started with mininal configuration
  • Built on top of the Slack Events API for smoothly responding to events in semi real-time. Uses Socket Mode so your bot doesn't need to be exposed to the internet!
  • Support for rich interactions using the Slack Web API
  • High-level API for maximum convenience when building plugins
  • Low-level API for maximum flexibility
  • Built on top of AsyncIO to ensure good performance by handling communication with Slack concurrently

Plugin API features:

  • Listen and respond to any regular expression
  • Respond to Slash Commands
  • Capture parts of messages to use as variables in your functions
  • Respond to messages in channels, groups and direct message conversations
  • Respond with reactions
  • Respond in threads
  • Respond with ephemeral messages
  • Send DMs to any user
  • Support for blocks
  • Support for message attachments [Legacy 🏚]
  • Listen and respond to any Slack event supported by the Events API
  • Store and retrieve any kind of data in persistent storage (currently Redis, DynamoDB, SQLite and in-memory storage are supported)
  • Schedule actions and messages
  • Emit and listen for events
  • Help texts for Plugins

Coming Soon

  • Support for Interactive Buttons
  • ... and much more

Installation

You can install Slack Machine using pip:

$ pip install slack-machine

or add it to your Poetry project:

poetry add slack-machine

It is strongly recommended that you install slack-machine inside a virtual environment!

Usage

  1. Create a directory for your Slack Machine bot: mkdir my-slack-bot && cd my-slack-bot

  2. Add a local_settings.py file to your bot directory: touch local_settings.py

  3. Create a new app in Slack: https://api.slack.com/apps

  4. Choose to create an app from an App manifest

  5. Copy/paste the following manifest: manifest.yaml

  6. Add the Slack App and Bot tokens to your local_settings.py like this:

    SLACK_APP_TOKEN = "xapp-my-app-token"
    SLACK_BOT_TOKEN = "xoxb-my-bot-token"
    
  7. Start the bot with slack-machine

  8. ...

  9. Profit!

Documentation

You can find the documentation for Slack Machine here: https://dondebonair.github.io/slack-machine/

Go read it to learn how to properly configure Slack Machine, write plugins, and more!

slack-machine's People

Contributors

arusahni avatar bennylu2 avatar brettlassian avatar cchadowitz avatar cp-richard avatar davidolrik avatar dependabot[bot] avatar dondebonair avatar eddyg avatar eguven avatar gfreezy avatar gitter-badger avatar jkmathes avatar preludedrew avatar pyup-bot avatar repudi8or avatar seerickcode 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar

slack-machine's Issues

Bug on send_dm

hello
On send_dm , i'have this error
'Traceback (most recent call last):
File "/home/devsupportbot/bot/lib/python3.6/site-packages/apscheduler/executors/base.py", line 125, in run_job
retval = job.func(*job.args, **job.kwargs)
File "/home/devsupportbot/bot/mybot/plugins/meteo.py", line 38, in humeurJour
Réagis en cliquant sur une icône''')
File "/home/devsupportbot/bot/lib/python3.6/site-packages/machine/plugins/base.py", line 191, in send_dm
self._client.send_dm(user, text)
File "/home/devsupportbot/bot/lib/python3.6/site-packages/machine/slack.py", line 82, in send_dm
dm_channel = self.open_im(u.id)
AttributeError: 'NoneType' object has no attribute 'id''

here is my code
def humeurJour(self): """humeurJour : demande l'humeur du jour sur le canal meteo""" for u in DbSession.query(users.utilisateur, slackusers.name, slackusers.user_id).join(slackusers, services).filter( services.nom == "Support").order_by( users.slackid): print(u.utilisateur, u.name, u.user_id) msg = self.send_dm(u.name, 'Salut , ' + u.name + ''' ,comment vas tu aujourdhui? \n Réagis en cliquant sur une icône''') channel = msg['channel'] reaction_channel.append(channel) ts = msg['ts'] for i in DbSession.query(emojis).order_by(emojis.score): print(i.emoji) self.react(channel, ts, i.emoji)

Help on init()

Hello , can you provide me some help how to use it ?
Thx

error message on scheduler task

Hello
I have a plugin that look at gmail message and send a notification to slack

from machine.plugins.base import MachineBasePlugin
from plugins.helpers.gmail import Gmail
from machine.plugins.decorators import schedule, listen_to


class schedmail(MachineBasePlugin):
    @schedule(day_of_week='mon-fri', hour='8-17', minute='00-59/5')
    def extranetbloquant(self):
        reponse = Gmail().readMailExtranet(['INBOX', 'bloquant'], ['bloquant'])
        if reponse:
            self.say('akuiteo-bloquant', reponse)

and i have regurlarly this message in logs

[2020-05-18 14:00:01][ERROR] apscheduler.executors.default base.py:run_job:131 | Job "schedmail.extranetbloquant (trigger: cron[day_of_week='mon-fri', hour='8-17', minute='0-59/5'], next run at: 2020-05-18 14:05:00 CEST)" raised an exception
Traceback (most recent call last):
  File "/home/supportbot/bot/lib/python3.6/site-packages/apscheduler/executors/base.py", line 125, in run_job
    retval = job.func(*job.args, **job.kwargs)
  File "/home/supportbot/bot/mybot/plugins/mailtoslack.py", line 12, in extranetbloquant
    self.say('akuiteo-bloquant', reponse)
  File "/home/supportbot/bot/lib/python3.6/site-packages/machine/plugins/base.py", line 137, in say
    thread_ts=thread_ts, ephemeral_user=ephemeral_user, **kwargs)
  File "/home/supportbot/bot/lib/python3.6/site-packages/machine/clients/slack.py", line 61, in send
    **kwargs
  File "/home/supportbot/bot/lib/python3.6/site-packages/slack/web/client.py", line 559, in chat_postMessage
    return self.api_call("chat.postMessage", json=kwargs)
  File "/home/supportbot/bot/lib/python3.6/site-packages/slack/web/base_client.py", line 171, in api_call
    return self._event_loop.run_until_complete(future)
  File "/usr/local/lib/python3.6/asyncio/base_events.py", line 455, in run_until_complete
    self.run_forever()
  File "/usr/local/lib/python3.6/asyncio/base_events.py", line 409, in run_forever
    raise RuntimeError('This event loop is already running')
RuntimeError: This event loop is already running


after some research with google , i found this
https://stackoverflow.com/questions/46827007/runtimeerror-this-event-loop-is-already-running-in-python
https://github.com/erdewit/nest_asyncio

Feature request: Official way of creating external plugins

I have created a few plugins I would like to distribute seperately on PyPI.

For now I have created them in a new top-level namespace like slack_machine_plugin_<name>, but this seems inelegant, and the doc-strings are not picked up for the help command.

Thoughts?

Information ? Scheduling and Listen_to

Hello
For the same fonction , i'd like to schedule thsi function and also have the possibility to force this function with a listen_to command

'class synchroAgenda(MachineBasePlugin):
"""Classe de gestion d'imports des evenements du calendrier support dans la
base de donnée pour affichage dans grafana"""
@listen_to(r"synchro agenda")
@schedule(hour='21', minute='05')'

When i try this i have an error message
Traceback (most recent call last): File "/home/devsupportbot/lib/python3.6/site-packages/machine/utils/pool.py", line 21, in run func(*args, **kargs) File "/home/devsupportbot/lib/python3.6/site-packages/machine/dispatch.py", line 50, in handle_event self._dispatch_listeners(listeners, event) File "/home/devsupportbot/lib/python3.6/site-packages/machine/dispatch.py", line 104, in _dispatch_listeners l['function'](message, **match.groupdict()) TypeError: sync_agenda() takes 1 positional argument but 2 were given

self.web_client.channels_list

Hi there,

Great to see the move towards slackclient v2 - thanks for all the work on the new version.

After debugging a KeyError relating to my tests with the new version (in which I was testing in a DM and a private channel) it seems the use of self.web_client.channels_list in machine/clients/singletons/slack.py may be causing it, due to it not including the same level of conversation coverage as conversations.list. At the moment, this appears to prevent the bot responding to private channel/DM messages.

Regards,
Kris

Running the default from the tutorial doesn't work

Hi, I'm completely new to this and probably making some silly mistake. I've followed your tutorial so far but it's silently failing. My local_settings.py looks like this:

import os

SLACK_API_TOKEN = os.environ.get('SLACK_BOT_TOKEN')

PLUGINS = ['machine.plugins.builtin.general.HelloPlugin',
           'machine.plugins.builtin.general.PingPongPlugin',
           'plugins.hitchhikers.UltimateQuestionPlugin']

The slack bot token is correct, the bot exists and I can make it say things directly using the slack_sdk WebClient. When I run slack-machine I don't see any errors, but the bot is doing nothing. It just sits there. Posting 42, !42, @botname 42 etc all does nothing. No output on the console either. I tried setting log level to debug - still nothing and no new output in the console. Deleting the token from env variables worked as expected with slack-machine throwing an error at startup.

Why is this happening? Am I missing some step?

(slack-glossary) ➜  slack-glossary git:(master) ✗ slack-machine
Initializing Slack Machine:
    Loading settings...
    Initializing storage using backend: machine.storage.backends.memory.MemoryStorage
    Loading plugins...
        ✓ machine.plugins.builtin.general:HelloPlugin
        ✓ machine.plugins.builtin.general:PingPongPlugin
        ✓ plugins.hitchhikers:UltimateQuestionPlugin

Starting Slack Machine:
    ✓ Connected to Slack
    ✓ Scheduler started
Bottle v0.13-dev server starting up (using WSGIRefServer())...
Listening on http://0.0.0.0:8080/
    ✓ Web server started
    ✓ Dispatcher started
Hit Ctrl-C to quit.

I've also experimented with using pipenv instead of venv and installing requirements.txt first before installing slack-machine from pip. What I realise now I didn't try yet is installing slack-machine from github.

slack-machine crashes with error wrong value type for field "topic.creator" - should be "str" instead of value "None"

Hi, I'm trying to test out slack-machine. I'm on Python 3.7 with latest version installed: Version: 0.20.1.

I only have the HelloPlugin enabled, when I run slack-machine in DEBUG mode I see a lot of API requests going through successfully, it appears to be paginating through channels and users and conversations, however it always gets to this point and crashes with error:

[2020-08-05 19:04:36][ERROR] slack.rtm.client client.py:_dispatch_event:505 | When calling '#_on_open()' in the 'machine.clients.singletons.slack' module the following error was raised: wrong value type for field "topic.creator" - should be "str" instead of value "None" of type "NoneType"
Traceback (most recent call last):
  File "/usr/local/bin/slack-machine", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.7/site-packages/machine/bin/run.py", line 14, in main
    bot.run()
  File "/usr/local/lib/python3.7/site-packages/machine/core.py", line 211, in run
    self._dispatcher.start()
  File "/usr/local/lib/python3.7/site-packages/machine/dispatch.py", line 34, in start
    self._client.start()
  File "/usr/local/lib/python3.7/site-packages/machine/clients/singletons/slack.py", line 121, in start
    self.rtm_client.start()
  File "/usr/local/lib/python3.7/site-packages/slack/rtm/client.py", line 206, in start
    return self._event_loop.run_until_complete(future)
  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 587, in run_until_complete
    return future.result()
  File "/usr/local/lib/python3.7/site-packages/slack/rtm/client.py", line 361, in _connect_and_read
    await self._dispatch_event(event="open", data=data)
  File "/usr/local/lib/python3.7/site-packages/slack/rtm/client.py", line 500, in _dispatch_event
    callback(**payload)
  File "/usr/local/lib/python3.7/site-packages/machine/clients/singletons/slack.py", line 74, in _on_open
    self._register_channel(c)
  File "/usr/local/lib/python3.7/site-packages/machine/clients/singletons/slack.py", line 49, in _register_channel
    channel = Channel.from_api_response(channel_response)
  File "/usr/local/lib/python3.7/site-packages/machine/models/channel.py", line 50, in from_api_response
    return from_dict(data_class=Channel, data=user_reponse)
  File "/usr/local/lib/python3.7/site-packages/dacite/core.py", line 60, in from_dict
    value = _build_value(type_=field.type, data=transformed_value, config=config)
  File "/usr/local/lib/python3.7/site-packages/dacite/core.py", line 83, in _build_value
    return _build_value_for_union(union=type_, data=data, config=config)
  File "/usr/local/lib/python3.7/site-packages/dacite/core.py", line 94, in _build_value_for_union
    return _build_value(type_=types[0], data=data, config=config)
  File "/usr/local/lib/python3.7/site-packages/dacite/core.py", line 87, in _build_value
    return from_dict(data_class=type_, data=data, config=config)
  File "/usr/local/lib/python3.7/site-packages/dacite/core.py", line 65, in from_dict
    raise WrongTypeError(field_path=field.name, field_type=field.type, value=value)
dacite.exceptions.WrongTypeError: wrong value type for field "topic.creator" - should be "str" instead of value "None" of type "NoneType"

I'm guessing this is a simple case of the Slack API returning something that we didn't expect, so I guess slack-machine must be made to treat topic.creator as None or even handling the fact that it might not exist. If you have any ideas how I could fix this locally please let me know.

Bug with bottle

Hello
To make slack machine configurable , i've made a web backoffice , i"ve updated my developpement environnemnt to your latest version and nothing is working anymore on this backoffice, here an example of my plugin join

`from machine.plugins.base import MachineBasePlugin
import bottle

class html(MachineBasePlugin):
@bottle.route('/')
def index():
heure = datetime.datetime.now().strftime(
"

Nous sommes le %d/%m/%Y, il est %H:%M:%S

" )
return bottle.template('index.tpl', title='Horloge',
title2='Bienvenue dans votre Backoffice ',
body=heure)`
while everything is ok with old version , with the new one i have 404 not found
i don't use your @route decorator because i need other bottle functions like template , hook etc...

i've tried using it and it's ok but other bottle function seems not working

Bot can respond to self using {say,reply}_webapi

@dandydev i have a listen_to function that listens for jira ticket mentions via regex in any message, and responds via say_webapi(). The problem im facing right now, is using *_webapi(), allows the bot to respond to itself, and in the case of say_webapi(), it's infinite. I have a quick fix for this, curious what your thoughts are. I'll upload a patch or at least a diff when I can, but in the mean time...
in handle_event() I'm wrapping the message events in

if not event['user'] == self._get_bot_id():

Failed to send a request to Slack API server: <urlopen error no host given>

On merging master here into my fork i am now getting the following.....
i'm guessing its something in the handoff to the slack rtm client, currently looking at what may have changed there

Successfully built slack-machine
Installing collected packages: slack-machine
Successfully installed slack-machine-0.19.2
(slack-machine) bash-3.2$ slack-machine
Initializing Slack Machine:
Loading settings...
Initializing storage using backend: machine.storage.backends.memory.MemoryStorage
Loading plugins...
✓ machine.plugins.builtin.general:PingPongPlugin
✓ machine.plugins.builtin.general:HelloPlugin
✓ machine.plugins.builtin.help:HelpPlugin
✓ machine.plugins.builtin.fun.images:ImageSearchPlugin
✓ machine.plugins.builtin.fun.memes:MemePlugin
✓ machine.plugins.prinfo:PRInfoPlugin
Starting Slack Machine:
✓ Connected to Slack
✓ Scheduler started
Bottle v0.13-dev server starting up (using WSGIRefServer())...
Listening on http://0.0.0.0:8080/
Hit Ctrl-C to quit.
✓ Web server started
✓ Keepalive thread started [Interval: 5s]
✓ Dispatcher started
[2020-07-16 09:41:57][ERROR] slack.web.base_client base_client.py:_perform_urllib_http_request:582 | Failed to send a request to Slack API server:
Traceback (most recent call last):
File "/private/tmp/slack-machine/.venv/bin/slack-machine", line 8, in
sys.exit(main())
File "/private/tmp/slack-machine/.venv/lib/python3.6/site-packages/machine/bin/run.py", line 14, in main
bot.run()
File "/private/tmp/slack-machine/.venv/lib/python3.6/site-packages/machine/core.py", line 211, in run
self._dispatcher.start()
File "/private/tmp/slack-machine/.venv/lib/python3.6/site-packages/machine/dispatch.py", line 34, in start
self._client.start()
File "/private/tmp/slack-machine/.venv/lib/python3.6/site-packages/machine/clients/singletons/slack.py", line 118, in start
self.rtm_client.start()
File "/private/tmp/slack-machine/.venv/lib/python3.6/site-packages/slack/rtm/client.py", line 206, in start
return self._event_loop.run_until_complete(future)
File "/Users/myuser/.pyenv/versions/3.6.9/lib/python3.6/asyncio/base_events.py", line 484, in run_until_complete
return future.result()
File "/private/tmp/slack-machine/.venv/lib/python3.6/site-packages/slack/rtm/client.py", line 352, in _connect_and_read
url, data = await self._retrieve_websocket_info()
File "/private/tmp/slack-machine/.venv/lib/python3.6/site-packages/slack/rtm/client.py", line 547, in _retrieve_websocket_info
resp = self._web_client.rtm_connect()
File "/private/tmp/slack-machine/.venv/lib/python3.6/site-packages/slack/web/client.py", line 1695, in rtm_connect
return self.api_call("rtm.connect", http_verb="GET", params=kwargs)
File "/private/tmp/slack-machine/.venv/lib/python3.6/site-packages/slack/web/base_client.py", line 215, in api_call
return self._sync_send(api_url=api_url, req_args=req_args)
File "/private/tmp/slack-machine/.venv/lib/python3.6/site-packages/slack/web/base_client.py", line 348, in _sync_send
additional_headers=headers,
File "/private/tmp/slack-machine/.venv/lib/python3.6/site-packages/slack/web/base_client.py", line 452, in _urllib_api_call
response = self._perform_urllib_http_request(url=url, args=request_args)
File "/private/tmp/slack-machine/.venv/lib/python3.6/site-packages/slack/web/base_client.py", line 583, in _perform_urllib_http_request
raise err
File "/private/tmp/slack-machine/.venv/lib/python3.6/site-packages/slack/web/base_client.py", line 564, in perform_urllib_http_request
req, context=self.ssl, timeout=self.timeout
File "/Users/myuser/.pyenv/versions/3.6.9/lib/python3.6/urllib/request.py", line 223, in urlopen
return opener.open(url, data, timeout)
File "/Users/myuser/.pyenv/versions/3.6.9/lib/python3.6/urllib/request.py", line 524, in open
req = meth(req)
File "/Users/myuser/.pyenv/versions/3.6.9/lib/python3.6/urllib/request.py", line 1241, in do_request

raise URLError('no host given')
urllib.error.URLError:
(slack-machine) bash-3.2$

Default response

Is there a way to specify default response when no respond_to regexes matches message?

Error on querying slack api

Hello
I've launch my slack machine in real prodcution and i have this error message when trying to load users informations

Traceback (most recent call last): File "/home/supportbot/bot/bin/slack-machine", line 10, in <module> sys.exit(main()) File "/home/supportbot/bot/lib/python3.6/site-packages/machine/bin/run.py", line 14, in main bot.run() File "/home/supportbot/bot/lib/python3.6/site-packages/machine/core.py", line 219, in run self._dispatcher.start() File "/home/supportbot/bot/lib/python3.6/site-packages/machine/dispatch.py", line 29, in start for event in self._client.rtm_read(): File "/home/supportbot/bot/lib/python3.6/site-packages/slackclient/client.py", line 235, in rtm_read json_data = self.server.websocket_safe_read() File "/home/supportbot/bot/lib/python3.6/site-packages/slackclient/server.py", line 296, in websocket_safe_read "Unable to send due to closed RTM websocket" slackclient.server.SlackConnectionError: Unable to send due to closed RTM websocket

cascade listen_to, reply_to for contextual reply?

I was trying to build daily standup meeting bot.
My daily standup bot have 4 questions:

  1. How do you feel?
  2. What did you do since yesterday?
  3. What will you do today?
  4. Anything blocking your progress?

I tried to use emit and @on events and found out it's not working, because I had to wait for user to reply.

    # WARNING: below codes doesn't work as intended.

    @respond_to("^daily.standup")
    def daily_standup_init(self, message):
        message.reply("Hello, how do you feel?")
        self.emit('dailyStandup_Q1', message=message)

    @on('dailyStandup_Q1')
    def daily_standup_done(self, **kwargs):
        reply=[]
        message=kwargs['message']
        reply['feel']=message.text
        self.say("What did you do since yesterday?")
        self.emit('dailyStandup_Q2', message=message, reply=reply)

    @on('dailyStandup_Q2')
    def daily_standup_plan(self, **kwargs):
        message=kwargs['message']
        reply['done']=message.text
        message.reply("What will you do today?")
        self.emit('dailyStandup_Q3', message=message, reply=reply)

    @on('dailyStandup_Q3')
    def daily_standup_blck(self, **kwargs):
        message=kwargs['message']
        reply['plan']=message.text
        message.reply("Anything blocking your progress?")
        self.emit('dailyStandup_Q4', message=message, reply=reply)

    @on('dailyStandup_Q4')
    def daily_standup_bye(self, **kwargs):
        message=kwargs['message']
        reply['blck']=message.text
        message.reply("Awesome! Have a great day :v:")
        self.emit('dailyStandup_bye', message=message, reply=reply)

is there any ways to do such thing? or is it even possible?
Then I was also thinking it would be nice if I could get some expected response in a criteria.
for example:

    @respond_to(r'I want to have some fruits')
    def fruit_choice(self, message):
        message.reply("Hello, which fruits do you want to have?\n1.orange\n2.pineapple\n3.watermelon")
        listen_for_reply(callback=fruit_favorite, message=message, timeout=0)

    def fruit_favorite(self, **kwargs):
        message=kwargs['message']
        message.reply("{} is your fruit? (answer in 30 seconds)".format(message.text))
        listen_for_reply(callback=choice_done, message=message, timeout=30)

    def fruit_complete(self, **kwargs):
        message=kwargs['message']
        message.reply("Thank you for your answer)")

...

With this idea, one can build some simple interactive bots, such as choosing from multiple choices, asking and feedback according to context.

FR : Log in a file

Hello
I will set up slack-machine for testing at work , is it possible to setup log in a file ?
Thx

Error slack.rtm.client client.py:_dispatch_event

@dandydev I got the error in 0.19.x version

[ERROR] slack.rtm.client client.py:_dispatch_event:445 | When calling '#handle_message()' in the 'machine.dispatch' module the following error was raised: 'DU6G9SQBC'

Would you please help me check this? It worked fine on 0.18.2 version

Responses to messages are sequential since 0.19

With recent changes slack-machine responses became sequential. Back in version 0.18.2 responses were processed in parallel and did not block each other. Currently, in case response method takes a significant amount of time to complete all other requests are queued and executed after a long-running response has completed.

Reproduction steps:
Define a simple sleep method:

    ###############################################################################
    @respond_to(r'^\s*sleep\s+(?P<sleep_time>\d+)\s*$', re.IGNORECASE)
    def sleep(self, message, sleep_time):
        message.reply('Sleeping: %s' % sleep_time)
        time.sleep(int(sleep_time))
        message.reply('Woken up')

And invoke it twice:
-> sleep 20
<- Sleeping: 20
-> sleep 20
<- Woken up
<- Sleeping: 20
<- Woken up

Expected result:
-> sleep 20
<- Sleeping: 20
-> sleep 20
<- Sleeping: 20
<- Woken up
<- Woken up

It seems that changes here: cause this behaviour

feature request: extend redis backend

Let's extend the redis backend to support more actions like:

This would be in order to scan or get all keys for a given plugin and iterate over them.

I'm trying to create a "Karma" plugin and I'd like to show the top Karma scores:

from machine.plugins.base import MachineBasePlugin
from machine.plugins.decorators import listen_to, respond_to
import re


class Karma(MachineBasePlugin):
    @respond_to(r'(?P<user>.*) \+\+')
    def up(self, msg, user):
        if self.storage.has(user):
            karma = self.storage.get(user)
            karma += 1
            self.storage.set(user, karma)
            msg.say('{}\'s karma is now: {}'.format(user, karma))
        else:
            self.storage.set(user, 1)
            msg.say('No karma found for: {}, setting to 1'.format(user))

    @respond_to(r'(?P<user>.*) \-\-')
    def down(self, msg, user):
        if self.storage.has(user):
            karma = self.storage.get(user)
            karma -= 1
            self.storage.set(user, karma)
            msg.say('{}\'s karma is now: {}'.format(user, karma))
        else:
            self.storage.set(user, -1)
            msg.say('No karma found for: {}, setting to -1'.format(user))

    @respond_to(r'.*(top karma).*')
    def top(self, msg):
        for i in self.storage.keys(pattern='*'):
            print(i)

in machine/storage/backends/redis.py:

...
    def get(self, key):
        return self._redis.get(self._prefix(key))

    def keys(self, pattern):
        return self._redis.keys(pattern='*')
...

Something like this...

But, I get: AttributeError: 'PluginStorage' object has no attribute 'keys'

Unable to launch slack-machine

When I try to launch the app, an error comes in:

Traceback (most recent call last):
  File "/home/thatside/own/venv/linker/bin/slack-machine", line 11, in <module>
    sys.exit(main())
  File "/home/thatside/own/venv/linker/lib/python3.6/site-packages/machine/bin/run.py", line 13, in main
    bot.run()
  File "/home/thatside/own/venv/linker/lib/python3.6/site-packages/machine/core.py", line 96, in run
    self._dispatcher.start()
  File "/home/thatside/own/venv/linker/lib/python3.6/site-packages/machine/dispatch.py", line 21, in start
    for event in self._client.rtm_read():
  File "/home/thatside/own/venv/linker/lib/python3.6/site-packages/slackclient/client.py", line 128, in rtm_read
    json_data = self.server.websocket_safe_read()
  File "/home/thatside/own/venv/linker/lib/python3.6/site-packages/slackclient/server.py", line 186, in websocket_safe_read
    data += "{0}\n".format(self.websocket.recv())
AttributeError: 'NoneType' object has no attribute 'recv'

Are there some nuances related to Python versions compatibility?

msg.say() in DM throws error

After upgrading to 0.19.2 I had to change say_webapi() to say() which unfortunately seems to have broken replies in DMs.

  File "/Users/me/bot/plugins/noru.py", line 36, in rebuild
    msg.say('Nice message')
  File "/Users/me/Library/Caches/pypoetry/virtualenvs/bot-UaO2qz8g-py3.8/lib/python3.8/site-packages/machine/plugins/base.py", line 340, in say
    self.channel.id,
  File "/Users/me/Library/Caches/pypoetry/virtualenvs/bot-UaO2qz8g-py3.8/lib/python3.8/site-packages/machine/plugins/base.py", line 275, in channel
    return self._client.channels[self._msg_event['channel']]
KeyError: 'DJDUJ1000'

[Docs] EventLoggerPlugin no longer exists

Hi there! I was going through to get a basic hello world running with this bot and got an error:

Initializing Slack Machine:
    Loading settings...
[2020-08-05 18:30:41][DEBUG] asyncio selector_events.py:__init__:58 | Using selector: KqueueSelector
    Initializing storage using backend: machine.storage.backends.memory.MemoryStorage
[2020-08-05 18:30:41][DEBUG] machine.core core.py:__init__:62 | Storage initialized!
    Loading plugins...
[2020-08-05 18:30:41][DEBUG] machine.core core.py:load_plugins:79 | PLUGINS: ['machine.plugins.builtin.general.HelloPlugin', 'machine.plugins.builtin.debug.EventLoggerPlugin']
[2020-08-05 18:30:41][DEBUG] machine.core core.py:load_plugins:83 | Found a Machine plugin: machine.plugins.builtin.general.HelloPlugin
        ✓ machine.plugins.builtin.general:HelloPlugin
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/machine/utils/module_loading.py", line 15, in import_string
    module = import_module(dotted_path)
  File "/usr/local/Cellar/python/3.7.7/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 962, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'machine.plugins.builtin.debug.EventLoggerPlugin'; 'machine.plugins.builtin.debug' is not a package

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/machine/utils/module_loading.py", line 22, in import_string
    return [("{}:{}".format(module_path, class_name), getattr(module, class_name))]
AttributeError: module 'machine.plugins.builtin.debug' has no attribute 'EventLoggerPlugin'

The most relevant line of the above is

ModuleNotFoundError: No module named 'machine.plugins.builtin.debug.EventLoggerPlugin';

I had my plugins list set to

PLUGINS = [
    # 'machine.plugins.builtin.general.PingPongPlugin',
    'machine.plugins.builtin.general.HelloPlugin',
    'machine.plugins.builtin.debug.EventLoggerPlugin',
    # 'machine.plugins.builtin.debug.EchoPlugin'
]

Likely the docs simply need to be updated where this is referenced as a possible Plugin. It looks like this was removed in a recent version, maybe 19 or 20 but I see it existed back here. I would update myself but I'm actually not sure at the moment what the replacement for EventLoggerPlugin is, or what it did. Perhaps it isn't needed because if we set the LOGLEVEL to "DEBUG" it will do the same thing that that Plugin did?

Connection is closing every few days

Every other day, slack bot is losing it's connection from some reason:

Traceback (most recent call last):
  File "/root/virtualenvs/tedbot/bin/slack-machine", line 11, in <module>
    sys.exit(main())
  File "/root/virtualenvs/tedbot/lib/python3.5/site-packages/machine/bin/run.py", line 14, in main
    bot.run()
  File "/root/virtualenvs/tedbot/lib/python3.5/site-packages/machine/core.py", line 198, in run
    self._dispatcher.start()
  File "/root/virtualenvs/tedbot/lib/python3.5/site-packages/machine/dispatch.py", line 23, in start
    for event in self._client.rtm_read():
  File "/root/virtualenvs/tedbot/lib/python3.5/site-packages/slackclient/client.py", line 135, in rtm_read
    json_data = self.server.websocket_safe_read()
  File "/root/virtualenvs/tedbot/lib/python3.5/site-packages/slackclient/server.py", line 194, in websocket_safe_read
    data += "{0}\n".format(self.websocket.recv())
  File "/root/virtualenvs/tedbot/lib/python3.5/site-packages/websocket/_core.py", line 300, in recv
    opcode, data = self.recv_data()
  File "/root/virtualenvs/tedbot/lib/python3.5/site-packages/websocket/_core.py", line 317, in recv_data
    opcode, frame = self.recv_data_frame(control_frame)
  File "/root/virtualenvs/tedbot/lib/python3.5/site-packages/websocket/_core.py", line 330, in recv_data_frame
    frame = self.recv_frame()
  File "/root/virtualenvs/tedbot/lib/python3.5/site-packages/websocket/_core.py", line 364, in recv_frame
    return self.frame_buffer.recv_frame()
  File "/root/virtualenvs/tedbot/lib/python3.5/site-packages/websocket/_abnf.py", line 361, in recv_frame
    self.recv_header()
  File "/root/virtualenvs/tedbot/lib/python3.5/site-packages/websocket/_abnf.py", line 309, in recv_header
    header = self.recv_strict(2)
  File "/root/virtualenvs/tedbot/lib/python3.5/site-packages/websocket/_abnf.py", line 396, in recv_strict
    bytes_ = self.recv(min(16384, shortage))
  File "/root/virtualenvs/tedbot/lib/python3.5/site-packages/websocket/_core.py", line 434, in _recv
    return recv(self.sock, bufsize)
  File "/root/virtualenvs/tedbot/lib/python3.5/site-packages/websocket/_socket.py", line 94, in recv
    "Connection is already closed.")
websocket._exceptions.WebSocketConnectionClosedException: Connection is already closed.

Not sure what is going on, but can the slack bot try to reconnect to slack if that happens. Or perhaps there should be some other approach?

Feature: Alias

I would be interested in having an 'alias' feature so that instead of @botName, just a symbol could be used.

I am looking at porting my plugin from lins05/slackbot and this is a feature I currently use to give a slash command like effect so users don't need to @botname every time.

I already coded it up, tested, and working in my fork (alias branch), but figured I would check if this is something you would be open to as a PR before I dive into setting up unit tests.

Feature idea: Use pydantic for loading configuration

Today Slack Machine uses a plain python file for its config, which I find less than ideal.

I would like to put my bot in git, but I don't want to commit any secrets into git.

To solve this I tried to do a simple import of the yaml module in local_settings.py, and load my secrets from there, but this won't work when using Redis as storage backend.

The reason it won't work is that the config is pickled and put into the storage, so any object will yield the error message seen in issue #273.

Changing to Dynaconf provides the benefit of letting me store my secrets separately from the main config.
It will also provide a lot of other benefits and features that Dynaconf provides, like letting me choose which format I want to store my config in, multiple environments etc.

What do you think?

Machine crash

Hello
this afternoon my prod machine crashes with this message

devsupportbot) [root@SRVHTLOE01 mybot]# less /var/log/supportbot/error.log
(devsupportbot) [root@SRVHTLOE01 mybot]# less /var/log/supportbot/error.log
  File "/home/supportbot/bot/lib/python3.6/site-packages/machine/bin/run.py", line 14, in main
    bot.run()
  File "/home/supportbot/bot/lib/python3.6/site-packages/machine/core.py", line 211, in run
    self._dispatcher.start()
  File "/home/supportbot/bot/lib/python3.6/site-packages/machine/dispatch.py", line 34, in start
    self._client.start()
  File "/home/supportbot/bot/lib/python3.6/site-packages/machine/clients/singletons/slack.py", line 118, in start
    self.rtm_client.start()
  File "/home/supportbot/bot/lib/python3.6/site-packages/slack/rtm/client.py", line 198, in start
    return self._event_loop.run_until_complete(future)
  File "/usr/local/lib/python3.6/asyncio/base_events.py", line 468, in run_until_complete
    return future.result()
  File "/home/supportbot/bot/lib/python3.6/site-packages/slack/rtm/client.py", line 339, in _connect_and_read
    await self._read_messages()
  File "/home/supportbot/bot/lib/python3.6/site-packages/slack/rtm/client.py", line 390, in _read_messages
    await self._dispatch_event(event, data=payload)
  File "/home/supportbot/bot/lib/python3.6/site-packages/slack/rtm/client.py", line 440, in _dispatch_event
    self._execute_in_thread(callback, data)
  File "/home/supportbot/bot/lib/python3.6/site-packages/slack/rtm/client.py", line 465, in _execute_in_thread
    future.result()
  File "/usr/local/lib/python3.6/concurrent/futures/_base.py", line 425, in result
    return self.__get_result()
  File "/usr/local/lib/python3.6/concurrent/futures/_base.py", line 384, in __get_result
    raise self._exception
  File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/home/supportbot/bot/lib/python3.6/site-packages/machine/clients/singletons/slack.py", line 82, in _on_user_change
    user = self._register_user(payload['data']['user'])
  File "/home/supportbot/bot/lib/python3.6/site-packages/machine/clients/singletons/slack.py", line 44, in _register_user
    user = User.from_api_response(user_response)
  File "/home/supportbot/bot/lib/python3.6/site-packages/machine/models/user.py", line 57, in from_api_response
    return from_dict(data_class=User, data=user_reponse)  # pragma: no cover
  File "/home/supportbot/bot/lib/python3.6/site-packages/dacite/core.py", line 63, in from_dict
    raise MissingValueError(field.name)
dacite.exceptions.MissingValueError: missing value for field "deleted"

Error "can't pickle module objects" using redis storage and schedule

I've created new project and scheduled couple of actions. Using memory storage everything works as expected, however when I switch to redis bot can't start due to:

Traceback (most recent call last):
  File "slack-bot/.py3/bin/slack-machine", line 10, in <module>
    sys.exit(main())
  File "slack-bot/.py3/lib/python3.7/site-packages/machine/bin/run.py", line 14, in main
    bot.run()
  File "slack-bot/.py3/lib/python3.7/site-packages/machine/core.py", line 195, in run
    Scheduler.get_instance().start()
  File "slack-bot/.py3/lib/python3.7/site-packages/apscheduler/schedulers/background.py", line 33, in start
    BaseScheduler.start(self, *args, **kwargs)
  File "slack-bot/.py3/lib/python3.7/site-packages/apscheduler/schedulers/base.py", line 162, in start
    self._real_add_job(job, jobstore_alias, replace_existing)
  File "slack-bot/.py3/lib/python3.7/site-packages/apscheduler/schedulers/base.py", line 867, in _real_add_job
    store.add_job(job)
  File "slack-bot/.py3/lib/python3.7/site-packages/apscheduler/jobstores/redis.py", line 82, in add_job
    self.pickle_protocol))
TypeError: can't pickle module objects

QUestion about blocks and buttons

Hello
If i send a message with block containing buttons and selections , how can i have the return of this button that was cliicked or the selection that as made ?

Using slack-machine in code

I would like to use slack-machine in code. Not by running slack-machine command.

I need to run the slack bot as a thread of a bigger application. I'm having a hard time finding a way to do this.

If it's already supported, please document it.

Issue : little pb slack machine repeat himself

Hello
my slack-machine is installed on a raspberry machine in a virtual env
i have this plugin which is very simple
`rom machine.plugins.base import MachineBasePlugin
from machine.plugins.decorators import listen_to
import re

class aide(MachineBasePlugin):
@listen_to(r"help?")
@listen_to(r"aide")
@listen_to(r"au secours")
def helpFunc(self, msg):
msg.reply(
"Pour l'astreinte indiquer : astreinte : la personne d'astreinte ; date : le lundi de la semaine d'astreinte")
`
when i type help? in slack i have 2 answers

image

Help needed ? like to use machine function outside a plugin

Hi
I'll like to create a generic function to say soehing to slack
here is a piece of code
`# -- coding: UTF-8 --
from plugins.helpers.gmail import Gmail
from machine.plugins.base import MachineBasePlugin

def mailToSlack(channel,
labelsToSearch=[],
labelsToRemove=[],
labelsToAdd=[]):
gm = Gmail()
mb = MachineBasePlugin()
reponse = gm.readMailExtranet(labelsToSearch,
labelsToRemove,
labelsToAdd)
if reponse:
print('reponse', reponse)
mb.say(channel=channel,
text=reponse)`

the purpose is to pick a specific label from gmail and post a message in slack
when i try this i have this message
'TypeError: init() missing 3 required positional arguments: 'client', 'settings', and 'storage''

Help needed , Scheduling from db

Hello
I'd like to store my scheduled job in db so tht everyone with rights could schedule without coding
fot tht i've created some tables with all job detail (hour to trigger the job ,function to exceute ...)
Now i'd like slack-machine to go trough my db tables and create a schedule for each task on startup or when it heards somethin like 'schedule tasks '
How can i do tht ?
Do i have to make it with APSscheduler or can i make it work with @schedule ?

Issue with slackclient 2.7.3

Still sorting out exactly what the heck is going on here and will submit a PR when I do if needed but it appears slack has done something to deprecate aiohttp < 3.6 connections

slackapi/python-slack-sdk#912

popped up a few hours ago but wanted to throw this here to save anyone else time trying to debug.

EDIT: appears you can fix it by upgrading aiohttp = "3.7.3"

note: this does not appear to be a slack-machine issue itself but will effect users of it none the less

FR : Capture text snippets

Hello
i'have tested this code
`from machine.plugins.base import MachineBasePlugin
from machine.plugins.decorators import process

class testevents(MachineBasePlugin):
@process("file_created")
def testFileUploadDetection(self, event):
self.say('ok')`

and nothing happen when added a file to my slack team

Dictionary passed into machine class is not used on slack client

Issue

Passing settings into the Machine class is ignored when generating the SlackClient. The Slack client class just runs a local_settings import via import_settings() when this seems to be unnecessary.

from machine import Machine
from machine.utils.collections import CaseInsensitiveDict

base_settings = {
    'PLUGINS': [],
    'STORAGE_BACKEND': 'machine.storage.backends.memory.MemoryStorage',
    'DISABLE_HTTP': True,
    'HTTP_SERVER_HOST': '0.0.0.0',
    'HTTP_SERVER_PORT': 8080,
    'HTTP_SERVER_BACKEND': 'wsgiref',
    'HTTP_PROXY': None,
    'HTTPS_PROXY': None,
    'KEEP_ALIVE': None,
    'SLACK_API_TOKEN': '<redacted token>'
}

settings = CaseInsensitiveDict(base_settings)
bot = Machine(settings=settings)
bot.run()

output:

pipenv run python test-bot.py                                     
Loading .env environment variables…
Initializing Slack Machine:
    Loading settings...
Traceback (most recent call last):
  File "test-bot.py", line 18, in <module>
    bot = Machine(settings=settings)
  File "/Users/henry.hollenstain/.virtualenvs/bot-9dQm3zAV/lib/python3.7/site-packages/machine/core.py", line 59, in __init__
    self._client = LowLevelSlackClient()
  File "/Users/henry.hollenstain/.virtualenvs/bot-9dQm3zAV/lib/python3.7/site-packages/machine/utils/__init__.py", line 14, in __call__
    cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
  File "/Users/henry.hollenstain/.virtualenvs/bot-9dQm3zAV/lib/python3.7/site-packages/machine/clients/singletons/slack.py", line 33, in __init__
    self.rtm_client = RTMClient(token=slack_api_token, proxy=http_proxy)
  File "/Users/henry.hollenstain/.virtualenvs/bot-9dQm3zAV/lib/python3.7/site-packages/slack/rtm/client.py", line 118, in __init__
    self.token = token.strip()
AttributeError: 'NoneType' object has no attribute 'strip'

Placing a local_settings.py file with a token works.

SLACK_API_TOKEN = 'redacted' 
pipenv run python test-bot.py                                           
Loading .env environment variables…
Initializing Slack Machine:
    Loading settings...
    Initializing storage using backend: machine.storage.backends.memory.MemoryStorage
    Loading plugins...

Starting Slack Machine:
    ✓ Connected to Slack
    ✓ Scheduler started
    ✓ Dispatcher started

It seems when generating the slack client https://github.com/DandyDev/slack-machine/blob/master/machine/core.py#L59

The client re imports settings already on the Machine class instead of passing in the settings to the LowLevelSlackClient:
https://github.com/DandyDev/slack-machine/blob/master/machine/clients/singletons/slack.py#L30

Proposed solution

Pass settings from the Machine class into LowLevelSlackClient

Cannot start after a clean install with a simple configuration file

Hi there,

I ran into this issue today after pip install slack_machine and follow the tutorials.

My local_settings.py is

SLACK_API_TOKEN="hidden"
PLUGINS = []

Then I ran slack-machine and saw the output below:

Initializing Slack Machine:
    Loading settings...
    Initializing storage using backend: machine.storage.backends.memory.MemoryStorage
    Loading plugins...

Starting Slack Machine:
    ✓ Connected to Slack
    ✓ Scheduler started
Bottle v0.13-dev server starting up (using WSGIRefServer())...
    ✓ Web server started
Listening on http://0.0.0.0:8080/
    ✓ Dispatcher started
Hit Ctrl-C to quit.

Traceback (most recent call last):
  File "/home/tradeops/.virtualenvs/default/bin/slack-machine", line 8, in <module>
    sys.exit(main())
  File "/home/tradeops/.virtualenvs/default/lib/python3.6/site-packages/machine/bin/run.py", line 14, in main
    bot.run()
  File "/home/tradeops/.virtualenvs/default/lib/python3.6/site-packages/machine/core.py", line 211, in run
    self._dispatcher.start()
  File "/home/tradeops/.virtualenvs/default/lib/python3.6/site-packages/machine/dispatch.py", line 34, in start
    self._client.start()
  File "/home/tradeops/.virtualenvs/default/lib/python3.6/site-packages/machine/clients/singletons/slack.py", line 118, in start
    self.rtm_client.start()
  File "/home/tradeops/.virtualenvs/default/lib/python3.6/site-packages/slack/rtm/client.py", line 198, in start
    return self._event_loop.run_until_complete(future)
  File "/usr/lib64/python3.6/asyncio/base_events.py", line 484, in run_until_complete
    return future.result()
  File "/home/tradeops/.virtualenvs/default/lib/python3.6/site-packages/slack/rtm/client.py", line 329, in _connect_and_read
    url, data = await self._retreive_websocket_info()
  File "/home/tradeops/.virtualenvs/default/lib/python3.6/site-packages/slack/rtm/client.py", line 503, in _retreive_websocket_info
    resp = await self._web_client.rtm_connect()
  File "/home/tradeops/.virtualenvs/default/lib/python3.6/site-packages/slack/web/base_client.py", line 214, in _send
    http_verb=http_verb, api_url=api_url, req_args=req_args
  File "/home/tradeops/.virtualenvs/default/lib/python3.6/site-packages/slack/web/base_client.py", line 244, in _request
    async with session.request(http_verb, api_url, **req_args) as res:
  File "/home/tradeops/.virtualenvs/default/lib/python3.6/site-packages/aiohttp/client.py", line 1012, in __aenter__
    self._resp = await self._coro
  File "/home/tradeops/.virtualenvs/default/lib/python3.6/site-packages/aiohttp/client.py", line 473, in _request
    ssl=ssl, proxy_headers=proxy_headers, traces=traces)
  File "/home/tradeops/.virtualenvs/default/lib/python3.6/site-packages/aiohttp/client_reqrep.py", line 291, in __init__
    self.update_proxy(proxy, proxy_auth, proxy_headers)
  File "/home/tradeops/.virtualenvs/default/lib/python3.6/site-packages/aiohttp/client_reqrep.py", line 519, in update_proxy
    raise ValueError("Only http proxies are supported")
ValueError: Only http proxies are supported

The server is an Amazon Cloud server, no proxy is set (env | grep -i proxy is empty).

What's interesting is that, if I run this locally, and install a HTTP proxy server and set it in the config like

HTTP_PROXY="http://127.0.0.1:1087"
SLACK_API_TOKEN='hidde'
PLUGINS=[]

...works like a charm.

I may have misunderstood but how to properly run it on the server without any proxy? Thanks!

Reacting to Bots and Apps

The slack-machine bot doesn't seem to react to apps and/or bots currently.

How could I trigger the bot with bot/app generated messages?

Altering RESPOND_MATCHER to match multiline messages.

Just noticed that the RESPOND_MATCHER in dispatch.py doesn't match messages such as:

@botname line 1
line 2

Adding re.DOTALL to RESPOND_MATCHER looks like it addresses this (and hopefully doesn't cause any other side effects).

Error since update

Hello
I've updated slack machine to latest release and i have this error after launching a scheduled message

[2019-03-12 21:35:00][DEBUG] apscheduler.scheduler base.py:_process_jobs:1017 | Next wakeup is due at 2019-03-13 21:35:00+01:00 (in 86399.996633 seconds)
Traceback (most recent call last):
  File "/home/pi/projets/supportBot/bin/slack-machine", line 10, in <module>
    sys.exit(main())
  File "/home/pi/projets/supportBot/lib/python3.5/site-packages/machine/bin/run.py", line 14, in main
[2019-03-12 21:35:00][INFO] apscheduler.executors.default base.py:run_job:144 | Job "suiviMeteo.humeurJour (trigger: cron[hour='21', minute='35'], next run at: 2019-03-13 21:35:00 CET)" executed successfully
    bot.run()
  File "/home/pi/projets/supportBot/lib/python3.5/site-packages/machine/core.py", line 219, in run
    self._dispatcher.start()
  File "/home/pi/projets/supportBot/lib/python3.5/site-packages/machine/dispatch.py", line 29, in start
    for event in self._client.rtm_read():
  File "/home/pi/projets/supportBot/lib/python3.5/site-packages/slackclient/client.py", line 235, in rtm_read
    json_data = self.server.websocket_safe_read()
  File "/home/pi/projets/supportBot/lib/python3.5/site-packages/slackclient/server.py", line 278, in websocket_safe_read
    data += "{0}\n".format(self.websocket.recv())
  File "/home/pi/projets/supportBot/lib/python3.5/site-packages/websocket/_core.py", line 310, in recv
    opcode, data = self.recv_data()
  File "/home/pi/projets/supportBot/lib/python3.5/site-packages/websocket/_core.py", line 327, in recv_data
    opcode, frame = self.recv_data_frame(control_frame)
  File "/home/pi/projets/supportBot/lib/python3.5/site-packages/websocket/_core.py", line 340, in recv_data_frame
    frame = self.recv_frame()
  File "/home/pi/projets/supportBot/lib/python3.5/site-packages/websocket/_core.py", line 374, in recv_frame
    return self.frame_buffer.recv_frame()
  File "/home/pi/projets/supportBot/lib/python3.5/site-packages/websocket/_abnf.py", line 361, in recv_frame
    self.recv_header()
  File "/home/pi/projets/supportBot/lib/python3.5/site-packages/websocket/_abnf.py", line 309, in recv_header
    header = self.recv_strict(2)
  File "/home/pi/projets/supportBot/lib/python3.5/site-packages/websocket/_abnf.py", line 396, in recv_strict
    bytes_ = self.recv(min(16384, shortage))
  File "/home/pi/projets/supportBot/lib/python3.5/site-packages/websocket/_core.py", line 449, in _recv
    return recv(self.sock, bufsize)
  File "/home/pi/projets/supportBot/lib/python3.5/site-packages/websocket/_socket.py", line 81, in recv
    bytes_ = sock.recv(bufsize)
  File "/usr/lib/python3.5/ssl.py", line 922, in recv
    return self.read(buflen)
  File "/usr/lib/python3.5/ssl.py", line 799, in read
    return self._sslobj.read(len, buffer)
  File "/usr/lib/python3.5/ssl.py", line 585, in read
    v = self._sslobj.read(len)
BlockingIOError: [Errno 11] Resource temporarily unavailable

`

Bugs ? on self.send_dm_webapi

Hello
here a piece of code for one of my plugin

@schedule(hour='22', minute='49') def humeurJour(self): """humeurJour : demande l'humeur du jour sur le canal meteo""" for u in session.query(users).order_by(users.id): print(u.name) self.send_dm_webapi(u.userID, 'Salut , ' + u.name + ' ,comment ça va aujourdhui')
, when it runs , i have this in logs files
Traceback (most recent call last): File "/home/pi/projets/supportBot/lib/python3.5/site-packages/apscheduler/executors/base.py", line 125, in run_job retval = job.func(*job.args, **job.kwargs) File "/home/pi/projets/supportBot/mybot/plugins/meteo.py", line 22, in humeurJour ' ,comment ça va aujourdhui') File "/home/pi/projets/supportBot/lib/python3.5/site-packages/machine/plugins/base.py", line 223, in send_dm_webapi return self._client.send_dm_webapi(user, text, attachments) File "/home/pi/projets/supportBot/lib/python3.5/site-packages/machine/slack.py", line 93, in send_dm_webapi dm_channel = self.open_im(u.id) File "/home/pi/projets/supportBot/lib/python3.5/site-packages/machine/slack.py", line 78, in open_im return response['channel']['id'] KeyError: 'channel'

listen to only message

thx for greate machine.
i really appreciate.
but i have one issue.

ex)
///
@listen_to('')
def to_duty(message):
print(message)
....

i want only listen_to NEW MESSAGE, NOT THREAD.
how can i solve this problem?

Bug ? Problem with reaction adding

Hello
I have a new problem on running this code
I doesn't appear until yesterday
It stops the bot and restart a few seconds later
Can you help me ?

Code :

def humeurJour(self):
        """humeurJour : demande l'humeur du jour sur le canal meteo"""
        for u in DbSession.query(users.utilisateur,
                                 slackusers.name,
                                 slackusers.user_id).join(slackusers,
                                                          services).filter(
                services.nom == "Support").order_by(
                users.slackid):
            print(u.user_id)
            msg = self.send_dm(u.user_id,
                               'Salut , ' + u.name +
                               ''' ,comment vas tu aujourdhui? \n
                                      Réagis en cliquant sur une icône''')
            channel = msg['channel']
            reaction_channel.append(channel)
            ts = msg['ts']
            for i in DbSession.query(emojis).order_by(emojis.score):
                print(i.emoji)
                self.react(channel, ts, i.emoji)

log :
[2020-03-17 14:00:43][ERROR] apscheduler.executors.default base.py:run_job:131 | Job "suiviMeteo.humeurJour (trigger: cron[day_of_week='mon-fri', hour='14', minute='0'], next run at: 2020-03 -18 14:00:00 CET)" raised an exception Traceback (most recent call last): File "/home/supportbot/bot/lib/python3.6/site-packages/apscheduler/executors/base.py", line 125, in run_job retval = job.func(*job.args, **job.kwargs) File "/home/supportbot/bot/mybot/plugins/meteo.py", line 44, in humeurJour self.react(channel, ts, i.emoji) File "/home/supportbot/bot/lib/python3.6/site-packages/machine/plugins/base.py", line 181, in react return self._client.react(channel, ts, emoji) File "/home/supportbot/bot/lib/python3.6/site-packages/machine/clients/slack.py", line 74, in react timestamp=ts) File "/home/supportbot/bot/lib/python3.6/site-packages/slack/web/client.py", line 1347, in reactions_add return self.api_call("reactions.add", json=kwargs) File "/home/supportbot/bot/lib/python3.6/site-packages/slack/web/base_client.py", line 171, in api_call return self._event_loop.run_until_complete(future) File "/usr/local/lib/python3.6/asyncio/base_events.py", line 468, in run_until_complete return future.result() File "/home/supportbot/bot/lib/python3.6/site-packages/slack/web/base_client.py", line 214, in _send http_verb=http_verb, api_url=api_url, req_args=req_args File "/home/supportbot/bot/lib/python3.6/site-packages/slack/web/base_client.py", line 244, in _request async with session.request(http_verb, api_url, **req_args) as res: File "/home/supportbot/bot/lib/python3.6/site-packages/aiohttp/client.py", line 1005, in __aenter__ self._resp = await self._coro File "/home/supportbot/bot/lib/python3.6/site-packages/aiohttp/client.py", line 575, in _request break File "/home/supportbot/bot/lib/python3.6/site-packages/aiohttp/helpers.py", line 585, in __exit__ raise asyncio.TimeoutError from None concurrent.futures._base.TimeoutError

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.