Errbotは本体設定とは別に、botプラグインごとの設定をストレージに保持することができます。
これは、APIトークンなどの設定を置けるようになり、プラグイン開発側にもパブリックなプラグインとして公開しやすくなるメリットがあります。
Gitter眺めてたら、Config周りのやり取りがあったので、軽く自分の理解をまとめてみることにしました。
Botプラグインの設定についての概要
外からの見え方
Errbotはインストールされている各Botプラグインにに対して、
-
!plugin config example
で、プラグインの設定取得 -
!plugin config example (dictの文字列表現)
で、プラグインの設定反映
ができます。(いずれも、bot管理者ユーザーのみ)
内部での取扱い
プラグイン内部では、self.config
でこれらのアクセスが可能になってます。
class ExamplePlugin(BotPlugin):
@botcmd
def hello(self, msg):
"""!helloに対して、設定として保存しているEXAMPLE_VALUEと答えるコマンド
"""
return self.config['EXAMPLE_VALUE']
設定用コマンドの挙動
前述のように、「dictの文字列表現」と書きましたが、何も全部の形式を受け付けるわけではありません。
!plugin config plugin config example
[@CHANGE_ME ➡ @errbot] [␍]
Default configuration for this plugin (you can copy and paste this directly as a command):
!plugin config example
{'EXAMPLE_KEY_1': 'Example value', 'EXAMPLE_KEY_2': ['Example', 'Value']}
Botプラグインが有効になった瞬間には、基本的に設定値には何も入っていません。
この状態で!plugin config example
と呼びかけると、上のように返ってきます。
これは、Botプラグインclassが持っている、get_config_template
が返しているのですが、
デフォルトではこの形式と過不足なく同じになっていないと、受け付けてくれません。
class ExamplePlugin(BotPlugin):
def get_configuration_template(self):
"""
Defines the configuration structure this plugin supports
You should delete it if your plugin doesn't use any configuration like this
"""
return {'EXAMPLE_KEY_1': "Example value",
'EXAMPLE_KEY_2': ["Example", "Value"]
}
[@CHANGE_ME ➡ @errbot] >>> !plugin config example {'EXAMPLE_KEY_1': 1}
[@CHANGE_ME ➡ @errbot] [␍]
Incorrect plugin configuration: {'EXAMPLE_KEY_1': 1} doesn't contain the key EXAMPLE_KEY_2
# 「キーが足りない」と怒られる
[@CHANGE_ME ➡ @errbot] >>> !plugin config example {'EXAMPLE_KEY_1': 1, 'EXAMPLE_KEY_2' : 'test2'}
[@CHANGE_ME ➡ @errbot] [␍]
Incorrect plugin configuration: Example value [<class 'str'>] is not the same type as 1 [<class 'int'>]
# 「型が一致してない」と怒られる
[@CHANGE_ME ➡ @errbot] >>> !plugin config example {'EXAMPLE_KEY_1': 'test1', 'EXAMPLE_KEY_2' : 'test2'}
[@CHANGE_ME ➡ @errbot] [␍]
Incorrect plugin configuration: ['Example', 'Value'] [<class 'list'>] is not the same type as test2 [<class 'str'>]
# 「型が一致してない」と怒られる(2)
[@CHANGE_ME ➡ @errbot] >>> !plugin config example {'EXAMPLE_KEY_1': 'test1', 'EXAMPLE_KEY_2' : [2]}
[@CHANGE_ME ➡ @errbot] [␍]
Incorrect plugin configuration: Example [<class 'str'>] is not the same type as 2 [<class 'int'>]
# 表面的な型だけでなく、listなら要素の型が違っても許されない
[@CHANGE_ME ➡ @errbot] >>> !plugin config example {'EXAMPLE_KEY_1': 'test1', 'EXAMPLE_KEY_2' : ['test2', ]}
[@CHANGE_ME ➡ @errbot] [␍]
Plugin configuration done.
# 許された
実態としては、check_configuration
メソッドとが呼ばれており、このメソッドが、errbot.utils.ValidationException
を返さなければバリデーションOKとなっています。12
もし、設定が必要なプラグインを外部に公開する場合は、get_configuration_template
を設定して、どういう設定が必要なのかを明示してあげると良いでしょう。
設定値はどこに置かれるか?
Errbotにおいて、Botプラグインの永続化データはStorageプラグインを通して、プラグインごとの領域に保存されます。
が、この設定値はプラグインごとの領域ではなく、Errbot全体情報を持つcore領域に置かれます。
見てみる
そのままだとShelf形式でちょっと分かりづらいので、昨年のACで作ったYAML形式にするストレージプラグインを使ってみます。
起動時
起動直後のdataフォルダです。core.ymlだけが存在しています3
$ ls -l data/
total 4
-rw-r--r-- 1 attakei users 12 Jun 10 22:46 core.yml
drwxr-xr-x 2 attakei users 6 Jun 10 22:41 plugins
このあと、!plugin reload example
など、一度状態を保持しないといけないアクションが発生すると、
その時初めてストレージが生成されます。今回は、速攻でリロードしたので永続化対象はなく、
空のdictが保存されています。
$ ls -l data/
total 8
-rw-r--r-- 1 attakei users 12 Jun 10 22:46 core.yml
-rw-r--r-- 1 attakei users 3 Jun 10 22:46 example.yml
drwxr-xr-x 2 attakei users 6 Jun 10 22:41 plugins
$ data/example.yml
{}
設定をセーブする
前段に書いたとおり、ルールに従って設定を保存してみます。
!plugin config example {"EXAMPLE_KEY_1": "test1", "EXAMPLE_KEY_2": ["t1", "t2"]}
$ ls -l data/
total 8
-rw-r--r-- 1 attakei users 82 Jun 10 22:50 core.yml
-rw-r--r-- 1 attakei users 3 Jun 10 22:50 example.yml
drwxr-xr-x 2 attakei users 6 Jun 10 22:41 plugins
example.yml
は全く増えてないですね。その代わりに、core.yml
のファイルサイズが大きく増加しています。
中身を覗いてみましょう。
$ cat data/core.yml
configs:
example:
EXAMPLE_KEY_1: test1
EXAMPLE_KEY_2:
- t1
- t2
coreの中にconfigsというキーがあり、ここに各プラグインごとに保存されるようです。
「なんで各プラグイン側の領域に管理しないんだ?」と思ったのですが、
よく考えればプラグイン用ストレージはまるっと永続化データの置き場となっていることを考えると、
こっちに置いたほうが良いんだろうなと考え直しました。