2014-07-08 (火)
*[golang] golangでIRCボットを書くときのメモ
昨日のハッカソンで,go-irceventを使ってみたので,その時に試しに書いたやつを.
go getで必要なものをインストール.最近はgoコマンドがなんでもやってくれて便利.
go get github.com/thoj/go-ircevent go get code.google.com/p/go.text/encoding go get code.google.com/p/go.text/encoding/japanese
IRCだとまだISO-2022-JPを使うこともあると思うので,文字コードはgo.textで変換するのが良い.会社のIRCはUTF-8なので不要なのだけど.
ライブラリの依存関係の管理はgodepとかが主流なのかな.そのうち試そう.
IRCボットの簡単なサンプル.設定はjsonファイルに出しました.
package main import ( "os" "log" "strings" "encoding/json" "io/ioutil" // go get github.com/thoj/go-ircevent "github.com/thoj/go-ircevent" // go get code.google.com/p/go.text/encoding // go get code.google.com/p/go.text/encoding/japanese "code.google.com/p/go.text/encoding/japanese" "code.google.com/p/go.text/transform" ) var settings struct { Server string `json:"server"` UserName string `json:"user"` NickName string `json:"nick"` Channels []string `json:"channels"` JisEncode bool `json:"jis_encode"` } func main() { configFile, _ := os.Open("settings.json") jsonParser := json.NewDecoder(configFile) if err := jsonParser.Decode(&settings); err != nil { log.Println("failed: load config.", err.Error()) } configFile.Close() con := irc.IRC(settings.NickName, settings.UserName) err := con.Connect(settings.Server) if err != nil { log.Println("failed: connect irc") return } con.AddCallback("001", func (e *irc.Event) { for _, ch := range settings.Channels { con.Join(ch) } }) // auto join con.AddCallback("INVITE", func (e *irc.Event) { //log.Println("invited " + e.Arguments[0] + "," + e.Arguments[1]) con.Join(e.Arguments[1]) }) con.AddCallback("KICK", func (e *irc.Event) { if e.Arguments[1] == settings.NickName { log.Println("KICKED " + strings.Join(e.Arguments, " ")) } }) con.AddCallback("PRIVMSG", func (e *irc.Event) { log.Println("PRIVMSG " + strings.Join(e.Arguments, " ")) ch := e.Arguments[0] msgString := string(toUtf8(e.Message())) log.Println("MSG " + e.Nick + ":" + msgString) if strings.Contains(msgString, "oreo") { con.Notice(ch, fromUtf8("オレオ")) } }) log.Println("Start bot.") con.Loop() } func toUtf8(s string) string { if !settings.JisEncode { return s } if msg, err := ioutil.ReadAll( transform.NewReader(strings.NewReader(s), japanese.ISO2022JP.NewDecoder())); err == nil { return string(msg) } return "" } func fromUtf8(s string) string { if !settings.JisEncode { return s } if msg, err := ioutil.ReadAll( transform.NewReader(strings.NewReader(s), japanese.ISO2022JP.NewEncoder())); err == nil { return string(msg) } return "" }
"oreo"と書き込むと"オレオ"と返事をします.
なぜかWindows上で実行しているとCtrl+Cで止まらなかったりするので,IRCのコマンドで再実行できるようにしておくと良いかも.
作ったボットも業務に関係ないやつなら公開しても問題ないとのことなので,GitHubに置く.