LoginSignup
65
78

More than 5 years have passed since last update.

Python3系でSlack Botの作成〜基礎的な対話を実装する

Last updated at Posted at 2018-10-26

はじめに

PythonでSlackのBotを作成する機会があったので、自分のメモも兼ねて、Botユーザ作成〜基本的なやりとりの実装について記載します。

環境

  • Ubuntu 16.04.5
  • Python 3.5.2
    • slackbot 0.5.3
  • Slack
    • SlackのUIなどはバージョンにより変わる可能性有り

Slack Bot利用の事前準備

Botユーザを作成する

こちらにアクセスし、「Create ap app」をクリックします。
スクリーンショット_2018-10-26_18_59_02.png

Bot名(チャンネル上で表示される名前ではないです)と追加するワークスペースを指定して「Create App」をクリックします。
8-10-26_18_59_31.png

Botをユーザとして認識させる

Botをユーザとして認識させるためには、まずBotに権限を設定する必要がある。以下の画像に示す「permission scope」をクリックします。
スクリーンショット 2018-10-26 19.12.10.png

作成したBotの用途に合わせて権限を選択します。
例えば「メッセージの変更ができるような権限」「メッセージをPinする権限」などです。(今回はAdmin権限で作成)
スクリーンショット 2018-10-26 19.12.58.png

先ほどの画面に戻ると「Install App to Workspace」が有効化されているので選択し、以下の画像のような画面に遷移するので「Authorize」をクリックします。。
スクリーンショット_2018-10-26_19_17_00.png

Botのユーザとしての表示名と「Always Show My Bots as Online」をOnに設定します。(必要に応じてアイコンも設定しておく)
スクリーンショット 2018-10-26 19.51.41.png

これでチャンネルに招待できるようになりました。
スクリーンショット_2018-10-26_19_54_07.png

 Botの作成

導入部分はこちらの記事を参考にさせていただきました。

slackbotパッケージのインストール

以下のコマンドでslackbotパッケージをインストールします。

$ pip3 install slackbot

Botの初期設定

以下のような構成でファイル/ディレクトリを作成します。

root@ubuntu-xenial:/vagrant_data/slack_bot# tree
.
├── plugins                # botで動かすスクリプトを格納するディレクトリ
├── run.py                 # 実行のトリガーとなるスクリプト
└── slackbot_settings.py   # botの設定を記述するファイル

run.pyとslackbot_settings.pyの中身はそれぞれ以下のようになっています。

run.py
# coding: utf-8

from slackbot.bot import Bot

def main():
    bot = Bot()
    bot.run()

if __name__ == "__main__":
    print('starting slackbot')
    main()
slackbot_settings.py
# coding: utf-8

# SlackのAPIを利用するためのトークン
# Botの設定ページから「OAuth & Permissions」のページに遷移し、
# 「Bot User OAuth Access Token」をコピーして貼り付ける
API_TOKEN = "*****************************"

# 対応するメッセージがなかった場合に反応するメッセージ
DEFAULT_REPLY = "I dont't understand you."

# Botが実行するスクリプトを配置するディレクトリパスのリスト
PLUGINS = ['plugins']

Botの起動

run.py を実行してBotを起動します。

root@ubuntu-xenial:/vagrant_data/slack_bot# python3.5 run.py
starting slackbot

スクリーンショット_2018-10-26_20_22_47.png
無事返事が返ってきました。

Botスクリプトの実装

特定の単語に反応するようにする

Botの基本です。Botといえば、何かしら命令してその処理を行わせるものですが、その命令を読み取るための仕組みがこちらになります。

pluginsディレクトリの下に、Botが実行するスクリプト hello.py (名前はなんでも良い) と空ファイルの __init__.py を作成してください。 __init__py が存在しないと動かない点に注意してください。

root@ubuntu-xenial:/vagrant_data/slack_bot# tree
.
├── plugins
│   ├── hello.py
│   ├── __init__.py
〜以下略〜
hello.py
# coding: utf-8

from slackbot.bot import respond_to

@respond_to('Hello')
def reply_hello(message):
    message.reply('Hello')

スクリーンショット_2018-10-26_20_43_52.png
無事こちらのHelloに反応して、Helloと返してくれました。

メッセージを変数として受け取る

受け取りたいメッセージが固定の文字列だけとは限らないと思います。
その場合、渡すメッセージを変数として定義し、その内容に応じて処理をさせる、ということもできます。

respond_toの中で () で囲んだ部分が変数となり、関数の引数で定義した変数名で参照することができます。以下の例では、 .* で何かしらの文字列を読み取り、それを変数 arg に格納しています。

