package main import ( "container/ring" "flag" "fmt" "log" "strings" "time" tdr "dim13.org/theo" irc "github.com/fluffle/goirc/client" ) var ( server = flag.String("server", "irc.rusnet.org.ru:6660", "IRC Server") room = flag.String("room", "#lor", "IRC Channel") name = flag.String("name", "mincom", "Bots Name") ) type Commander interface { irc.Handler fmt.Stringer } type ( Last string News string BSD string Theo string Help string ) var ( commands = make(map[string]Commander) buffer = ring.New(10) ) func Register(cmd string, f Commander) { commands[cmd] = f } func (v Last) String() string { return string(v) } func (_ Last) Handle(conn *irc.Conn, line *irc.Line) { buffer.Do(func(v interface{}) { if v != nil { l := v.(*irc.Line) s := fmt.Sprintf("%v <%v> %v", l.Time.Format(time.Kitchen), l.Nick, l.Text()) conn.Privmsg(line.Nick, s) } }) } func (v Theo) String() string { return string(v) } func (_ Theo) Handle(conn *irc.Conn, line *irc.Line) { conn.Privmsg(line.Target(), tdr.Theo()) } func (v News) String() string { return string(v) } func (_ News) Handle(conn *irc.Conn, line *irc.Line) { n, err := FetchNews(lor) if err != nil { conn.Privmsg(line.Target(), err.Error()) return } if line.Public() { n = n[:3] } for _, s := range n { conn.Privmsg(line.Target(), s) } } func (v BSD) String() string { return string(v) } func (_ BSD) Handle(conn *irc.Conn, line *irc.Line) { n, err := FetchNews(undeadly) if err != nil { conn.Privmsg(line.Target(), err.Error()) return } if line.Public() { n = n[:3] } for _, s := range n { conn.Privmsg(line.Target(), s) } } func (v Help) String() string { return string(v) } func (_ Help) Handle(conn *irc.Conn, line *irc.Line) { for k, v := range commands { s := fmt.Sprintf("%4s: %v", k, v) conn.Privmsg(line.Target(), s) } } func privmsg(conn *irc.Conn, line *irc.Line) { log.Println(line) txt := line.Text() if line.Public() && line.Nick != conn.Me().Nick { buffer.Value = line buffer = buffer.Next() } // lookup command if f := strings.Fields(txt); len(f) > 0 { if c, ok := commands[f[0]]; ok { c.Handle(conn, line) } } // extract single link and fetch title if strings.Contains(txt, "http") { if i := strings.Index(txt, "http"); i >= 0 { txt = txt[i:] } if i := strings.IndexAny(txt, " ,"); i > 0 { txt = txt[:i] } if t, err := FetchTitle(txt); err == nil { conn.Privmsg(line.Target(), t) } } } func init() { flag.Parse() Register("last", Last("return last 10 messages")) Register("theo", Theo("Quote Theo De Raadt")) Register("news", News("Last LOR news (msg private to see all)")) Register("bsd", BSD("Last Undeadly news (msg private to see all)")) Register("help", Help("This help")) } func main() { c := irc.SimpleClient(*name) c.EnableStateTracking() quit := make(chan bool) c.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) { quit <- true }) c.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) { conn.Join(*room) }) c.HandleFunc(irc.PRIVMSG, privmsg) if err := c.ConnectTo(*server); err != nil { log.Fatal(err) } <-quit }