1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
package irclogs
import (
"bufio"
"database/sql"
"fmt"
"log"
"net"
"net/textproto"
"slices"
"strings"
)
type IRCClient struct {
dbid int
Host string
port int
nick string
pass string
caps []string
rooms []string
conn net.Conn
}
func NewIRCClient(dbid int, host string, port int, nick string, pass string, capabilities []string) IRCClient {
return IRCClient{
dbid: dbid,
Host: host,
port: port,
nick: nick,
pass: pass,
caps: capabilities,
}
}
func (c *IRCClient) Connect() (err error) {
conn, err := net.Dial("tcp", net.JoinHostPort(c.Host, fmt.Sprintf("%d", c.port)))
if err != nil {
return
}
c.conn = conn
c.authorize()
for _, r := range c.rooms {
c.SendRaw(fmt.Sprintf("JOIN %s", r))
}
tp := textproto.NewReader(bufio.NewReader(c.conn))
for {
raw, err := tp.ReadLine()
if err != nil {
log.Panicf("Failed to read a line: %v\n", err)
}
for _, line := range strings.Split(raw, "\r\n") {
message := ParseIRCMessage(line)
log.Printf("IRC message: %s\n", message)
}
}
}
func (c *IRCClient) authorize() {
c.SendRaw(fmt.Sprintf("NICK %s", c.nick))
c.SendRaw(fmt.Sprintf("PASS %s", c.pass))
for _, cap := range c.caps {
c.SendRaw(fmt.Sprintf("CAP REQ :%s", cap))
}
}
func (c *IRCClient) SendRaw(message string) {
if c.conn != nil {
fmt.Fprintf(c.conn, "%s\r\n", message)
}
}
func (c *IRCClient) JoinChannels(db *sql.DB) {
for {
rooms := []string{}
rows, err := db.Query("SELECT name FROM rooms WHERE server_id = ? AND departed_at IS NULL", c.dbid)
if err != nil {
log.Fatalf("Failed to get rooms: %v\n", err)
continue
}
for rows.Next() {
var room string
if err = rows.Scan(&room); err != nil {
log.Fatalf("Failed to scan rows: %v\n", err)
continue
}
rooms = append(rooms, room)
}
rows.Close()
for _, r := range rooms {
if !slices.Contains(c.rooms, r) {
log.Printf("[%s] Joining %s...", c.Host, r)
c.SendRaw(fmt.Sprintf("JOIN %s", r))
c.rooms = append(c.rooms, r)
}
}
for _, r := range c.rooms {
if !slices.Contains(rooms, r) {
log.Printf("[%s] Departing %s...", c.Host, r)
c.SendRaw(fmt.Sprintf("PART %s", r))
c.rooms = slices.DeleteFunc(c.rooms, func(s string) bool { return s == r })
}
}
}
}
|