nadoka のプラグインの作り方

nadoka のプラグインを作ってみようと思ったのですが、あまり情報がなくて苦労したので、自分が調べたことをメモとして残しておきます。

プラグインファイルの場所

rc ファイルの Plugins_dir に指定されている場所に置きます。 Ubuntu の場合は /usr/share/nadoka/plugins/ に標準プラグインが置かれています。 Plugins_dir には配列を指定できるので、次のように独自のディレクトリを指定することも可能です。

Plugins_dir = ['/usr/share/nadoka/plugins', '/etc/nadoka/plugins']

プラグインファイル

Nadoka::NDK_Bot を継承したクラスを作成します。

プラグインファイル名は、プラグインのクラス名を小文字化して拡張子 .nb を付与したものです。

[hoge.nb]

class Hoge < Nadoka::NDK_Bot
end

設定

rc ファイルに次のように設定します。

BotConfig = [
  {                   # プラグインに渡したい値がある場合
    :name => :Hoge,
    :attr => 12345,
    ...
  },
  :Hoge,              # プラグインに渡したい値がない場合
  ...
]

Hash で指定した場合は、プラグイン中でその Hash を @bot_config インスタンス変数で参照できます。

初期化と終了

初期化時に何か処理が必要な場合は、クラスに bot_initialize メソッドを定義します。 終了時の処理は bot_destruct メソッドです。

class Hoge < Nadoka::NDK_Bot
  def bot_initialize
    # 初期化処理
    @bot_config[:attr]
  end

  def bot_destruct
    # 終了時の処理
  end
end

イベントハンドラ

on_xxxx 形式のメソッドを定義しておくと、対応したイベントが発生する度にそのメソッドが呼び出されます。

on_privmsg, on_join, on_part などのように、on_ の後に IRC のコマンド名を指定すると、そのコマンドが発生する度にメソッドが実行されます。 第1引数は Nadoka::NDK_Server::PrefixObject で第2引数はチャネル名です。 privmsgpart の場合は第3引数にメッセージが渡されます。

on_timer メソッドは、1分毎に呼び出されます。 引数は、現在時刻の Time オブジェクトです。

on_every_message メソッドは、すべてのメッセージで呼び出されます。 引数は、Nadoka::NDK_Server::PrefixObject, コマンド, メッセージパラメータ です。

on_quit_from_channel メソッドは、QUIT 時に呼び出されます。 引数は、チャネル名, ニックネーム, QUIT メッセージ です。

on_client_login, on_client_logout メソッドは、nadoka にクライアントがログイン/ログアウトした時に呼び出されます。 引数は、クライアント数, Nadoka::NDK_Client です。

on_client_privmsg メソッドは、nadoka クライアントがメッセージを送った時に呼び出されます。 引数は、Nadoka::NDK_Client, チャネル名, メッセージ です。

on_nadoka_command メソッドは、nadoka クライアントが /nadoka でコマンドを送った時に呼び出されます。 引数は、Nadoka::NDK_Client, コマンド名, パラメータ です。

on_server_connected メソッドは、nadoka がサーバーに接続した時に呼び出されます。 引数はありません。

on_sigusr1, on_sigusr2 メソッドは、nadoka が SIGUSR1, SIGUSR2 シグナルを受けた時に呼び出されます。 引数はありません。

メッセージ送信

イベントハンドラ等から IRC サーバーに対してメッセージを送信できます。

send_notice, send_privmsg でメッセージを送ることが出来ます。 引数は、チャネル名、メッセージ文字列です。

プラグイン

作ろうと思っていたプラグインは、ある時刻にあるチャネルに対して指定したメッセージを書き込むものでした。

最初は on_timer を使おうと思ったのですが、on_timer では秒単位まで制御できなかったので、結局イベントハンドラを使わずにスレッドを使うことにしました。

次のファイルを [hoge.nb] という名前でプラグインディレクトリに置きます。

class Hoge < Nadoka::NDK_Bot
  def bot_initialize
    @threads = []
    @bot_config[:message].each do |ch, time_message|
      thr = Thread.new do
        data = time_message.sort_by{|time,| time}
        while true
          now = Time.now
          now_hhmm = now.strftime('%H:%M')
          hhmm, message = data.find{|time,| now_hhmm < time} || data.first
          h, m = hhmm.split(/:/, 2)
          at = Time.local(now.year, now.mon, now.day, h, m, 0)
          at += 86400 if now > at
          sleep(at - now)
          send_privmsg ch, message
        end
      end
      @threads.push thr
    end
  end

  def bot_destruct
    @threads.each do |thr|
      thr.exit
    end
    @threads.clear
  end
end

rc ファイルに次のように設定します。

  BotConfig = [
    ...
    {
      :name => :Hoge,
      :message => {
        '#ch1' => {
          '07:00' => 'おはよう',
          '12:00' => 'こんにちわ',
          '22:00' => 'おやすみ',
        },
        '#ch2' => {
          '08:00' => 'でかける時間です',
          '18:00' => '帰る時間です',
        },
      },
    },
  ]