Edited at

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

More than 1 year has passed since last update.


はじめに

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を叩いたりできます。

使っていく中でまた何かあれば、追記(もしくは別の記事にて)しようと思います。

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


参考ページ