func Connect(ctx *cli.Context) { fmt.Printf("Connecting to %s...\n", RC.Host) // create new IRC connection cfg := irc.NewConfig(RC.Nick, "rusty") cfg.SSL = RC.SSL if cfg.SSL { cfg.SSLConfig = &tls.Config{ MinVersion: 0, MaxVersion: 0, InsecureSkipVerify: false, ServerName: RC.Host, CipherSuites: []uint16{ tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, tls.TLS_RSA_WITH_AES_256_CBC_SHA, }, } } cfg.Server = fmt.Sprintf("%s:%d", RC.Host, RC.Port) cfg.NewNick = func(n string) string { return n + "_" } c := irc.Client(cfg) c.EnableStateTracking() c.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) { fmt.Printf("Connected to %s\n", RC.Host) conn.Join(RC.Channel) }) // Set up a handler to notify of disconnect events. quit := make(chan bool) c.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) { quit <- true }) c.HandleFunc(irc.JOIN, func(conn *irc.Conn, line *irc.Line) { if line.Nick == conn.Config().Me.String() && line.Args[0] == RC.Channel { fmt.Printf("Joined channel %s\n", RC.Channel) } }) c.HandleFunc(irc.PRIVMSG, handle_privmsg) reallyquit := false for !reallyquit { // connect to server if err := c.ConnectTo(RC.Host); err != nil { fmt.Printf("Connection error: %s\n", err) return } // wait on quit channel <-quit } }
func New(pc config.Config) plug.Plug { st := &state.Nick{ Nick: pc.Identity.Nick[0], Ident: pc.Identity.RealName, Name: globals.Name(), } cf := &client.Config{ Server: pc.Connection.Addr, Pass: pc.Identity.Password, Me: st, NewNick: nextNick(pc.Identity.Nick), Version: globals.Version(), PingFreq: PING_FREQ, SplitLen: SPLIT_LEN, Timeout: TIMEOUT, Recover: logPanic, Flood: true, } cl := client.Client(cf) p := &IRCPlug{ config: pc, client: cl, endloop: make(chan bool), changes: make(chan plug.Change, CHANGE_CAPACITY), } cl.HandleFunc(client.CONNECTED, p.onConnected) cl.HandleFunc(client.DISCONNECTED, p.onDisconnected) cl.HandleFunc(client.PRIVMSG, p.onMessage) cl.HandleFunc(client.TOPIC, p.onTopic) return p }
func main() { config := loadConfig() irclog.SetLogger(LogrusAdapter{*log}) ircCfg := config.Network.GoIrcConfig() c := irc.Client(ircCfg) c.EnableStateTracking() module.InitModules(c, config) c.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) { for _, cmd := range config.Network.OnConnectCmds { conn.Raw(cmd) } for channel, _ := range config.Network.Channels { conn.Join(channel) } }) quit := make(chan bool) c.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) { quit <- true }) if err := c.ConnectTo(config.Network.Server); err != nil { panic(err) } // Wait for disconnect <-quit }
func main() { ircConf := irc.NewConfig("doctwitchbot") ircConf.Server = "irc.freenode.net:6667" bot := irc.Client(ircConf) bot.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) { fmt.Printf("Connected to IRC server\n") conn.Join("#mychannel") fmt.Printf("Joined channel.\n") }) bot.HandleFunc(irc.PRIVMSG, func(conn *irc.Conn, line *irc.Line) { fmt.Printf("%+v %+v\n", line.Nick, line.Args) }) // And a signal on disconnect quit := make(chan bool) bot.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) { fmt.Printf("%+v\n", conn) fmt.Printf("%+v\n", line) fmt.Printf("Disconnected.\n") quit <- true }) // Tell client to connect. if err := bot.Connect(); err != nil { fmt.Printf("Connection error: %s\n", err.Error()) } // Wait for disconnect <-quit }
func (i *irc) Start(server string, user string) { go func() { for { cfg := goirc.NewConfig(user) cfg.SSL = true cfg.Server = "irc.freenode.net:7000" cfg.NewNick = func(n string) string { return n + "^" } i.conn = goirc.Client(cfg) //i.conn = goirc.SimpleClient(user) //ircConn.SSL = true i.conn.HandleFunc("connected", func(conn *goirc.Conn, line *goirc.Line) { //conn.Join("#channel") i.connected = true }) quit := make(chan bool) i.conn.HandleFunc("disconnected", func(conn *goirc.Conn, line *goirc.Line) { i.connected = false quit <- true }) // Tell client to connect if err := i.conn.Connect(); err != nil { fmt.Printf("Connection error: %s\n", err) } i.SendMessage("willemvds", "STEVE!") // Wait for disconnect <-quit } }() }
// Connect connects the bot to its serve func (ib *IrcBot) Connect() { ib.connMu.Lock() defer ib.connMu.Unlock() //reconnect ib.reconnectAllowed = true settings := ib.dataService.LoadSettings() // create a config and fiddle with it first: cfg := irc.NewConfig(settings.Nick) cfg.Timeout = 10 * time.Second ib.conn = irc.Client(cfg) // Join channels ib.conn.HandleFunc("connected", func(conn *irc.Conn, line *irc.Line) { log.Printf("connected to " + ib.server.Name + ":" + strconv.Itoa(ib.server.Port)) ib.logToConsole("connected to " + ib.server.Name + ":" + strconv.Itoa(ib.server.Port)) for _, channel := range ib.server.Channels { ib.logToConsole("joining channel " + channel.Name) conn.Join(channel.Name) } }) // Parse Messages ib.conn.HandleFunc("PRIVMSG", ib.parseMessage) ib.conn.HandleFunc("372", ib.log372) ib.conn.HandleFunc("DISCONNECTED", ib.handleDisconnect) ib.conn.HandleFunc("CTCP", ib.handleDCC) ib.conn.HandleFunc(irc.NOTICE, ib.handleNotice) // Tell client to connect. ips, err := net.LookupIP(ib.server.Name) if err != nil { log.Printf("Lookup error: %v\n", err) ib.logToConsole("Lookup error: " + err.Error()) } for _, ip := range ips { server := ip.String() + ":" + strconv.Itoa(ib.server.Port) log.Printf("Connecting to '%v'", server) if err := ib.conn.ConnectTo(server); err != nil { log.Printf("Connection error: %v\n", err) ib.logToConsole("Connection error: " + err.Error()) } else { break } } }
func teddyBot(nick string, password string, config IRCNetworks) { cfg := irc.NewConfig(nick) cfg.SSL = config.Ssl cfg.SSLConfig = &tls.Config{ServerName: config.Host, InsecureSkipVerify: true} cfg.Server = config.Host cfg.NewNick = func(n string) string { return n + "^" } bot := irc.Client(cfg) bot.EnableStateTracking() bot.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) { conn.Mode(conn.Me().Nick, "+B") bot.Privmsg("NickServ", fmt.Sprintf("identify %s", password)) for key, channel := range config.Channels { fmt.Printf("Connecting to channel #%s\n", key) conn.Join(channel.Name + " " + channel.Key) } }) bot.HandleFunc(irc.PRIVMSG, func(conn *irc.Conn, line *irc.Line) { if strings.HasPrefix(line.Text(), "http") { bot.Privmsg(line.Args[0], getTitle(line.Text())) } else if strings.HasPrefix(line.Text(), "!dance") { for _, moves := range dance() { bot.Privmsg(line.Args[0], moves) } } else if strings.HasPrefix(line.Text(), "!angrydance") { for _, moves := range angrydance() { bot.Privmsg(line.Args[0], moves) } } }) quit := make(chan bool) bot.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) { quit <- true }) if err := bot.Connect(); err != nil { fmt.Printf("Connection error: %s\n", err.Error()) } // go func(line *irc.Line) { // fmt.Println(line) // } <-quit }
func main() { admhost := flag.String("admhost", "", "The operator hostname") flag.Parse() cfg := irc.NewConfig("ZeGoNoob", "tgn", "Ze Go Noob") cfg.SSL = true cfg.Server = "irc.freenode.net:7000" cfg.NewNick = func(n string) string { return n + "^" } c := irc.Client(cfg) // c.HandleFunc("connected", // func(conn *irc.Conn, line *irc.Line) { conn.Join("#") }) quit := make(chan bool) c.HandleFunc("connected", func(conn *irc.Conn, line *irc.Line) { log.Println("Connected to server!") }) c.HandleFunc("disconnected", func(conn *irc.Conn, line *irc.Line) { quit <- true }) c.HandleFunc(irc.PRIVMSG, func(conn *irc.Conn, line *irc.Line) { words := strings.Split(line.Args[1], " ") if line.Host == *admhost { if line.Args[1] == "quit" { quit <- true } } if words[0] == "reverse" { text := Reverse(strings.Join(words[1:], " ")) conn.Privmsg(line.Nick, text) } log.Printf("%s!%s@%s: %s", line.Nick, line.Ident, line.Host, strings.Join(line.Args[1:], " ")) }) // Tell client to connect. if err := c.Connect(); err != nil { log.Printf("Connection error: %s\n", err.Error()) } // Wait for disconnect <-quit log.Println("Bye!") }
func IRCConnection(host, channel, nick string) { IRCConnQuit := make(chan bool) run := true cfg := irc.NewConfig(nick, nick) cfg.Server = host cfg.NewNick = func(n string) string { return n + "~" } cli := irc.Client(cfg) cli.EnableStateTracking() cli.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) { fmt.Printf("[*] Connect Done\n") IRCConnQuit <- true run = false }) cli.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) { fmt.Printf("[*] Joining %s\n", channel) cli.Join(channel) }) cli.HandleFunc(irc.PRIVMSG, func(conn *irc.Conn, line *irc.Line) { if line.Text()[0:1] == "^" { ParseCommand(conn, line.Nick, line.Text()) } }) cli.HandleFunc(irc.JOIN, func(conn *irc.Conn, line *irc.Line) { if val, ok := messages[line.Nick]; ok { message <- line.Nick + ", " + val delete(messages, line.Nick) } }) fmt.Printf("[*] Connecting to %s\n", host) if err := cli.Connect(); err != nil { fmt.Printf("[*] Connection error: %s\n", err.Error()) } // Run Worker for run { cli.Privmsg(channel, <-message) } <-IRCConnQuit }
func newEndpointIRC(options *json.RawMessage) *EndpointIRC { e := &EndpointIRC{} json.Unmarshal(*options, &e.Config) c := irc.NewConfig(e.Config.Nick) c.Server = e.Config.Server e.conn = irc.Client(c) e.conn.EnableStateTracking() e.conn.HandleFunc(irc.CONNECTED, e.connect) e.conn.HandleFunc(irc.PRIVMSG, e.message) e.conn.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) { time.AfterFunc(time.Second*30, func() { e.conn.Connect() }) }) return e }
func New(server *Server) *ircClient.Conn { // irccon := irc.IRC(server.Nick, server.User) // irccon.VerboseCallbackHandler = false // irccon.Debug = false // //Set options // // ircobj.UseTLS = false //default is false // //ircobj.TLSOptions //set ssl options // // ircobj.Password = "" // server.Client = irccon // return irccon // other client cfg := ircClient.NewConfig(server.Nick, server.User, server.Version) cfg.SSL = server.SSL if len(server.Password) > 0 { cfg.Pass = server.Password } cfg.SSLConfig = &tls.Config{ ServerName: server.Address, InsecureSkipVerify: server.InsecureSkipVerify, } cfg.Server = fmt.Sprintf("%s:%s", server.Address, server.Port) cfg.NewNick = func(n string) string { return n + "^" } cfg.Version = server.Version cfg.QuitMessage = server.Version cfg.SplitLen = 2000 c := ircClient.Client(cfg) // this will cause a lot of connection issues // c.EnableStateTracking() server.Client = c return c }
// Create a new ModManager from a ServerInfo config func NewManager(serverInfo *ServerInfo) (*ModManager, error) { ircCfg, err := serverInfo.configServer() if err != nil { return nil, err } con := irc.Client(ircCfg) // copy Chans and Accesss to allow serverInfo to be marked for GC chans := make([]string, len(serverInfo.Channels)) copy(chans, serverInfo.Channels) access := access{ list: make(map[string][]string, len(serverInfo.Access)), } for name, list := range serverInfo.Access { users := list.Users l := make([]string, len(users)) copy(l, users) access.list[name] = l } m := &ModManager{ core: newCore(), modules: make([]*module.Module, 0, 5), cons: console.New(os.Stdin), Conn: con, Config: &BotInfo{ Chans: chans, Access: access, }, Quit: make(chan bool), } m.registerCoreCommands() m.registerCommands() return m, nil }
func main() { if len(os.Args) != 3 { fmt.Printf("Usage: %s server:port nick\n", os.Args[0]) os.Exit(1) } cfg := irc.NewConfig(os.Args[2]) cfg.SSL = false cfg.Server = os.Args[1] cfg.NewNick = func(n string) string { return n + "_" } con := irc.Client(cfg) con.HandleFunc("connected", func(con *irc.Conn, line *irc.Line) { fmt.Println("Connected!") }) // read commands from stdin in := make(chan string, 4) go ReadCmd(in) // do something about the stuff go ui(con, in) // make channel seeing the signal to quit quit := make(chan bool) con.HandleFunc("disconnected", func(conn *irc.Conn, line *irc.Line) { quit <- true }) con.HandleFunc("PRIVMSG", func(conn *irc.Conn, line *irc.Line) { fmt.Printf("<%s> %s\n%s: ", line.Nick, line.Args[1], line.Args[0]) }) if err := con.Connect(); err != nil { fmt.Printf("Connection error: %s\n", err) } <-quit }
func NewIRCGateway(cfg config.IRCGateway, botname string) *IRCGateway { //irc irccfg := irc.NewConfig(botname, botname, "Powered by botyard") if cfg.UseSSL == true { irccfg.SSL = true irccfg.SSLConfig = &tls.Config{ InsecureSkipVerify: true, } } irccfg.Server = cfg.Server irccfg.NewNick = func(n string) string { return n + "^" } //TODO: c := irc.Client(irccfg) gw := &IRCGateway{ id: uuid.NewV4().String(), cfg: cfg, ircConn: c, logger: kitlog.NewContext(log.Logger).With("m", "Gateway-IRC"), } return gw }
func main() { quit := make(chan bool, 1) var config Config if err := gcfg.ReadFileInto(&config, "config.gcfg"); err != nil { log.Fatal("Couldn't read configuration") } ircConf := irc.NewConfig(config.IRC.Nickname) ircConf.Server = config.IRC.Host bot := irc.Client(ircConf) bot.HandleFunc("connected", func(conn *irc.Conn, line *irc.Line) { log.Println("Connected to IRC server", config.IRC.Host) conn.Join(config.IRC.Channel) }) bot.HandleFunc("privmsg", func(conn *irc.Conn, line *irc.Line) { log.Println("Received:", line.Nick, line.Text()) if strings.HasPrefix(line.Text(), config.IRC.Nickname) { command := strings.Split(line.Text(), " ")[1] switch command { case "quit": log.Println("Received command to quit") quit <- true } } }) log.Println("Connecting to IRC server", config.IRC.Host) if err := bot.Connect(); err != nil { log.Fatal("IRC connection failed:", err) } <-quit }
func (sys *IrcSubSystem) Run(channelIn, channelOut chan msgsystem.Message) { if len(sys.irchost) == 0 { return } // channel signaling irc connection status sys.ConnectedState = make(chan bool) // setup IRC client: cfg := irc.NewConfig(sys.ircnick, "ircflu", "ircflu") cfg.SSL = sys.ircssl cfg.Server = sys.irchost cfg.Pass = sys.ircpassword cfg.NewNick = func(n string) string { return n + "_" } sys.client = irc.Client(cfg) sys.client.HandleFunc("connected", func(conn *irc.Conn, line *irc.Line) { sys.ConnectedState <- true }) sys.client.HandleFunc("disconnected", func(conn *irc.Conn, line *irc.Line) { sys.ConnectedState <- false }) sys.client.HandleFunc("PRIVMSG", func(conn *irc.Conn, line *irc.Line) { channel := line.Args[0] text := "" if len(line.Args) > 1 { text = line.Args[1] } if channel == sys.client.Config().Me.Nick { log.Println("PM from " + line.Src) channel = line.Src // replies go via PM too. } else { log.Println("Message in channel " + line.Args[0] + " from " + line.Src) } msg := msgsystem.Message{ To: []string{channel}, Msg: text, Source: line.Src, Authed: auth.IsAuthed(line.Src), } channelIn <- msg }) // loop on IRC dis/connected events go func() { for { log.Println("Connecting to IRC:", sys.irchost) err := sys.client.Connect() if err != nil { log.Println("Failed to connect to IRC:", sys.irchost) log.Println(err) continue } for { status := <-sys.ConnectedState if status { log.Println("Connected to IRC:", sys.irchost) if len(sys.channels) == 0 { // join default channel sys.Join(sys.ircchannel) } else { // we must have been disconnected, rejoin channels sys.Rejoin() } } else { log.Println("Disconnected from IRC:", sys.irchost) break } } time.Sleep(5 * time.Second) } }() }
func main() { flag.Parse() // parses the logging flags. TODO logging.SetLogger(ircLogger{log.New(os.Stdout, "[irc]", log.LstdFlags)}) cfg := irc.NewConfig(frankconf.BotNick, frankconf.BotNick, "Frank Böterrich der Zweite") cfg.SSL = true cfg.SSLConfig = &tls.Config{InsecureSkipVerify: true} cfg.Flood = true cfg.Server = frankconf.IrcServer cfg.NewNick = func(n string) string { return n + "_" } c := irc.Client(cfg) c.EnableStateTracking() // connect c.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) { log.Printf("Connected as: %s\n", conn.Me().Nick) conn.Privmsg("nickserv", "identify "+frankconf.NickServPass) var instaJoin string if frankconf.Production { instaJoin = frankconf.InstaJoinProduction } else { instaJoin = frankconf.InstaJoinTesting } log.Printf("AutoJoining: %s\n", instaJoin) for _, cn := range strings.Split(instaJoin, " ") { if cn != "" { conn.Join(cn) } } // handle RSS frank.Rss(conn) // watch topics and maybe change them on midnight go frank.TopicChanger(conn) }) // react c.HandleFunc("PRIVMSG", func(conn *irc.Conn, line *irc.Line) { // ignore eicar, the bot we love to hate. // Also ignore i3-bot. if line.Nick == "eicar" || line.Nick == "i3" { return } go frank.RaumBang(conn, line) go frank.UriFind(conn, line) go frank.Lmgtfy(conn, line) go frank.Karma(conn, line) go frank.Help(conn, line) go frank.ItsAlive(conn, line) go frank.Highlight(conn, line) }) if frankconf.Verbose { c.HandleFunc("NOTICE", func(conn *irc.Conn, line *irc.Line) { tgt := line.Args[0] msg := line.Args[1] log.Printf("Debug NOTICE: tgt: %s, msg: %s\n", tgt, msg) }) } c.HandleFunc("INVITE", func(conn *irc.Conn, line *irc.Line) { tgt := line.Args[0] cnnl := line.Args[1] // auto follow invites only in test mode or if asked by master if frankconf.Production && line.Nick != frankconf.Master { log.Printf("only following invites by %s in production\n", frankconf.Master) return } if conn.Me().Nick != tgt { log.Printf("WTF: received invite for %s but target was %s\n", conn.Me().Nick, tgt) return } log.Printf("Following invite for channel: %s\n", cnnl) conn.Join(cnnl) }) // auto deop frank c.HandleFunc("MODE", func(conn *irc.Conn, line *irc.Line) { log.Printf("Mode change array length: %s", len(line.Args)) log.Printf("Mode changes: %s", line.Args) if len(line.Args) < 3 { // mode statement cannot be not in a channel, so ignore return } var modeop bool // true => add mode, false => remove mode var nickIndex int = 2 for i := 0; i < len(line.Args[1]); i++ { switch m := line.Args[1][i]; m { case '+': modeop = true case '-': modeop = false case 'o': if !modeop || line.Args[nickIndex] != conn.Me().Nick { nickIndex += 1 break } channel := line.Args[0] if strings.Contains(" "+frankconf.OpOkIn+" ", " "+channel+" ") { if strings.ToLower(line.Nick) != "chanserv" { conn.Privmsg(channel, "Unbelievable "+line.Nick+", you… https://yrden.de/f1.ogg") } } else { conn.Mode(channel, "+v-o", conn.Me().Nick, conn.Me().Nick) conn.Privmsg(channel, line.Nick+": SKYNET® Protection activated") } return default: nickIndex += 1 } } }) // disconnect quit := make(chan bool) c.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) { quit <- true }) // go go GO! if err := c.Connect(); err != nil { log.Fatalf("Connection error: %s\n", err) } log.Printf("Frank has booted\n") // Wait for disconnect <-quit }
func main() { fmt.Println("Allbotv2 loading...") // TODO persistent settings /*r, err := ioutil.ReadFile("settings.json") if err != nil { panic(err) } setting := IRCSetting{}*/ // Do our connection settings cfg := irc.NewConfig(botName) cfg.SSL = false cfg.Server = ircServer cfg.NewNick = func(n string) string { return n + "^" } c := irc.Client(cfg) // Begin handlers c.HandleFunc("connected", func(conn *irc.Conn, line *irc.Line) { fmt.Printf("Connected to %s...\n", cfg.Server) if autoJoin { if len(channels) > 0 { for index, channel := range channels { fmt.Printf("Joining [%s] [%d/%d]\n", channel, index, len(channels)-1) conn.Join(channel) } } } else { fmt.Println("What's next?") } }) c.HandleFunc("join", func(conn *irc.Conn, line *irc.Line) { if doOnJoin { //TODO send greeting eventJoin(conn, line) } }) c.HandleFunc("privmsg", func(conn *irc.Conn, line *irc.Line) { fmt.Printf("[%s] %s : %s\n", line.Cmd, line.Nick, line.Args) // determine if channel message or addressing bot if line.Args[0] != botName { //fmt.Println("^---- Channel message -----^") if muzzle == false { eventPrivmsg(conn, line, true) } } else { //fmt.Println("^---- Priavte message -----^") eventPrivmsg(conn, line, false) } }) c.HandleFunc("ctcp", func(conn *irc.Conn, line *irc.Line) { fmt.Printf("[%s] %s : %s\n", line.Cmd, line.Nick, line.Args) if debug { fmt.Printf("Line args: [%s]\n", line.Args[0]) } if line.Args[0] == "VERSION" { fmt.Printf("CTCP Reply sent to: [%s]\n", line.Nick) conn.CtcpReply(line.Nick, "VERSION", "allbot") } }) // And a signal on disconnect quit := make(chan bool) c.HandleFunc("disconnected", func(conn *irc.Conn, line *irc.Line) { // TODO reconnect upon disconnect signal quit <- true }) // Tell client to connect. if err := c.Connect(); err != nil { fmt.Printf("Connection error: %s\n", err) } // Wait for disconnect <-quit }
// Create func (s *Server) Create() { verbf("Creating bot from server struct: %s", s) // Create connection s.Conn = irc.Client(&irc.Config{ Me: &state.Nick{ Nick: s.Nick, Ident: s.Host, Host: s.Host, Name: s.RealName, }, Server: s.Network, Pass: s.Password, SSL: s.Ssl, PingFreq: 30 * time.Second, NewNick: func(s string) string { return s + "_" }, Version: "Kittens IRC", QuitMessage: "bye!", SplitLen: 450, Recover: (*irc.Conn).LogPanic, }) // Enable state tracking s.Conn.EnableStateTracking() // Add connect handler s.Conn.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) { s.Timestamp = time.Now().Unix() s.Connected = true infof("Connected to %s", s.Network) s.JoinChannels() }) // Add disconnect handler s.Conn.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) { s.Connected = false infof("Disconnected from %s", s.Network) infof("Reconnecting to %s", s.Network) s.Connect() }) // Listen for messages s.Conn.HandleFunc(irc.PRIVMSG, func(conn *irc.Conn, line *irc.Line) { // Show output of line currently s.Logging(line) }) // Listen for JOIN s.Conn.HandleFunc(irc.JOIN, func(conn *irc.Conn, line *irc.Line) { // Create new irc user if it doesn't exist db.Table("irc_users").Where("nickname = ? and host = ?", line.Nick, line.Host).Attrs(IrcUser{ Nickname: line.Nick, Host: line.Host, ServerId: s.Id, }).FirstOrCreate(&IrcUser{}) // Get irc user var ircuser IrcUser db.Table("irc_users").Where("nickname = ? and host = ?", line.Nick, line.Host).First(&ircuser) // Create new channel related to irc user if it doesn't exist db.Table("irc_user_channels").Where("channel = ? and irc_user_id = ?", line.Args[0], ircuser.Id).Attrs(IrcUserChannel{ Channel: line.Args[0], IrcUserId: ircuser.Id, Modes: "", LastJoinedAt: time.Now(), LastPartedAt: time.Now(), }).FirstOrCreate(&IrcUserChannel{}) // Get the irc user channel var iuc IrcUserChannel db.Table("irc_user_channels").Where("channel = ? and irc_user_id = ?", line.Args[0], ircuser.Id).First(&iuc) // Set the LastJoinedAt time iuc.LastJoinedAt = time.Now() db.Save(&iuc) }) verbf("Finished creating bot for server %s", s.ServerName) // Connect server if enabled if s.Enabled { s.Connect() } }
func main() { flag.Parse() log := logging.NewFromFlags() reg := event.NewRegistry() if *server == "" { //Don't call log.Fatal as we don't want a backtrace in this case log.Error("--server option required. \nOptions are:\n") flag.PrintDefaults() os.Exit(1) } // Connect to mongo db, err := db.Connect("localhost") if err != nil { log.Fatal("mongo dial failed: %v\n", err) } defer db.Session.Close() // Initialise the factoid driver (which currently acts as a plugin mgr too). fd := factdriver.FactoidDriver(db, log) // Configure IRC client irc := client.Client(*nick, "boing", "not really sp0rkle", reg, log) irc.SSL = *ssl // Initialise bot state bot := bot.Bot(irc, fd, log) bot.AddChannels(strings.Split(*channels, ",")) // Add drivers bot.AddDriver(bot) bot.AddDriver(fd) bot.AddDriver(calcdriver.CalcDriver(log)) bot.AddDriver(decisiondriver.DecisionDriver(log)) bot.AddDriver(quotedriver.QuoteDriver(db, log)) bot.AddDriver(netdriver.NetDriver(log)) bot.AddDriver(seendriver.SeenDriver(db, log)) bot.AddDriver(urldriver.UrlDriver(db, log)) // Register everything (including http handlers) bot.RegisterAll() // Start up the HTTP server go http.ListenAndServe(*httpPort, nil) // Connect loop. quit := false for !quit { if err := irc.Connect(*server); err != nil { log.Fatal("Connection error: %s", err) } quit = <-bot.Quit } if bot.ReExec() { // Calling syscall.Exec probably means deferred functions won't get // called, so disconnect from mongodb first for politeness' sake. db.Session.Close() // If sp0rkle was run from PATH, we need to do that lookup manually. fq, _ := exec.LookPath(os.Args[0]) log.Warn("Re-executing sp0rkle with args '%v'.", os.Args) err := syscall.Exec(fq, os.Args, os.Environ()) if err != nil { // hmmmmmm log.Fatal("Couldn't re-exec sp0rkle: %v", err) } } }
func (mod *IrcBee) Run(eventChan chan bees.Event) { if len(mod.server) == 0 { return } // channel signaling IRC connection status mod.connectedState = make(chan bool) // setup IRC client: cfg := irc.NewConfig(mod.nick, "beehive", "beehive") cfg.SSL = mod.ssl cfg.Server = mod.server cfg.Pass = mod.password cfg.NewNick = func(n string) string { return n + "_" } mod.client = irc.Client(cfg) mod.client.HandleFunc("connected", func(conn *irc.Conn, line *irc.Line) { mod.connectedState <- true }) mod.client.HandleFunc("disconnected", func(conn *irc.Conn, line *irc.Line) { mod.connectedState <- false }) mod.client.HandleFunc("PRIVMSG", func(conn *irc.Conn, line *irc.Line) { channel := line.Args[0] if channel == mod.client.Config().Me.Nick { channel = line.Src // replies go via PM too. } msg := "" if len(line.Args) > 1 { msg = line.Args[1] } user := line.Src[:strings.Index(line.Src, "!")] hostmask := line.Src[strings.Index(line.Src, "!")+2:] ev := bees.Event{ Bee: mod.Name(), Name: "message", Options: []bees.Placeholder{ bees.Placeholder{ Name: "channel", Type: "string", Value: channel, }, bees.Placeholder{ Name: "user", Type: "string", Value: user, }, bees.Placeholder{ Name: "hostmask", Type: "string", Value: hostmask, }, bees.Placeholder{ Name: "text", Type: "string", Value: msg, }, }, } eventChan <- ev }) // loop on IRC dis/connected events for { log.Println("Connecting to IRC:", mod.server) err := mod.client.Connect() if err != nil { log.Println("Failed to connect to IRC:", mod.server) log.Println(err) } else { disconnected := false for { if disconnected { break } select { case <-mod.SigChan: mod.client.Quit() return case status := <-mod.connectedState: if status { log.Println("Connected to IRC:", mod.server) mod.Rejoin() } else { log.Println("Disconnected from IRC:", mod.server) disconnected = true break } default: time.Sleep(1 * time.Second) } } } } }
func NewBridge(slackToken, slackChannel, ircServer, ircChannel, ircNick string, ircSSL, insecureSkipVerify bool) (bridge *Bridge) { sc := slack.NewSlackClient(slackToken) ircCfg := ircc.NewConfig(ircNick) ircCfg.Server = ircServer ircCfg.NewNick = func(n string) string { return n + "_" } if ircSSL { ircCfg.SSL = true if insecureSkipVerify { ircCfg.SSLConfig = &tls.Config{InsecureSkipVerify: true} } } c := ircc.Client(ircCfg) bridge = &Bridge{SlackChan: slackChannel, IRCChan: ircChannel, slack: sc, irc: c} // IRC Handlers c.HandleFunc(ircc.CONNECTED, func(conn *ircc.Conn, line *ircc.Line) { conn.Join(ircChannel) bridge.slack.Send(bridge.SlackChan, "Connected to IRC.") log.Println("Connected to IRC.") }) c.HandleFunc(ircc.DISCONNECTED, func(conn *ircc.Conn, line *ircc.Line) { bridge.slack.Send(bridge.SlackChan, "Disconnected from IRC. Issuing reconnect...") log.Println("Disconnected from IRC. Issuing reconnect...") for { if err := conn.Connect(); err != nil { log.Println("IRC reconnect failed: ", err) log.Println("Trying again in 30 seconds...") time.Sleep(30 * time.Second) continue } // success break } }) c.HandleFunc(ircc.PRIVMSG, func(conn *ircc.Conn, line *ircc.Line) { if line.Target() == bridge.IRCChan { msg := fmt.Sprintf("[%s]: %s", line.Nick, line.Text()) bridge.slack.Send(bridge.SlackChan, msg) } }) // Slack Handlers sc.HandleFunc("shutdown", func(sc *slack.SlackClient, e *slack.Event) { bridge.irc.Privmsg(bridge.IRCChan, "Disconnected from Slack.") log.Println("Disconnected from Slack.") }) sc.HandleFunc("disconnected", func(sc *slack.SlackClient, e *slack.Event) { bridge.irc.Privmsg(bridge.IRCChan, "Issuing reconnect to Slack...") log.Println("Issuing reconnect to Slack...") sc.Connect() }) sc.HandleFunc("connected", func(sc *slack.SlackClient, e *slack.Event) { bridge.irc.Privmsg(bridge.IRCChan, "Connected to Slack.") log.Println("Connected to Slack.") }) sc.HandleFunc("message", func(sc *slack.SlackClient, e *slack.Event) { if e.Chan() == bridge.SlackChan && !sc.IsSelfMsg(e) && e.Text != "" { msg := fmt.Sprintf("[%s]: %s", e.Usernick(), e.Msg()) // IRC has problems with newlines, therefore we split the message for _, line := range strings.SplitAfter(msg, "\n") { // we do not want to send empty lines... if strings.TrimSpace(line) != "" { bridge.irc.Privmsg(bridge.IRCChan, line) } } } }) go func() { if err := c.Connect(); err != nil { log.Fatal("Could not connect to IRC: ", err) } }() go func() { if err := sc.Connect(); err != nil { log.Fatal("Could not connect to Slack: ", err) } }() return bridge }
func main() { zax = ZAX{} zax_log, _ := os.OpenFile("zax.log", os.O_CREATE|os.O_APPEND, os.ModeAppend) irc_logging.SetLogger(IrcLogger{}) log_file := logging.NewLogBackend(zax_log, "", 0) log_file_f := logging.NewBackendFormatter(log_file, format) log_stdout := logging.NewLogBackend(os.Stdout, "", 0) log_stdout_f := logging.NewBackendFormatter(log_stdout, format) log_stdout_levelled := logging.AddModuleLevel(log_stdout_f) log_stdout_levelled.SetLevel(logging.INFO, "") logging.SetBackend(log_stdout_levelled, log_file_f) last_url = "" m := []Message{} e := []Event{} u := []Url{} history = IrcHistory{} history.data = HistoryData{m, e, u} history.userdata = make(map[string]*HistoryData) log.Notice("Loading config...") file, _ := os.Open("conf.json") decoder := json.NewDecoder(file) config = Config{} err := decoder.Decode(&config) if err != nil { log.Errorf("Error loading config: %s", err.Error()) os.Exit(-1) } log.Notice("Config loaded.") log.Notice("Opening history...") time_history := time.Now() file_history, err = os.OpenFile("history.log", os.O_CREATE, os.ModeAppend) if err != nil { log.Errorf("Unable to open history.log: %s", err.Error()) os.Exit(-1) } log.Notice("Loading history...") reader := bufio.NewScanner(file_history) file_history_writer = bufio.NewWriter(file_history) for reader.Scan() { l := reader.Text() is_url := strings.HasPrefix(l, "url") is_msg := strings.HasPrefix(l, "msg") is_event := strings.HasPrefix(l, "event") parts := []string{} user := "" channel := "" timestamp := time.Time{} if is_url || is_msg || is_event { parts = strings.Split(l, ",") ts, _ := strconv.ParseInt(parts[1], 10, 64) timestamp = time.Unix(ts, 0) user = parts[2] channel = parts[3] if !history.IsUserInit(user) { history.InitUser(user) } } if strings.HasPrefix(l, "event") { evt_s := parts[4] data := "" if len(parts) == 6 { data = parts[5] } event := Event{evt_s, user, data, channel, timestamp} history.userdata[user].Events = append(history.userdata[user].Events, event) history.data.Events = append(history.data.Events, event) } if strings.HasPrefix(l, "msg") { text := "" for i := 4; i < len(parts); i++ { text = text + parts[i] } msg := Message{text, user, channel, timestamp} history.userdata[user].Messages = append(history.userdata[user].Messages, msg) history.data.Messages = append(history.data.Messages, msg) } if strings.HasPrefix(l, "url") { url := Url{parts[3], timestamp} history.userdata[user].Urls = append(history.userdata[user].Urls, url) history.data.Urls = append(history.data.Urls, url) } } elapsed := time.Since(time_history) log.Noticef("History loaded %d events, %d urls and %d messages in %f seconds.\n", len(history.data.Events), len(history.data.Urls), len(history.data.Messages), elapsed.Seconds()) log.Notice("Initializing IRC connection.") // Init IRC connection log.Noticef("Creating IRC cfg. Server: %s, Use SSL: %t, Nickname %s", config.Server, config.SSL, config.Nickname) cfg := irc.NewConfig(config.Nickname) cfg.SSL = config.SSL cfg.SSLConfig = &tls.Config{} cfg.SSLConfig.InsecureSkipVerify = config.SSLIgnoreInsecure cfg.Me.Ident = "ZAX" cfg.Me.Name = "ZAX" cfg.Version = "ZAX" cfg.Server = config.Server cfg.NewNick = func(n string) string { return n + "^" } quit := make(chan bool) c := irc.Client(cfg) c.EnableStateTracking() c.Connect() zax.IrcClient = c zax.IrcConfig = cfg c.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) { for i := 0; i < len(config.Channels); i++ { ch := config.Channels[i] c.Join(ch.Chan, ch.Password) } }) c.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) { log.Notice("Disconnected") quit <- true }) c.HandleFunc(irc.JOIN, func(conn *irc.Conn, line *irc.Line) { log.Infof("[%s] %s (%s@%s) has joined.", line.Target(), line.Nick, line.Ident, line.Host) history.AddEvent(line.Nick, "join", "", line.Target()) }) c.HandleFunc(irc.QUIT, func(conn *irc.Conn, line *irc.Line) { log.Infof("[%s] %s (%s@%s) has quit.", line.Target(), line.Nick, line.Ident, line.Host) history.AddEvent(line.Nick, "quit", line.Text(), "") }) c.HandleFunc(irc.PING, func(conn *irc.Conn, line *irc.Line) { log.Debug("PING.") }) c.HandleFunc(irc.PRIVMSG, func(conn *irc.Conn, line *irc.Line) { sender_host := line.Host sender := line.Nick text := line.Text() channel := line.Target() target := line.Target() reply_to := line.Target() if line.Target() == config.Nickname { reply_to = sender } // Remove control characters text = strings.Replace(text, "", "", -1) text = strings.Replace(text, "", "", -1) log.Noticef("[%s] %s: %s", target, sender, text) history.AddMessage(sender, target, text) if len(config.ReportChan) > 0 { zax.Privmsg(config.ReportChan, fmt.Sprintf("[%s] %s: %s", target, sender, text)) } args := strings.Split(text, " ") cmd_admin := []string{"%%", "<<"} // Check if admin if is_command(text, cmd_admin) { re_adm := regexp.MustCompile("(nick|host):(.+)") criteria := re_adm.FindStringSubmatch(config.Admin) //is_admin := false match_str := "" if criteria == nil { log.Debug("Unable to parse admin criteria.") return } re_adm_eval := regexp.MustCompile(criteria[2]) if criteria[1] == "nick" { match_str = sender } if criteria[1] == "host" { match_str = sender_host } if !re_adm_eval.MatchString(match_str) { log.Debugf("Didn't pass the criteria: %s:%s", criteria[1], criteria[2]) return } log.Debugf("Passed the criteria: %s:%s with %s", criteria[1], criteria[2], match_str) if text == "<<" { zax.Quit(get_quit_msg()) } if strings.HasPrefix(text, "%%") { if len(args) == 4 { if args[1] == "opt" { if args[2] == "process_urls" { if args[3] == "on" { config.ProcessUrls = true } if args[3] == "off" { config.ProcessUrls = false } } } } } } cmd_rand := []string{".r", ".random"} cmd_steam := []string{".s", ".steam"} cmd_game := []string{".g", ".game"} cmd_url := []string{".u", ".url"} cmd_msg := []string{".m", ".msg"} cmd_seen := []string{"!"} cmd_help := []string{"?h"} if is_command(text, cmd_help) { reply_msg := "" if text == "?h" { reply_msg = "Cmds: [[.g(ame) .r(andom) .s(team) .u(rl) .m(sg) !]] -- Type ?h <cmd> for more info." } if len(args) > 1 { if args[1] == "!" { reply_msg = "Checks when user was last seen. Syntax: !<username>" } if is_command(args[1], cmd_rand) { reply_msg = "Generate random number. Syntax: .random <min> <max>" } if is_command(args[1], cmd_steam) { if len(args) == 3 { if args[2] == "symbols" { reply_msg = "MP=MultiPlayer, SP=SinglePlayer, CO=Co-op VAC=Valve Anti-Cheat, TC=Trading Card, Ach=Achievments, EA=Early Access, WS=Workshop support" } } else { reply_msg = "Search steam. For result symbols type '?h .s symbols' Syntax: .steam [ find | latest | random | trending | appid] <expression>" } } if is_command(args[1], cmd_game) { reply_msg = "Search for game info. Syntax: .game <query>" } if is_command(args[1], cmd_msg) { reply_msg = "Search message log. Syntax: .msg [ find | latest | random ] <expression>" } if is_command(args[1], cmd_url) { reply_msg = "Search URL log. Syntax: .url [ find | latest | random ] <expression>" } } zax.Privmsg(reply_to, reply_msg) return } if is_command(text, cmd_seen) { log.Debug("Executing seen command.") seen_user := strings.Replace(args[0], "!", "", -1) if seen_user == "" { log.Debug("No user was specified.") return } if seen_user == sender { log.Debug("Sender same as specified seen user, insult.") zax.Privmsg(reply_to, get_insult()) } state := c.StateTracker().GetNick(seen_user) if state != nil { user_channels := state.Channels for i := 0; i < len(config.Channels); i++ { ch := config.Channels[i] _, exists := user_channels[ch.Chan] if exists { if ch.Chan == channel { zax.Privmsg(reply_to, get_insult()) log.Notice("seen_user is here now.") } else { sender_state := c.StateTracker().GetNick(sender) _, exists := sender_state.Channels[ch.Chan] if exists { zax.Privmsg(reply_to, seen_user+" is on "+ch.Chan) } else { zax.Privmsg(reply_to, "Yeah, somewhere... can't tell you where though.") } } } } } time_seen := time.Time{} data, found := history.userdata[seen_user] if !found { zax.Privmsg(channel, get_user_not_exists()) return } log.Debug("Finding latest event/msg...") action := "" evt := Event{} msg := Message{} if data.Events != nil && len(data.Events) > 0 { evt = data.Events[len(data.Events)-1] } if data.Messages != nil && len(data.Messages) > 0 { msg = data.Messages[len(data.Messages)-1] } is_event := false if evt.Event != "" { time_seen = evt.Timestamp is_event = true } else if msg.Msg != "" { time_seen = msg.Timestamp is_event = false } else { if evt.Timestamp.Unix() > msg.Timestamp.Unix() { time_seen = evt.Timestamp is_event = true } else { time_seen = msg.Timestamp is_event = false } } if is_event { if evt.Event == "quit" { action = "quitting" } if evt.Event == "join" { action = "joining" } } else { action = "writing: \"" + msg.Msg + "\"" } log.Debugf("Found latest event %s at %d", action, time_seen.Unix()) duration := time.Since(time_seen) days := 0 hours := 0 sec := 0 min := 0 log.Debugf("User %s seen hours: %.1f, minutes: %.1f, seconds %.1f ago.", seen_user, duration.Hours(), duration.Minutes(), duration.Seconds()) if duration.Hours() > 24 { days = int(duration.Hours()) / 24 hours = int(duration.Hours()) % 24 min = 0 } else if duration.Minutes() > 60 { hours = int(duration.Hours()) min = int(duration.Minutes()) % 60 } else if duration.Seconds() > 60 { min = int(duration.Minutes()) sec = int(duration.Seconds()) % 60 } else { sec = int(duration.Seconds()) } if duration.Hours() > 24 { days = int(duration.Hours()) / 24 hours = int(duration.Hours()) % 24 min = 0 } times := []string{} if days > 0 { times = append(times, strconv.Itoa(days)+" day(s)") } if hours > 0 { times = append(times, strconv.Itoa(hours)+" hour(s)") } if min > 0 { times = append(times, strconv.Itoa(min)+" minute(s)") } if sec > 0 { times = append(times, strconv.Itoa(sec)+" second(s)") } time_str := strings.Join(times, ", ") zax.Privmsg(reply_to, fmt.Sprintf("%s was last seen %s ago %s.", seen_user, time_str, action)) } if is_command(text, cmd_game) { query := "" for i := 1; i < len(args); i++ { query += " " + args[i] } games, success := games.FindGames(query, config.UserAgent) if success { zax.Privmsg(reply_to, fmt.Sprintf("%s (%s) - %s\n", games[0].Name, games[0].Year, games[0].Url)) } } if is_command(text, cmd_url) { var url Url var urls []Url urls = history.data.Urls is_cmd_last := args[1] == "last" || args[1] == "l" is_cmd_random := args[1] == "random" || args[1] == "r" is_cmd_find := args[1] == "find" || args[1] == "f" if is_cmd_last || is_cmd_random && len(args) == 3 { user_urls := history.userdata[args[2]].Urls if user_urls != nil { urls = user_urls } } if is_cmd_last { url = urls[len(urls)-1] } if is_cmd_random { url = urls[rand_int(0, len(urls)-1)] } if is_cmd_find { expr := "" for i := 2; i < len(args); i++ { expr += expr + args[i] } re := regexp.MustCompile(expr) for _, i_url := range urls { match := re.FindStringSubmatch(i_url.Url) if match != nil { url = i_url } } } if url.Url == "" { return } t := url.Timestamp zax.Privmsg(reply_to, fmt.Sprintf("[%d-%02d-%02d %02d:%02d:%02d] %v", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), url.Url)) return } if is_command(text, cmd_msg) { var msg Message var msgs []Message msgs = history.data.Messages is_cmd_last := args[1] == "last" || args[1] == "l" is_cmd_random := args[1] == "random" || args[1] == "r" is_cmd_find := args[1] == "find" || args[1] == "f" if is_cmd_last || is_cmd_random && len(args) == 3 { user_msgs := history.userdata[args[2]].Messages if user_msgs != nil { msgs = user_msgs } } if is_cmd_last { msg = msgs[len(msgs)-1] } if is_cmd_random { msg = msgs[rand_int(0, len(msgs)-1)] } if is_cmd_find { expr := "" for i := 2; i < len(args); i++ { add := args[i] if i != 2 { add = " " + add } expr += add } re := regexp.MustCompile(expr) for _, i_msg := range msgs { match := re.FindStringSubmatch(i_msg.Msg) if match != nil { if !(strings.Contains(i_msg.Msg, fmt.Sprintf("%s %s", args[0], args[1]))) { msg = i_msg } } } } if msg.Msg == "" { return } t := msg.Timestamp zax.Privmsg(reply_to, fmt.Sprintf("[%d-%02d-%02d %02d:%02d:%02d] %v: %v", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), msg.User, msg.Msg)) } if is_command(text, cmd_rand) { if len(args) < 3 { return } min, err := strconv.ParseInt(args[1], 10, 32) if err != nil { log.Debug("Failed to parse min.") return } max, err := strconv.ParseInt(args[2], 10, 32) if err != nil { log.Debug("Failed to parse max.") return } if min > max { return } zax.Privmsg(reply_to, "What about... "+strconv.Itoa(rand_int(int(min), int(max)))) } if is_command(text, cmd_steam) { if len(args) < 2 { return } subcommand := args[1] success := false steam_appid := 0 var err error steam_latest_url := "http://store.steampowered.com/search/?sort_by=Released_DESC&tags=-1&category1=998&page=" if subcommand == "latest" || subcommand == "l" { steam_appid, success = steam.SearchSteampowered(steam_latest_url+"1", 0) } if subcommand == "random" || subcommand == "r" { page := strconv.Itoa(rand_int(1, 286)) steam_appid, success = steam.SearchSteampowered(steam_latest_url+page, -2) } if subcommand == "trending" || subcommand == "t" { apps, suc := steam.GetTrending(config.UserAgent) if suc { app := apps[0] zax.Privmsg(reply_to, fmt.Sprintf("[Steamcharts] %s [%s increase in players last 24h] %d current players. Type '.s a %d' to get more info.", app.Name, app.Increase, app.Players, app.Id)) return } } if subcommand == "appid" || subcommand == "a" { steam_appid, err = strconv.Atoi(args[2]) success = (err == nil) } if subcommand == "find" || subcommand == "f" { re := regexp.MustCompile(fmt.Sprintf("%s %s ([[:alnum:]'*!_ ]+)", args[0], args[1])) match := re.FindStringSubmatch(text) if match == nil || len(match) == 0 { log.Debug("Doesn't match.") return } log.Debugf("matched term: %s", match[1]) search_url := "http://store.steampowered.com/search/?snr=&term=" + match[1] log.Debugf("Search URL: %s", search_url) steam_appid, success = steam.SearchSteampowered(search_url, 0) } if success { log.Info("Found appid %d, retrieving info...", steam_appid) app, success2 := steam.GetAppInfo(steam_appid, config.UserAgent) if success2 { rating_str := "" if app.Reviews > 0 { rating_str = fmt.Sprintf("| %.1f%s rating (%d reviews)", app.Rating, "%", app.Reviews) } os_str := "" if app.OS("") != "" { os_str = fmt.Sprintf("%s - [%s]", app.OS("/"), app.Features("/")) } price := "" if app.PriceDiscount != "" { price = "| " + app.PriceDiscount } else { if app.Price != "" { price = "| " + app.Price } } base_str := "" if app.ReleaseYear != "" && app.Developer != "" { base_str = fmt.Sprintf("(%s by \"%s\")", app.ReleaseYear, app.Developer) } info := fmt.Sprintf("[http://steamspy.com/app/%d/] \"%s\" %s %s %s %s", app.Id, app.Name, base_str, os_str, rating_str, price) zax.Privmsg(reply_to, info) } else { log.Error("Failed to retrieve steamapp info.") } } else { log.Notice("Failed to retrieve appid from search.") } } // Handle URLs if !(sender == "Wipe" && (strings.Contains(text, "Steam") || strings.Contains(text, "YouTube"))) && config.ProcessUrls { log.Debug("Looking for URLs...") urls := xurls.Relaxed.FindAllString(text, -1) for i := 0; i < len(urls); i++ { url := urls[i] log.Debugf("Found reddit url: %s", url) history.AddUrl(sender, url) if url == last_url { log.Debugf("Matches same url (%s) as last time, ignore.", last_url) continue } reddit, success := reddit.Search(url) if success { zax.Privmsg(reply_to, reddit) } else { log.Debug("Failed to retrieve reddit URL for the link.") } last_url = url } } time.Sleep(10 * time.Millisecond) }) <-quit log.Notice("Closing history.log") file_history.Close() time.Sleep(1000 * time.Millisecond) }
func main() { flag.Parse() if *apiKey == "" { log.Fatalln("Missing API key, provide one using -api-key") } lfm = lastfm.New(*apiKey) loadNickMap() loadCache() if *cacheFile != "" { cacheTimer = time.NewTimer(120 * time.Second) go func() { for _ = range cacheTimer.C { saveCacheNow() cacheTimer.Reset(120 * time.Second) } }() } if *server == "" { log.Fatalln("No server to connect to") } if *channelList == "" { log.Fatalln("No channels to join") } config := client.NewConfig(*botNick) config.Version = "github.com/Kovensky/go-lastfm-bot" config.SSL = *useSSL config.Flood = false // TODO: CA management? config.SSLConfig = &tls.Config{InsecureSkipVerify: true} irc := client.Client(config) addNickHandlers(irc) addWhoHandlers(irc) irc.HandleFunc(client.CONNECTED, func(irc *client.Conn, line *client.Line) { if *nickPass != "" { if irc.Me().Nick != *botNick { log.Println("Nick", *botNick, "was not available; trying to retake it") irc.Privmsg("NickServ", fmt.Sprintf("GHOST %s %s", *botNick, *nickPass)) } else { log.Println("Identifying with NickServ") irc.Privmsg("NickServ", fmt.Sprintf("IDENTIFY %s", *nickPass)) } } log.Println("Connected; joining", *channelList) irc.Join(*channelList) }) irc.HandleFunc("NOTICE", func(irc *client.Conn, line *client.Line) { if strings.ToLower(line.Nick) == "nickserv" { log.Println("NickServ:", line.Args[1]) switch { case strings.Contains(strings.ToLower(line.Args[1]), "ghost"): log.Println("Ghost command successful") log.Println("Changing nick to", *botNick) irc.Nick(*botNick) case strings.Contains(line.Args[1], "identified"), strings.Contains(line.Args[1], "recognized"): log.Println("Successfully identified with NickServ; joining", *channelList) irc.Join(*channelList) } } }) irc.HandleFunc("QUIT", func(irc *client.Conn, line *client.Line) { if line.Nick == *botNick { log.Println("Nick", *botNick, "now available, changing to it") irc.Nick(*botNick) } }) irc.HandleFunc("NICK", func(irc *client.Conn, line *client.Line) { if line.Args[len(line.Args)-1] == irc.Me().Nick { log.Println("Nick successfully changed to", irc.Me().Nick) if *nickPass != "" { log.Println("Identifying with NickServ") irc.Privmsg("NickServ", fmt.Sprintf("IDENTIFY %s", *nickPass)) } } }) irc.HandleFunc("332", func(irc *client.Conn, line *client.Line) { log.Println("Joined", line.Args[1]) }) irc.HandleFunc("INVITE", onInvite) irc.HandleFunc("PRIVMSG", onPrivmsg) quitting := false quit := make(chan bool) irc.HandleFunc(client.DISCONNECTED, func(irc *client.Conn, line *client.Line) { if quitting { quit <- true return } resetIdentifiedCache() log.Println("Disconnected; waiting 10 seconds then reconnecting...") saveCacheNow() go func() { time.Sleep(10 * time.Second) errorCount := 0 for !irc.Connected() { log.Println("Reconnecting...") err := irc.ConnectTo(*server, *password) if err != nil { log.Println("Error reconnecting:", err) // limited exponential backoff (10, 12, 14, 18, 26, 42, 74) retryDuration := 10 + time.Duration(math.Pow(2, float64(errorCount)))*time.Second if errorCount < 6 { errorCount += 1 } log.Println("Retrying in", retryDuration) time.Sleep(retryDuration) } } }() }) if *useSSL { log.Println("Using SSL") } log.Println("Connecting to", *server) irc.ConnectTo(*server, *password) sig = make(chan os.Signal, 1) signal.Notify(sig, os.Interrupt, os.Kill, syscall.SIGTERM) <-sig quitting = true log.Println("Disconnecting") irc.Quit("Exiting") saveCacheNow() <-quit // wait until the QUIT is sent to server }
func main() { if len(os.Args) < 2 { fmt.Println("Cannot read config file!") os.Exit(3) } irc.InitConf(os.Args[1]) if len(irc.GetLogFile()) > 0 { f, err := os.OpenFile(irc.GetLogFile(), os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666) if err != nil { fmt.Printf("Error opening log file: %v", err) os.Exit(3) } defer f.Close() log.SetOutput(f) } else { if runtime.GOOS == "windows" { var format = new(prefixed.TextFormatter) format.ForceColors = true log.SetFormatter(format) } } log.SetLevel(log.DebugLevel) log.Infof("<<<<<----- Application started %s ----->>>>>", time.Now()) irc.InitImageAction() CheckAndCreate(irc.GetDataPath()) CheckAndCreate(filepath.Join(irc.GetDataPath(), "thumb")) CheckAndCreate(filepath.Join(irc.GetDataPath(), "image")) CheckAndCreate(filepath.Join(irc.GetDataPath(), "gif")) CheckAndCreate(filepath.Join(irc.GetDataPath(), "webm")) cfg := client.NewConfig(irc.GetBotName()) cfg.SSL = irc.GetUseSsl() cfg.Server = fmt.Sprintf("%s:%d", irc.GetServerAddress(), irc.GetServerPort()) cfg.Pass = irc.GetServerPassword() c = client.Client(cfg) handler := irc.NewHandler(c, irc.GetChannel()) var ssl crypt.Config ssl.InsecureSkipVerify = irc.GetAcceptInvalidCert() cfg.SSLConfig = &ssl quit = make(chan bool) lastReconnect = time.Now() c.HandleFunc("connected", func(conn *client.Conn, line *client.Line) { log.Infof("Connected to server %s, joining channel %s", irc.GetServerAddress(), irc.GetChannel()) conn.Join(fmt.Sprintf("%s %s", irc.GetChannel(), irc.GetChannelPassword())) }) c.HandleFunc("privmsg", func(conn *client.Conn, line *client.Line) { handler.Recv(line.Args[1], line.Nick) }) c.HandleFunc("disconnected", func(conn *client.Conn, line *client.Line) { log.Infof("Disconnected from server %s", irc.GetServerAddress()) handleDisconnect() }) c.HandleFunc("KICK", func(conn *client.Conn, line *client.Line) { log.Infof("Kicked from channel %s", irc.GetChannel()) if irc.GetAutoReJoin() { log.Infof("Joining channel %s", irc.GetChannel()) conn.Join(fmt.Sprintf("%s %s", irc.GetChannel(), irc.GetChannelPassword())) } }) err := connect() if err != nil { log.Errorf(err.Error()) handleDisconnect() } go irc.ImageAction.StartupCheck() web.StartWeb() <-quit }