rubyenvの設定
今回のボットでは他のライブラリを利用しないが、Xchatプラグインにおいて他のライブラリをrequireするには、rubyenvというファイルを作成しなければならない。なので、おまじないのように次のコマンドを実行しよう。ruby -e 'puts $:' > ~/.xchat2/rubyenv
チャンネルで発言する
挨拶をするというこことは、チャンネル上で発言をするということである。通常、Xchatを利用している場合、発言は単に入力エリアにメッセージを入力し、Enterで確定するだけであるが、実際にはその裏で/SAYというコマンドが発行されている。Xchatプラグインで発言を行うには、次のようにcommandメソッドを使おう。def say(words)
command("SAY #{words}")
end
commandメソッドは、先頭のスラッシュ(/)を除いた一行のコマンド文字列を引数にとる。わざわざsayメソッドを作ることもないが、上のようにしておけばわかり易いだろう。他のコマンドも同様の方法で実行することができる。どのようなコマンドがあるかは、Xchat上で/HELPコマンドを実行すれば分かるが、Xchat上で調べるのは一覧性に欠けるので、次のページなどを参照するといいだろう。
https://toxin.jottit.com/xchat_help_commands
誰かがチャンネルに入室した!
挨拶をするボットと言っても、闇雲に挨拶すればいいというものではない。例えばチャンネルに入室したタイミングなどが、挨拶をするのに適しているだろう。そのようなイベントに応答して何らかの処理を実行するにはフックを設定する必要がある。前回はChannel Messageなどのイベントにフックを設定したが、チャンネル参加時はJoinにフックを仕掛ける。フックを仕掛ける場所はinitializeメソッド中がいいだろう。def initialize
...
hook_print("Join", XCHAT_PRI_NORM, method(:join_hook), "Join.")
...
end
ここでは、join_hookというメソッドにフックをしかけている。誰かがチャンネルにJoin(入室)すると、join_hookメソッドが呼ばれるのだ。join_hookは好きなように定義すればいい。「自動挨拶ボット」では次のようにしている。def join_hook(words, data)
return XCHAT_EAT_NONE if away?
unless @greet_channel_list.include? words[1]
return XCHAT_EAT_NONE
end
say_greetings_or_wb(normalize_nick(words[0]))
return XCHAT_EAT_NONE
end
Joinフックでは、words[0]に新たに参加した人のニックネームが、words[1]にチャンネルが格納される。オマケだが、IRCを利用している人の中にはニックネームをfoo-awayなどのように変更して長時間離籍する人もいる。そのような人がチャンネルに復帰したことを検知するには、ニックネームの変更を追跡する必要があるだろう。そうするには、"Change Nick"イベントにフックを仕掛ければ良い。
def nick_change_hook(words, data)
return XCHAT_EAT_NONE if away?
unless @greet_channel_list.include? words[1]
return XCHAT_EAT_NONE
end
away_re = /[\|\_](afk|away|awy|zzz|bbl|brb|out)/i
if words[0] =~ away_re and not words[1] =~ away_re
say_greetings_or_wb(normalize_nick(words[1]))
end
return XCHAT_EAT_NONE
end
words[0]には変更前のニックネームが、words[1]には変更後のニックネームが格納されている。在籍中か否か。
前述の例にはaway?という名前のメソッドが登場した。これは何かというと、自分がaway(離席中)かどうかを調べるメソッドである。Xchatプラグインでは、get_infoというメソッドで各種情報を取得できるようになっている。そのまんまやんけ!とツッコミをいれたくメソッド名であるが、気にせず利用しよう。get_infoは調べたい対象を文字列引数としてとる。自分がawayかどうかを調べるには、get_info('away')という具合に利用する。以下はボットプラグインで定義されているaway?メソッドの中身である。def away?
return ((not get_info('away').nil?) or\
(get_info('nick') =~ /awa?y$|out$|afk$|bb[sl]$|lunch$/))
end
get_info('away')は、away中であればその理由を文字列で返す。get_info('nick')は自分のニックネームである。自分もmikiya|awayなどというニックネームに変更して離籍することがあるので、そのような場合にはawayであると判定しなければならない。get_infoで取得できる情報の詳細は、次のページを参照して欲しい。
http://xchat.org/docs/xchat2-perl.html#xchat_get_info
ディレイを入れる
誰かがチャンネルに参加したとき、電光石火で挨拶をしたらすぐにボットだと分かってしまうだろう。人間にはそのような離れ業は出来ないからだ。常識的に考えると、誰かがチャンネルに入ったのを見て、挨拶をタイプするという所作には、少なくとも数秒は掛かるはずである。しかし、ここで注意しなければならないのは、sleepしてはいけないということだ。sleepすると、Xchatの反応が止まってしまう。sleepせずに応答を遅らせるには、hook_timerを使う。def timed_print(words)
hook_timer(@delay * 1000, method(:say), words)
end
このようにすると、@delay秒後に、sayメソッドが呼ばれる。その時の引数はwordsである。hook_timerの第一引数の単位はミリ秒である。追記:hook_timerにより発動したイベントでは、フック登録時のコンテキスト(サーバーやチャンネルなど)が失われ、現在のチャンネルにメッセージが出力されることが分かった。フック登録時のコンテキストを利用するには、次のようにget_contextでコンテキストを保存し、set_contextを使ってコンテキストを復元しよう。
def timed_print(words)
ctx = XChatRuby::XChatRubyEnvironment.get_context()
data = {
:words => words,
:ctx => ctx,
}
hook_timer(@delay * 1000, method(:say_with_context), data)
end
def say_with_context(data)
ctx = data[:ctx]
XChatRuby::XChatRubyEnvironment.set_context(ctx) unless ctx.nil?
say(data[:words])
end
チャンネル参加者一覧
get_infoは単一の情報を取得するためのメソッドであり、「今このチャンネルには参加者がどれだけいるか?」というようなリストを返す問いには答えることが出来ない。他の言語用のプラグインではget_listという関数を用いることが出来るのだが、Rubyプラグインではget_listはXChatRubyListというクラスでラッピングされている。次のメソッドは、現在のチャンネルに居る参加者の一覧を得るものである。def get_users
users = []
cur = XChatRuby::XChatRubyList.new("users")
while cur.next do
users.push(cur.str('nick'))
end
users.sort
end
下手にラッピングされているのでRubyっぽくないコードになってしまうが、気にせずカーソルを回して情報をゲッツしよう。独自コマンドの定義
プラグインに命令を伝えるには、独自のコマンドを定義するのが一番の近道である。独自のコマンドを定義するのは非常に簡単だ。次のようにhook_commandメソッドを使って未定義のコマンドにフックを仕掛ければ良い。def initialize
...
hook_command("GREET", XCHAT_PRI_NORM, method(:handle_command),
"Usage: Greet , see /greet help for more info")
...
end
この例ではGREETというコマンドを新たに定義して、handle_commandメソッドをコールバックしている。def handle_command(words, words_eol, data)
if words.size < 2
display_help
else
case words[1].downcase
when "help"
display_help
when ""
display_help
when "all"
greet_all
when "status"
print_status
when "list"
list_nicks
when "config"
show_config
end
end
return XCHAT_EAT_NONE
end
words[0]にはGREETという文字列が、words[1]には一つめの引数が格納されている。words_eolは便利な引数で、コマンドの引数が長い場合、引数全体からwords[x-1]までの部分を取り除いた残りが格納される。words_eol[0]はコマンド全体を表す。







0 コメント:
コメントを投稿