@respond_to('(.*)')
def reply_hello(message, arg):
    message.reply(arg)

スクリーンショット_2018-10-26_22_32_02.png

以下のように、変数は複数個別々に定義することも可能です。
例えばコマンドとオプションを別々に渡す、というような状況で使えます。

@respond_to('(.*) (.*)')
def reply_hello(message, arg1, arg2):
    message.reply(arg1 + ': ' + arg2)

スクリーンショット_2018-10-26_22_37_33.png
定義した通り、コロンで区切ってメッセージを返してくれました。

メッセージを正規表現で表す

反応するメッセージは正規表現で表すことも可能です。
詳しくはPythonの正規表現を参照してください。

下記の例だと [a-zA-Z] はアルファベットの文字列、 \s はスペースを表します。

@respond_to('[a-zA-Z]\sうさぎ')
def reply_hello(message):
    message.reply('どうしたの?')

スクリーンショット_2018-10-26_22_44_40.png
スペースを含まなかった場合には反応せず、スペースを含んだ文字列には反応してくれました。

記号を含むメッセージに反応させる

変数を別々に渡すことで、コマンドとオプションのように読み取ることができる、と書きましたが、記号はそのままでは読んでくれません。

記号を使うときは \ でエスケープが必要になります。
下記の例ではハイフンをエスケープ (\-) しており、何かしらの文字 + スペース + ハイフン付きのアルファベットに反応します。

@respond_to('(.*)\s(\-[a-zA-Z])')
def reply_hello(message, command, arg):
    message.reply(command + ' ' + arg + 'ですね')

スクリーンショット_2018-10-26_22_53_53.png

前の発言にスタンプをつける

slackといえばスタンプです!スタンプがつくと嬉しいと思うので、Botにスタンプを押してもらいましょう。

@respond_to('(スライムベス|スライム)')
def reply_hello(message, name):
    if name == 'スライムベス':
        message.react('slimebess')
    elif name == 'スライム':
        message.react('slime')

スクリーンショット_2018-10-27_0_46_06.png

ファイルを添付する

何か処理をし、その結果のログやファイルなどをファイルとして取得する…みたいな処理もさせることができます。

以下の例では get_file ~~~.txt にマッチするメッセージを送ると、ファイルが返ってくるという仕組みです。

@respond_to('get_file\s([a-zA-Z]*\.txt)')
def reply_hello(message, file_name):
    # fname: slack上で表示するファイル名
    # fpath: ファイルが置いてあるパス
    # initial_comment: slack上で表示するコメント
    message.channel.upload_file(fname=file_name, fpath=file_name, initial_comment=file_name + 'です')

スクリーンショット_2018-10-26_23_21_15.png

zipファイルだとこのような表示になります。
スクリーンショット_2018-10-27_1_37_29.png

メッセージを整形する

Botからのメッセージを整形することができます。
使えるパラメータはこちらを参照してください。

@respond_to('usagi')
def reply_hello(message):
    attachments = [
        {
            "color": "#3104B4",
            "fields": [
                {
                    "title": "場所",
                    "value": "東京駅"
                },
                {
                    "title": "時間",
                    "value": "19:00"
                }
            ],
            "footer": "usagi-san",
            "footer_icon": "https://pics.prcm.jp/db36726f85742/67433428/jpeg/67433428.jpeg"
        }
    ]
    message.send_webapi('集合場所', json.dumps(attachments))

スクリーンショット_2018-10-27_0_12_15.png

short をつけることで、以下のように横に並べて表示することもできます。

@respond_to('usagi help')
def reply_hello(message):
    attachments = [
        {
            'color': "#FF8000",
            'fields': [
                {'title': "コマンド", 'value': "usagi help", 'short': True},
                {'title': "説明", 'value': "ヘルプを表示します", 'short': True},
            ]
        }
    ]
    message.send_webapi('コマンド一覧', json.dumps(attachments))

スクリーンショット_2018-10-27_1_18_20.png

おわりに

本記事ではPythonでslackのBotを作成する方法を記載しました。

このようにメッセージを渡し、そこから他のAPIと連携してJenkinsのジョブのビルドしたり、AWSのAPI Gatewayを叩いたりできます。
使っていく中でまた何かあれば、追記(もしくは別の記事にて)しようと思います。

また「こういう使い方は便利だよ」とか「こういう風に書いた方が良いよ」みたいな指摘も大歓迎です。

参考ページ

65
78
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
65
78