LoginSignup
16
17

More than 5 years have passed since last update.

Errbot: Python製chatbotの基礎

Last updated at Posted at 2016-10-05

概要

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で実行させたい処理を好き勝手に処理を書くだけです。

他にも正規表現を用いたコマンドの使用やテンプレートの活用など
シンプルながら多くの機能があるようです。
興味を持たれたら、ドキュメントをご一読ください。

16
17
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
16
17