diff --git a/src/irc.go b/src/irc.go index 0455e06..ea438c7 100644 --- a/src/irc.go +++ b/src/irc.go @@ -10,26 +10,29 @@ import ( "net" "strings" "time" - "github.com/lye/tls" + "tls" ) const ( - VERSION = "GolangBOT v1.0" + VERSION = "cleanirc v1.0" ) var error_ bool func reader(irc *IRCConnection) { br := bufio.NewReader(irc.socket) + for !error_ { msg, err := br.ReadString('\n') if err != nil { irc.Error <- err break } + irc.lastMessage = time.Now() msg = msg[0 : len(msg)-2] //Remove \r\n event := &IRCEvent{Raw: msg} + if msg[0] == ':' { if i := strings.Index(msg, " "); i > -1 { event.Source = msg[1:i] @@ -43,32 +46,39 @@ func reader(irc *IRCConnection) { event.Host = event.Source[j+1 : len(event.Source)] } } + args := strings.SplitN(msg, " :", 2) if len(args) > 1 { event.Message = args[1] } + args = strings.Split(args[0], " ") event.Code = strings.ToUpper(args[0]) if len(args) > 1 { event.Arguments = args[1:len(args)] } + irc.RunCallbacks(event) } + irc.syncreader <- true } func writer(irc *IRCConnection) { b, ok := <-irc.pwrite + for !error_ && ok { if b == "" || irc.socket == nil { break } + _, err := irc.socket.Write([]byte(b)) if err != nil { fmt.Printf("%s\n", err) irc.Error <- err break } + b, ok = <-irc.pwrite } irc.syncwriter <- true @@ -78,6 +88,7 @@ func writer(irc *IRCConnection) { func pinger(i *IRCConnection) { i.ticker = time.Tick(1 * time.Minute) //Tick every minute. i.ticker2 = time.Tick(15 * time.Minute) //Tick every 15 minutes. + for { select { case <-i.ticker: @@ -85,6 +96,7 @@ func pinger(i *IRCConnection) { if time.Since(i.lastMessage) >= (4 * time.Minute) { i.SendRaw(fmt.Sprintf("PING %d", time.Now().UnixNano())) } + case <-i.ticker2: //Ping every 15 minutes. i.SendRaw(fmt.Sprintf("PING %d", time.Now().UnixNano())) @@ -131,8 +143,10 @@ func (irc *IRCConnection) SendRaw(message string) { func (i *IRCConnection) Reconnect() error { close(i.pwrite) close(i.pread) + <-i.syncreader <-i.syncwriter + for { fmt.Printf("Reconnecting to %s\n", i.server) var err error @@ -142,27 +156,36 @@ func (i *IRCConnection) Reconnect() error { } fmt.Printf("Error: %s\n", err) } + error_ = false + fmt.Printf("Connected to %s (%s)\n", i.server, i.socket.RemoteAddr()) + go reader(i) go writer(i) + i.pwrite <- fmt.Sprintf("NICK %s\r\n", i.nick) i.pwrite <- fmt.Sprintf("USER %s 0.0.0.0 0.0.0.0 :%s\r\n", i.user, i.user) + return nil } func (i *IRCConnection) Loop() { for !i.quitting { e := <-i.Error + if i.quitting { break } + fmt.Printf("Error: %s\n", e) error_ = true i.Reconnect() } + close(i.pwrite) close(i.pread) + <-i.syncreader <-i.syncwriter } diff --git a/src/irc_callback.go b/src/irc_callback.go index b6a922b..6acc685 100644 --- a/src/irc_callback.go +++ b/src/irc_callback.go @@ -9,8 +9,10 @@ import ( func (irc *IRCConnection) AddCallback(eventcode string, callback func(*IRCEvent)) { eventcode = strings.ToUpper(eventcode) + if _, ok := irc.events[eventcode]; ok { irc.events[eventcode] = append(irc.events[eventcode], callback) + } else { irc.events[eventcode] = make([]func(*IRCEvent), 1) irc.events[eventcode][0] = callback @@ -19,42 +21,54 @@ func (irc *IRCConnection) AddCallback(eventcode string, callback func(*IRCEvent) func (irc *IRCConnection) ReplaceCallback(eventcode string, i int, callback func(*IRCEvent)) { eventcode = strings.ToUpper(eventcode) + if event, ok := irc.events[eventcode]; ok { if i < len(event) { event[i] = callback return } + fmt.Printf("Event found, but no callback found at index %d. Use AddCallback\n", i) return } + fmt.Printf("Event not found. Use AddCallBack\n") } func (irc *IRCConnection) RunCallbacks(event *IRCEvent) { if event.Code == "PRIVMSG" && len(event.Message) > 0 && event.Message[0] == '\x01' { event.Code = "CTCP" //Unknown CTCP + if i := strings.LastIndex(event.Message, "\x01"); i > -1 { event.Message = event.Message[1:i] } + if event.Message == "VERSION" { event.Code = "CTCP_VERSION" + } else if event.Message == "TIME" { event.Code = "CTCP_TIME" + } else if event.Message[0:4] == "PING" { event.Code = "CTCP_PING" + } else if event.Message == "USERINFO" { event.Code = "CTCP_USERINFO" + } else if event.Message == "CLIENTINFO" { event.Code = "CTCP_CLIENTINFO" } } + if callbacks, ok := irc.events[event.Code]; ok { if irc.VerboseCallbackHandler { fmt.Printf("%v (%v) >> %#v\n", event.Code, len(callbacks), event) } + for _, callback := range callbacks { go callback(event) } + } else if irc.VerboseCallbackHandler { fmt.Printf("%v (0) >> %#v\n", event.Code, event) } @@ -84,7 +98,9 @@ func (irc *IRCConnection) setupCallbacks() { irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01TIME %s\x01", e.Nick, ltime.String())) }) - irc.AddCallback("CTCP_PING", func(e *IRCEvent) { irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01%s\x01", e.Nick, e.Message)) }) + irc.AddCallback("CTCP_PING", func(e *IRCEvent) { + irc.SendRaw(fmt.Sprintf("NOTICE %s :\x01%s\x01", e.Nick, e.Message)) + }) irc.AddCallback("437", func(e *IRCEvent) { irc.nickcurrent = irc.nickcurrent + "_" @@ -94,9 +110,11 @@ func (irc *IRCConnection) setupCallbacks() { irc.AddCallback("433", func(e *IRCEvent) { if len(irc.nickcurrent) > 8 { irc.nickcurrent = "_" + irc.nickcurrent + } else { irc.nickcurrent = irc.nickcurrent + "_" } + irc.SendRaw(fmt.Sprintf("NICK %s", irc.nickcurrent)) }) diff --git a/src/irc_struct.go b/src/irc_struct.go index 44ea0de..9a7f538 100644 --- a/src/irc_struct.go +++ b/src/irc_struct.go @@ -7,7 +7,7 @@ package irc import ( "net" "time" - "github.com/lye/tls" + "tls" ) type IRCConnection struct {