goによるmecab wrapperの実装がある事をtokuhiromさんに教えてもらったので、さっそく使わせて頂いた。
package main
import (
"fmt";
"http";
"bytes";
"json";
"strings";
"io";
"mecab";
)
func get_json(url string, data map[string]string) json.Json {
q := "";
for key, val := range data {
if (len(q) > 0) { q += "&" }
q += fmt.Sprintf("%s=%s", key, http.URLEscape(val));
}
bb := &bytes.Buffer{};
bb.Write(strings.Bytes(q));
r, err := http.Post(url + "?" + q, "application/x-www-form-urlencoded", nil);
if err == nil {
b, _ := io.ReadAll(r.Body);
r.Body.Close();
j, _, _ := json.StringToJson(string(b));
return j
}
return nil
}
func get_sid(nick string) string {
j := get_json("http://webchat.freenode.net/e/n", map[string]string{"nick":nick});
return j.Elem(1).String();
}
func login(nick *string) string {
sid := get_sid(*nick);
for {
j := get_json("http://webchat.freenode.net/e/s", map[string]string{"s":sid});
if j == nil {
break;
}
for i := 0; i < j.Len(); i++ {
data := j.Elem(i);
println(data.String());
if (data.Elem(0).String() != "c") {
continue;
}
if (data.Elem(1).String() == "433") {
*nick += "_";
sid = get_sid(*nick);
}
if (data.Elem(1).String() == "376") {
return sid;
}
}
}
return "";
}
func join(sid string, room string) bool {
j := get_json("http://webchat.freenode.net/e/p", map[string]string{"s":sid, "c":"JOIN " + room});
if j == nil {
return false;
}
return true;
}
func say(sid string, room string, msg string) bool {
j := get_json("http://webchat.freenode.net/e/p", map[string]string{"s":sid, "c":"NOTICE " + room + " :" + msg});
if j == nil {
return false;
}
return true;
}
func listen(sid string, nick string, room string) {
for {
j := get_json("http://webchat.freenode.net/e/s", map[string]string{"s":sid});
if j == nil {
continue;
}
for i := 0; i < j.Len(); i++ {
data := j.Elem(i);
println(data.String());
if (data.Elem(0).String() != "c") {
continue;
}
if (data.Elem(1).String() != "PRIVMSG") {
continue;
}
line := data.Elem(3);
if (line.Elem(0).String() == nick) {
continue;
}
s := line.Elem(1).String();
m := mecab.New2("");
r := mecab.SparseToStr(m, s);
ss := strings.Split(r, "\n", 999);
for l := 0; l < len(ss); l++ {
st := strings.Split(ss[l], "\t", 2);
if (len(st) < 2) {
continue;
}
if (strings.Index(st[1], "固有名詞") != -1 ||
strings.Index(st[1], "人名") != -1 ||
strings.Index(st[1], "組織") != -1) {
say(sid, room, st[0] + "は良い奴だ。悪く言うな。俺が許さん。");
}
}
}
}
}
func main() {
nick := "go-japan";
room := "#mattn";
sid := login(&nick);
if (len(sid) > 0) {
if (join(sid, room)) {
listen(sid, nick, room);
}
}
}
channelに固有名詞や人名等が現れると「XXXは良い奴だ。悪く言うな。俺が許さん。」と発言します。mecabライブラリについては、やっぱりfeatureとかsurfaceを扱いたいのでこれからに期待したいと思います。まぁ、現状でも上記の様にstrings.Split使えば出来なくないんですけどね。
なんとなくだけど、だんだん「C++書きの為のGo言語」と言われてる理由が分かって来た気がする。