// PrivMsgCallback (PRIVMSG) is really any message in IRC that the bot sees func PrivMsgCallback(con *irc.Connection) { con.AddCallback("PRIVMSG", func(e *irc.Event) { message := e.Arguments[1] channel := e.Arguments[0] log.Printf("%s said: %s\n", e.Nick, message) // Look for urls in messages urls := urlRegex.FindAllString(message, -1) if len(urls) > 0 { for _, url := range urls { messageCh := make(chan string, 1) go scrapePage(url, messageCh) con.Privmsg(channel, <-messageCh) } } }) }
func main() { var ( irc *goirc.Connection err error ) var configFile = flag.String("c", "r2d2.cfg", "Load configuration from file") flag.Parse() _, err = os.Stat(*configFile) if err != nil { log.Fatal("%v", err) os.Exit(1) } err = gcfg.ReadFileInto(&cfg, *configFile) if err != nil { log.Fatal("Error in configuration file: %v", err) os.Exit(1) } irc = goirc.IRC(cfg.Irc.Nick, cfg.Irc.Nick) irc.UseTLS = cfg.Irc.TLS irc.VerboseCallbackHandler = cfg.Irc.Debug irc.Debug = cfg.Irc.Debug err = irc.Connect(cfg.Irc.Server) if err != nil { log.Fatal("Connection to IRC server failed: %v", err) os.Exit(1) } // block while performing authentication handleAuth(irc) // we are identified, let's continue if cfg.Irc.ChannelPass != "" { // if a channel pass is used, craft a join command // of the form "&<channel>; <key>" irc.Join(cfg.Irc.Channel + " " + cfg.Irc.ChannelPass) } else { irc.Join(cfg.Irc.Channel) } if cfg.Irc.Debug { irc.Privmsg(cfg.Irc.Channel, "beep beedibeep dibeep") } go watchGithub(irc) go watchUntappd(irc) go fetchPageTitles(irc) initMaxmind() // add callback that captures messages sent to bot terminate := make(chan bool) irc.AddCallback("PRIVMSG", func(e *goirc.Event) { re := regexp.MustCompile("^" + cfg.Irc.Nick + ":(.+)$") if re.MatchString(e.Message()) { parsed := re.FindStringSubmatch(e.Message()) if len(parsed) != 2 { return } req := strings.Trim(parsed[1], " ") resp := handleRequest(e.Nick, req, irc) if resp != "" { irc.Privmsgf(cfg.Irc.Channel, "%s: %s", e.Nick, resp) } } }) <-terminate irc.Loop() irc.Disconnect() }