Posted at

Errbotのcrontabもどき

More than 3 years have passed since last update.

Errbotを使い始めた頃に、ボットらしく「毎日指定時間に喋らせる」をやろうとして色々試していた時のログなどを振り返り。


Errbotにはcrontab的機能はなさそう

いずれも、crontabに相当する機能はなさそう。Googleに至っては「Errbotなにそれ?errならわかるけど」みたいな検索結果しか返してくれない


Errbotにあるスケジューリング機能

http://errbot.io/en/latest/user_guide/plugin_development/scheduling.html

crontabのように、「特定条件の時間に何かを実行する」仕組みは見当たらなかったのですが、

「定期的に何かを実行する」はスケジューリング機能として存在します。


Errbotサイトの機能サンプル

from errbot import BotPlugin

class PluginExample(BotPlugin):
def my_callback(self):
self.log.debug('I am called every minute')

def activate(self):
super().activate()
self.start_poller(60, self.my_callback)


Errbotの起動時に配下のPluginをまとめてロードするのですが、インスタンス生成時にactivate()メソッドを一回だけ実行します。

このタイミングで、start_poller()を実行することで、一定間隔ごとにメソッドを実行できるように設定が可能になります。

サンプルコードの場合は、1分間隔でmy_callback()を実行してデバッグログをロギングする挙動となります。


スケジューリング機能をもとに、雑にcrontabもどきを実装してみる

試しに実装して、しばらく動かしていた一番雑なcrontabもどき


crontab.py

# -*- coding:utf8 -*-

from errbot import BotPlugin
from datetime import datetime

class Crontab(BotPlugin):
"""Crontab polling plugin for Errbot
"""

def activate(self):
super(Crontab, self).activate()
self.start_poller(60, self.poll_crontab)

def poll_crontab(self):
self.log.debug('Run polling for crontab')
user = self.build_identifier('@attakei')
polled_time = datetime.now()
if polled_time.strftime('%H:%M') == '13:00':
self.send(user, 'そろそろお昼?')


ちょっと強引ですが、


  • activate時には毎分単位でとりあえずpoll_crontab()を呼ぶようにする

  • poll_crontabの中では、


    • 呼ばれた時間を取得

    • 動かしたい時間に該当してたらメッセージを送信



という「動けばいいや」系なもの。


注意点した点1:メッセージの送り方

@botcmdデコレーターを使った命令の場合だと、メソッドは文字列を返せばそのままメッセージとしてくれるのですが、ポーリングされているメソッドが文字列を返しても何もしてくれないっぽく、send()を使って明示的にメッセージを送信していく必要があります。


注意した点2:じわりじわりと時間がずれる

どちらかというか、最終的に諦めた部分なのですが。

時間が来る→実行条件を満たしているジョブを実行する ではなく、

定期的に時間をチェックする→実行条件を満たしているジョブを実行する だからなのか、

しばらく放っておくと、じわりじわりとメッセージを送ってくる時間がずれていきます。(最大59秒)

雑に動作確認できた分までだと、

* ポーリングを1分間隔から30分間隔にして

* 秒が30未満のときだけジョブ実行判定する

などにすれば、もうちょっとは楽かなとは思います。