package irc import ( "bufio" "fmt" "log" "net" "strconv" "strings" "time" ) type IrcConnection struct { Sock net.Conn privmsgCallback func(string, string, string) joinCallback func(string, string) quitCallback func(string, string) partCallback func(string, string, string) numericCallback func(string, int, string) joined bool channels []string } func (c *IrcConnection) SendPong(ping string) { pong := strings.Replace(ping, "PING", "PONG", 1) c.Sock.Write([]byte(fmt.Sprintf("%s\n", pong))) log.Println("pong sent") } func (c *IrcConnection) SendPrivmsg(channel, msg string) { _, err := c.Sock.Write([]byte(fmt.Sprintf("PRIVMSG %s :%s\n", channel, msg))) if err != nil { log.Printf("Error sending private message: %s\n", err.Error()) } } func (c *IrcConnection) SendNotice(channel, msg string) { _, err := c.Sock.Write([]byte(fmt.Sprintf("NOTICE %s :%s\n", channel, msg))) if err != nil { log.Printf("Error sending NOTICE message: %s\n", err.Error()) } } func (c *IrcConnection) SendNick(nick string) { c.Sock.Write([]byte(fmt.Sprintf("NICK %s\n", nick))) } func (c *IrcConnection) SendJoin(channel string) { c.Sock.Write([]byte(fmt.Sprintf("JOIN %s\n", channel))) } func (c *IrcConnection) SendPart(channel, msg string) { c.Sock.Write([]byte(fmt.Sprintf("PART %s :%s\n", channel, msg))) } func (c *IrcConnection) SendQuit(msg string) { c.Sock.Write([]byte(fmt.Sprintf("QUIT :%s\n", msg))) } func (c *IrcConnection) DelayedSend(sock net.Conn, dur time.Duration, channel, msg string) { time.Sleep(dur) c.SendPrivmsg(channel, msg) } func (c *IrcConnection) Names(channel string) { c.Sock.Write([]byte(fmt.Sprintf("NAMES %s\n", channel))) } //NewIrcConnection creates and connects an IrcConnection func NewIrcConnection(server, nick, user, pass string) *IrcConnection { irc := &IrcConnection{} sock, err := net.Dial("tcp", server) if err != nil { log.Fatalln(err.Error()) } irc.Sock = sock irc.Sock.Write([]byte(fmt.Sprintf("USER %s * * :%s\n", user, user))) irc.SendNick(nick) irc.Sock.Write([]byte(fmt.Sprintf("PASS %s\n", pass))) return irc } func getNick(name string) string { return strings.Split(name, "!")[0] } func (c *IrcConnection) parseMessage(line string) { if line[0] == ':' { buf := line[1:] params := strings.SplitN(buf, " ", 3) from := params[0] cmd := params[1] args := params[2] if _, e := strconv.Atoi(cmd); e == nil { //numeric message if !c.joined { if cmd == "376" { for _, v := range c.channels { c.SendJoin(v) } c.joined = true } } if c.numericCallback != nil { code, _ := strconv.Atoi(cmd) c.numericCallback(from, code, args) } } else { t := strings.SplitN(args, ":", 2) target := strings.TrimSpace(t[0]) msg := "" if len(t) > 1 { msg = t[1] } switch strings.ToLower(cmd) { case "privmsg": if c.privmsgCallback != nil { c.privmsgCallback(target, from, msg) } case "join": if c.joinCallback != nil { c.joinCallback(from, target) } case "quit": if c.quitCallback != nil { c.quitCallback(from, msg) } case "part": if c.partCallback != nil { c.partCallback(from, target, msg) } } } } } //Run runs the irc event loop func (c *IrcConnection) Run() { rdr := bufio.NewScanner(c.Sock) c.joined = false for rdr.Scan() { line := rdr.Text() if strings.HasPrefix(line, "PING") { c.SendPong(line) continue } c.parseMessage(line) } }