TL;DR
ErrBot
自作プラグインを作るときにはBotPlugin
クラスを継承するのですが、このクラスを追いかけていくとBotPluginBase
< StoreMixin
< MutableMapping
という継承関係にあります。
で、このうちの、StoreMixin
で実装されている部分になるのですが、__getitem__()
と__setitem__()
をオーバーライドしていて、辞書的なアクセスをされた際にはerrbot起動時に参照しているストレージに対して永続データをやり取りできるようになっています。
# -*- coding:utf8 -*-
from errbot import BotPlugin, botcmd
class TodoPlugin(BotPlugin):
@botcmd
def set_todo(self, msg, args):
from_id = str(msg.frm)
self[from_id] = args
@botcmd
def show_todo(self, msg, args):
from_id = str(msg.frm)
return self[from_id]
こんな感じで、書くと
set_todo
で投げた文字をtodoとして保持してくれ、show_todo
と投げると、保持しているtodoを返してくれます。
別のユーザーから同じコマンドを投げられても、別のキーになるので別の値として保持され、ユーザーごとのtodoを持てるようになります。
永続データ管理の注意点
こう書いても動きません。
# -*- coding:utf8 -*-
from errbot import BotPlugin, botcmd
class TodoPlugin(BotPlugin):
@botcmd
def set_todo(self, msg, args):
from_id = str(msg.frm)
todolist = self[from_id]
todolist.append(args)
あくまで、BotPluginの実装として動くのみのため、取り出したものに対して何かやっても無意味になります。
# -*- coding:utf8 -*-
from errbot import BotPlugin, botcmd
class TodoPlugin(BotPlugin):
@botcmd
def set_todo(self, msg, args):
from_id = str(msg.frm)
todolist = self[from_id]
todolist.append(args)
こんな感じで、一度値を丸ごと取り出して、編集した内容を丸ごとセットする必要があります。 1
使ってみた例
-
作ってみたtodoデモ
- 一番ストレートに保持したい内容をそのまま保持するケース
-
JpWeatherプラグイン
- あまり大元のAPIに迷惑をかけないように、マスターデータをキャッシュする用(起動時にのみ取り込み直す)
-
Teratail質問監視プラグイン
- 多重通知防止のために、最新の質問IDを保持しているケース
-
コンテキストマネージャーはあって、もうちょっと楽な書き方はあるのですが、今回は割愛 ↩