Go言語でIRC-BOTを動かしてみる
こんにちは、ムックです。
BOTといえば、node.jsのHubotのようなbotフレームワークがありますが、今回は、Go言語のIRC-BOTライブラリを使って以下の機能を持つIRC-BOTを実装したいと思います。
- 順番を決めるようなダイス機能
- メンバーの中からランダムで一人選ぶ機能
- MTG、提出物などのリマインダ機能
IRC-BOT
http://waterpigs.co.uk/articles/a-simple-go-irc-bot/
時刻処理
https://godoc.org/github.com/robfig/cron
ライブラリを利用させてもらいました。
IRC-BOTの生成
まずは、IRC-BOTの生成
1 2 3 4 5 6 7 8 |
[sourcecode lang="text"] ircobj := irc.IRC("my_nick", "my_name") ircobj.UseTLS = true ircobj.TLSConfig = &tls.Config{InsecureSkipVerify: true} ircobj.Password = "passwd" if err := ircobj.Connect("172.16.1.100:6667"); err != nil { fmt.Println(err) } [/sourcecode] |
1行目、ニックネーム、名前の指定。
2,3行目、SSL接続を利用する場合はUseTLSをtrueに、configに任意の設定をします。
4行目、パスワードを指定。
最後に、Connectでホスト名、ポートを指定でします。
コールバック処理
1 2 3 4 5 |
[sourcecode lang="text"] // ウェルカム処理 ircobj.AddCallback("001", func (e *irc.Event) { ircobj.Join("#system_channel") }) [/sourcecode] |
AddCallbackで、トリガーとなるメッセージと第二引数に実行される関数を記述します。
上記では、RPL_WELCOMEを受け取ったらJOIN処理を行っています。
irc.Eventは以下の様な構造になります。
1 2 3 4 5 6 7 8 9 |
[sourcecode lang="text"]type Event struct { Code string Raw string Nick string //<nick> Host string //<nick>!<usr>@<host> Source string //<host> User string //<usr> Arguments []string }[/sourcecode] |
Welcomeメッセージ
1 2 3 4 5 6 7 |
[sourcecode lang="text"] ircobj.AddCallback("JOIN", func (e *irc.Event) { time.Sleep(100 * time.Millisecond) ircobj.Notice("#system_channel", fmt.Sprintf("こんにちは、%sさん\n", e.Nick)) if !strings.Contains(e.Nick, my_nick) { member[e.Nick] = e.Nick } })[/sourcecode] |
e *irc.Eventを使って、ニックネームを取得しています。
4-6行目は入室しているメンバーを保持しておくものです。
順番を決めるようなダイス機能
1 2 3 4 5 6 7 |
[sourcecode lang="text"] ircobj.AddCallback("PRIVMSG", func (e *irc.Event) { // ダイス if e.Message() == ":dice" { time.Sleep(100 * time.Millisecond) ircobj.Notice("#system_channel", fmt.Sprintf("%sさんの出目は、%dです\n", e.Nick, rand.Intn(100))) } }[/sourcecode] |
ものすごくシンプルです。
AddCallbackでPRIVMSGを受け取り、特定文字列”:dice”だった場合ランダムで0-99の数を返します。
プレゼン発表の順番やなにかの当番の順番など決めたりできます。
メンバーの中からランダムで一人選ぶ機能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[sourcecode lang="text"] // メンバー member := make(map[string]string) ircobj.AddCallback("PRIVMSG", func (e *irc.Event) { if e.Message() == ":decide" { dice := rand.Intn(len(member)) ii := 0 for _,v := range member { if (ii == dice) { ircobj.Notice("#system_channel", fmt.Sprintf("%sさんが選ばれました\n", v)) break } ii += 1 } } [/sourcecode] |
入室時に保持したメンバーのマップからランダムで1人選びます。
Go言語のマップはアクセスするたびに取り出す順番が変わりますが偏りがあるためここでもrandを使います。
こちらは、メンバーの中から1人決めたいとき、議事録当番なんかを決めたりできます。
MTG、提出物などのリマインダ機能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
[sourcecode lang="text"] // 毎週月曜 c := cron.New() c.AddFunc("0 50 16 * * MON", func() { ircobj.Notice("#system_channel", "---------------------------") ircobj.Notice("#system_channel", "- システムMTG 10分前 です -") ircobj.Notice("#system_channel", "---------------------------") }) // 毎月 c.AddFunc("0 5 11 1 * *", func() { ircobj.Notice("#system_channel", "------------------------") ircobj.Notice("#system_channel", "- 本日経費提出期限です -") ircobj.Notice("#system_channel", "------------------------") }) c.Start() [/sourcecode] |
cronライブラリで実行時刻を設定しNotice通知させます。
cronライブラリはとても良く出来ていて標準のcron表記も出来ますが
毎n時n分、毎月などは”@hourly”、”@every 1h30m”のような指定も出来ます。
出力結果
1人botと戯れる…。
終わりに
ただGo言語を使いたい!と練習がてら書いてみました。
業務では、ほぼ100%PHPなのですが時間を見つけてGo言語も使っていきたいです。
Goルーチンを使った並列処理を使ってなにか作りたいです。