Edited at

Errbot: Python製chatbotの基礎

More than 1 year has passed since last update.


概要

ErrbotはPython製のchatbotです。

このページにはErrbotのプラグイン(自作bot)の作り方で学んだことをまとめます。

内容は公式ドキュメントのPlugin Developmentに概ね沿っていて

Pythonの基礎的な知識があれば容易に理解できるはずです。

環境構築については以前の記事をご参照ください。


作成前の基礎知識


ローカルディレクトリの読み込み

基本的にErrbotにおけるpluginは

組み込みの!reposコマンドによりgitを経由して管理されます。

ただし、開発中はいちいちgitリポジトリにソースをあげるのも手間ですので

ローカルディレクトリからpluginを読み込みます。

errbot --initによって生成されたconfig.pyの中に

BOT_EXTRA_PLUGIN_DIRという設定項目があります。

ここにローカルディレクトリとしたいディレクトリのパスを記載します。

とはいえ、デフォルトでpluginsディレクトリが指定されているはずですので

そのまま使って問題ないはずです。


テストモードでの実行

他のサーバとの接続なしでbotのデバッグをするため

起動時に--text-Tを指定することで、テストモードでの実行が行えます。

testではなくtextです。


テストモードでの起動

$ errbot --text



pluginの構成ファイル



  • .plugファイル: pluginのメタデータをINIファイル形式で記載


  • .pyファイル: pluginで実際に処理されるPythonコードを記載

詳細は後述します。


Hello, World!


ファイルの作成

BOT_EXTRA_PLUGIN_DIRで指定されているディレクトリ内に

HelloWorldディレクトリとその構成ファイルを作成します。

plugins/           

|~err-example/
| |-example.plug
| `-example.py
`~HelloWorld/
|-helloworld.plug
`-helloworld.py

helloworld.pyには、例に従って以下のように記載します。


helloworld.py

from errbot import BotPlugin, botcmd

class HelloWorld(BotPlugin):
"""Example 'Hello, world!' plugin for Errbot"""

@botcmd
def hello(self, msg, args):
"""Say hello to the world"""
return "Hello, world!"



コードの解説

まず、pluginの継承元になるクラスと

コマンドに対応する関数を作成するためのデコレータをimportします。


helloworld.py

from errbot import BotPlugin, botcmd


BotPluginクラスを継承し、plugin用のクラスを生成します。

docstringの部分は!helpコマンドを使った際に表示されます。


helloworld.py

class HelloWorld(BotPlugin):

"""Example 'Hello, world!' plugin for Errbot"""

次に関数を記載し、@botcmdでデコレートします。

関数名がコマンド名になり、botは!helloコマンドを受け付けるようになります。

関数内のdocstringも、!helpコマンドを使った際に表示されます。


helloworld.py

@botcmd

def hello(self, msg, args):
"""Say hello to the world"""
return "Hello, world!"

hello関数はmsgargsという複数の引数を受け取ります。



  • msg: ユーザが入力した文章全体


  • args: ユーザが入力した文章からコマンド部分を除いたもの

例えば、!hello hoge mogeと入力した際は以下の値を格納しています。



  • msg: '!hello hoge moge'


  • args: 'hoge moge'

両方ただの文字列っぽく書いてますが、msg

errbot.backends.base.Messageクラスのインスタンスのようです。


pluginのメタデータ

helloworld.plugには、例に従って以下のように記載します。

[Core]

Name = HelloWorld
Module = helloworld

[Python]
Version = 2+

[Documentation]
Description = Example "Hello, world!" plugin



  • Name: 実行ファイルの名前から.pyを除いたもの


  • Module: botクラスとなるモジュール(Nameで指定したファイル内)


  • Version: 対応するPythonのバージョン(詳細不明)


  • Description: プラグインの詳細(詳細不明)


作成したbotの実行

ここまで記載すれば、botの実行が可能になります。


helloコマンドの実行

 >>> !hello

Hello, World!


コマンド作成における応用


引数の自動分割

botcmdデコレータには引数が指定可能です。

キーワード引数としてsplit_args_withを指定することで

前述のargs変数をリストとして受け取ることができます。


引数の分割

@botcmd(split_args_with=None)

def action(self, mess, args):
# !action one two three と入力したときに
# argsは ['one', 'two', 'three']を受け取る

split_args_withの指定はstr.split()のように振る舞い

Noneはホワイトスペースを示しています。


サブコマンド

関数名の中で_を使用している場合、_以降はサブコマンドとして扱われます。

これはコマンドのグルーピングに役立ちます。


サブコマンド

@botcmd

def basket_add(self, mess, args):
# !basket add という入力に対応
pass

@botcmd
def basket_remove(self, mess, args):
# !basket remove という入力に対応
pass


このとき、addremoveはあくまでもコマンドの一部ですので

argsの中に引数として格納されることはないようです。


argparseによる引数の分割

botcmdの代わりにarg_botcmdデコレータを使用することで

argparseのフォーマットで引数を定義することができます。

デコレータは重ねて記載することで複数の指定が可能です。


argparseによる引数の指定

@arg_botcmd('first_name', type=str)

@arg_botcmd('--last-name', dest='last_name', type=str)
@arg_botcmd('--favorite', dest='favorite_number', type=int, default=42)
def hello(self, mess, first_name=None, last_name=None, favorite_number=None):
# !hello Err --last-name Bot と入力したとき
# first_name は 'Err'
# last_name は 'Bot'
# favorite_number は 42(デフォルト値)


まとめ

pluginの作成の基本的な部分について書きました。

引数はある程度自由に受け取れるようになったため

あとはPythonで実行させたい処理を好き勝手に処理を書くだけです。

他にも正規表現を用いたコマンドの使用やテンプレートの活用など

シンプルながら多くの機能があるようです。

興味を持たれたら、ドキュメントをご一読ください。