slackbotを特定のチャンネルでのみ反応するようにする (Python slackbot)


はじめに

Slackでslackbotを利用した自作botを運用しています。
用途別にチャンネルを作成しており、botの各プラグインはそれぞれ専用のチャンネルで実行する、という運用にしております。

しかし、チャンネルの用途とは異なるプラグインを実行してしまうというヒューマンエラーが度々起きており、なんとかしたいと考えていました。

そこで、特定のチャンネルでのみ処理を実行する機構をbotに実装しました。

※本記事にはslackbotの使用方法は記載しておりません

検証環境

Python 3.6.1
slackbot 0.5.3

デコレータによる処理を実行するチャンネルの指定

実行を許可するチャンネルを引数にとるデコレータを作ります。

import functools


def in_channel(allow_channel):
    def decorator(func):
        @functools.wraps(func)
        def wrapper(message, *args, **kargs):
            channel_id = message.body['channel']
            channel_info = message.channel._client.channels[channel_id]
            channel = channel_info['name']
            if allow_channel not in (channel, channel_id):
                message.reply("Please post in #{}".format(allow_channel))
                return
            return func(message, *args, **kargs)
        return wrapper
    return decorator

上記コードでは、引数はチャンネル名/チャンネルIDのどちらでもOKです。

そして、特定のチャンネルでのみ実行したい関数にデコレータを適用します。
私は先ほどのコードをutils.pyというファイルに記述しています。

from slackbot.bot import listen_to

from .utils import in_channel


@listen_to("^強い$")
@in_channel("playground")
def tsuyoi(message):
    message.reply("強くない:white_frowning_face:")

上記コードでは、 playground というチャンネルでのみ、関数tsuyoiが実行するように設定しています。

  • playgroundチャンネルで発言した場合

  • playgroundチャンネルで以外のチャンネルで発言した場合

注意する点

@in_channelはslackbotのデコレータ(上記例では@listen_to)よりもに記述してください。
順番が逆だと@listen_toの方が先に適用されます。その場合、メッセージが投稿されてしまうことを確認しています。

おわりに

デコレータでチャンネルを指定することで、用途が異なるチャンネルでプラグインを実行してしまうミスを防ぐことができました。

課題としては、(私の運用では問題ないのですが)チャンネルを1つしか指定できない点です。
複数のチャンネルを指定したい場合は、上記コードを少しいじる必要があります。

参考にしたページ

Limit slackbot responce to certain channel · Issue #152 · lins05/slackbot · GitHub
Python デコレータ再入門  ~デコレータは種類別に覚えよう~ - Qiita