irc/irc.go

167 lines
3.8 KiB
Go
Raw Normal View History

2020-01-05 12:39:58 -05:00
package irc
import (
"bufio"
"fmt"
"log"
"net"
"strconv"
"strings"
"time"
)
2020-01-05 12:48:57 -05:00
//Connection holds the callbacks for the client
type Connection struct {
2020-01-05 12:39:58 -05:00
Sock net.Conn
2020-01-05 13:04:31 -05:00
PrivmsgCallback func(string, string, string)
JoinCallback func(string, string)
QuitCallback func(string, string)
PartCallback func(string, string, string)
NumericCallback func(string, int, string)
2020-01-05 12:39:58 -05:00
joined bool
channels []string
}
2020-01-05 12:48:57 -05:00
//SendPong replies to the recieved PING
func (c *Connection) SendPong(ping string) {
2020-01-05 12:39:58 -05:00
pong := strings.Replace(ping, "PING", "PONG", 1)
c.Sock.Write([]byte(fmt.Sprintf("%s\n", pong)))
log.Println("pong sent")
}
2020-01-05 12:48:57 -05:00
//SendPrivmsg sends a privmsg to channel/target
func (c *Connection) SendPrivmsg(channel, msg string) {
2020-01-05 12:39:58 -05:00
_, 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())
}
}
2020-01-05 12:48:57 -05:00
//SendNotice sends a notice to channel/target
func (c *Connection) SendNotice(channel, msg string) {
2020-01-05 12:39:58 -05:00
_, 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())
}
}
2020-01-05 12:48:57 -05:00
//SendNick changes the clients nick
func (c *Connection) SendNick(nick string) {
2020-01-05 12:39:58 -05:00
c.Sock.Write([]byte(fmt.Sprintf("NICK %s\n", nick)))
}
2020-01-05 12:48:57 -05:00
//SendJoin sends a JOIN
func (c *Connection) SendJoin(channel string) {
2020-01-05 12:39:58 -05:00
c.Sock.Write([]byte(fmt.Sprintf("JOIN %s\n", channel)))
}
2020-01-05 12:48:57 -05:00
//SendPart sends a PART
func (c *Connection) SendPart(channel, msg string) {
2020-01-05 12:39:58 -05:00
c.Sock.Write([]byte(fmt.Sprintf("PART %s :%s\n", channel, msg)))
}
2020-01-05 12:48:57 -05:00
//SendQuit sends a QUIT
func (c *Connection) SendQuit(msg string) {
2020-01-05 12:39:58 -05:00
c.Sock.Write([]byte(fmt.Sprintf("QUIT :%s\n", msg)))
}
2020-01-05 12:48:57 -05:00
//SendNames sends a NAMES request for the channel
func (c *Connection) SendNames(channel string) {
c.Sock.Write([]byte(fmt.Sprintf("NAMES %s\n", channel)))
2020-01-05 12:39:58 -05:00
}
2020-01-05 12:48:57 -05:00
//DelayedSend sends a privmsg AFTER the specified delay
func (c *Connection) DelayedSend(sock net.Conn, dur time.Duration, channel, msg string) {
time.Sleep(dur)
c.SendPrivmsg(channel, msg)
2020-01-05 12:39:58 -05:00
}
2020-01-05 12:48:57 -05:00
//NewConnection creates and connects an Connection
func NewConnection(server, nick, user, pass string, chans []string) *Connection {
irc := &Connection{channels: chans}
2020-01-05 12:39:58 -05:00
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]
}
2020-01-05 12:48:57 -05:00
func (c *Connection) parseMessage(line string) {
2020-01-05 12:39:58 -05:00
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
}
}
2020-01-05 13:04:31 -05:00
if c.NumericCallback != nil {
2020-01-05 12:39:58 -05:00
code, _ := strconv.Atoi(cmd)
2020-01-05 13:04:31 -05:00
c.NumericCallback(from, code, args)
2020-01-05 12:39:58 -05:00
}
} 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":
2020-01-05 13:04:31 -05:00
if c.PrivmsgCallback != nil {
c.PrivmsgCallback(target, from, msg)
2020-01-05 12:39:58 -05:00
}
case "join":
2020-01-05 13:04:31 -05:00
if c.JoinCallback != nil {
c.JoinCallback(from, target)
2020-01-05 12:39:58 -05:00
}
case "quit":
2020-01-05 13:04:31 -05:00
if c.QuitCallback != nil {
c.QuitCallback(from, msg)
2020-01-05 12:39:58 -05:00
}
case "part":
2020-01-05 13:04:31 -05:00
if c.PartCallback != nil {
c.PartCallback(from, target, msg)
2020-01-05 12:39:58 -05:00
}
}
}
}
}
//Run runs the irc event loop
2020-01-05 12:48:57 -05:00
func (c *Connection) Run() {
2020-01-05 12:39:58 -05:00
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)
}
}