Browse Source

Initial working TCP version

tags/v0.1.0
Russ Garrett 7 years ago
commit
2e58d8ab24
No account linked to committer's email address
4 changed files with 203 additions and 0 deletions
  1. 12
    0
      irccat.json
  2. 70
    0
      main.go
  3. 34
    0
      tcplistener/colours.go
  4. 87
    0
      tcplistener/tcplistener.go

+ 12
- 0
irccat.json View File

@@ -0,0 +1,12 @@
1
+{
2
+  "tcp_listen": ":12345",
3
+  "http_listen": ":8045",
4
+  "irc": {
5
+    "server": "irc.irccloud.com:6667",
6
+    "tls": false,
7
+    "tls_skip_verify": true,
8
+    "nick": "gocat",
9
+    "realname": "IRCCat",
10
+    "channels": ["#russtest"]
11
+  }
12
+}

+ 70
- 0
main.go View File

@@ -0,0 +1,70 @@
1
+package main
2
+
3
+import (
4
+	"crypto/tls"
5
+	"github.com/irccloud/irccat/tcplistener"
6
+	"github.com/juju/loggo"
7
+	"github.com/spf13/viper"
8
+	"github.com/thoj/go-ircevent"
9
+)
10
+
11
+var log = loggo.GetLogger("main")
12
+
13
+type IRCCat struct {
14
+	irc *irc.Connection
15
+	tcp *tcplistener.TCPListener
16
+}
17
+
18
+func main() {
19
+	loggo.ConfigureLoggers("<root>=DEBUG")
20
+	viper.SetConfigName("irccat")
21
+	viper.AddConfigPath("/etc")
22
+	viper.AddConfigPath(".")
23
+	var err error
24
+
25
+	err = viper.ReadInConfig()
26
+	if err != nil {
27
+		return
28
+	}
29
+
30
+	irccat := IRCCat{}
31
+
32
+	irccat.tcp, err = tcplistener.Bind()
33
+	if err != nil {
34
+		return
35
+	}
36
+
37
+	err = irccat.connectIRC()
38
+
39
+	if err != nil {
40
+		log.Criticalf("Error connecting to IRC server: %s", err)
41
+		return
42
+	}
43
+
44
+	irccat.tcp.Run(irccat.irc)
45
+	irccat.irc.Loop()
46
+}
47
+
48
+func (i *IRCCat) connectIRC() error {
49
+	irccon := irc.IRC(viper.GetString("irc.nick"), viper.GetString("irc.realname"))
50
+	irccon.UseTLS = viper.GetBool("irc.tls")
51
+	if viper.GetBool("irc.tls_skip_verify") {
52
+		irccon.TLSConfig = &tls.Config{InsecureSkipVerify: true}
53
+	}
54
+
55
+	err := irccon.Connect(viper.GetString("irc.server"))
56
+	if err != nil {
57
+		return err
58
+	}
59
+
60
+	irccon.AddCallback("001", i.handleWelcome)
61
+
62
+	i.irc = irccon
63
+	return nil
64
+}
65
+
66
+func (i *IRCCat) handleWelcome(e *irc.Event) {
67
+	for _, channel := range viper.GetStringSlice("irc.channels") {
68
+		i.irc.Join(channel)
69
+	}
70
+}

+ 34
- 0
tcplistener/colours.go View File

@@ -0,0 +1,34 @@
1
+package tcplistener
2
+
3
+import "strings"
4
+
5
+var colourMap map[string]string = map[string]string{
6
+	"NORMAL":    "\x0f",
7
+	"BOLD":      "\x02",
8
+	"UNDERLINE": "\x1f",
9
+	"REVERSE":   "\x16",
10
+	"WHITE":     "\x0300",
11
+	"BLACK":     "\x0301",
12
+	"DBLUE":     "\x0302",
13
+	"DGREEN":    "\x0303",
14
+	"RED":       "\x0304",
15
+	"BROWN":     "\x0305",
16
+	"PURPLE":    "\x0306",
17
+	"ORANGE":    "\x0307",
18
+	"YELLOW":    "\x0308",
19
+	"GREEN":     "\x0309",
20
+	"TEAL":      "\x0310",
21
+	"CYAN":      "\x0311",
22
+	"BLUE":      "\x0312",
23
+	"PINK":      "\x0313",
24
+	"DGRAY":     "\x0314",
25
+	"GRAY":      "\x0315",
26
+}
27
+
28
+func replaceFormatting(msg string) string {
29
+	for colour, code := range colourMap {
30
+		msg = strings.Replace(msg, "%"+colour, code, -1)
31
+		msg = strings.Replace(msg, "#"+colour, code, -1)
32
+	}
33
+	return msg
34
+}

+ 87
- 0
tcplistener/tcplistener.go View File

@@ -0,0 +1,87 @@
1
+package tcplistener
2
+
3
+import (
4
+	"bufio"
5
+	"github.com/juju/loggo"
6
+	"github.com/spf13/viper"
7
+	"github.com/thoj/go-ircevent"
8
+	"net"
9
+	"strings"
10
+)
11
+
12
+var log = loggo.GetLogger("TCPListener")
13
+
14
+type TCPListener struct {
15
+	socket net.Listener
16
+	irc    *irc.Connection
17
+}
18
+
19
+func Bind() (*TCPListener, error) {
20
+	var err error
21
+
22
+	listener := TCPListener{}
23
+	listener.socket, err = net.Listen("tcp", viper.GetString("tcp_listen"))
24
+	if err != nil {
25
+		return nil, err
26
+	}
27
+
28
+	return &listener, nil
29
+}
30
+
31
+func (l *TCPListener) Run(irccon *irc.Connection) {
32
+	log.Infof("Listening for TCP requests on %s", viper.GetString("tcp_listen"))
33
+	l.irc = irccon
34
+	go l.acceptConnections()
35
+}
36
+
37
+func (l *TCPListener) acceptConnections() {
38
+	for {
39
+		conn, err := l.socket.Accept()
40
+		if err != nil {
41
+			break
42
+		}
43
+		go l.handleConnection(conn)
44
+	}
45
+	l.socket.Close()
46
+}
47
+
48
+func (l *TCPListener) handleConnection(conn net.Conn) {
49
+	reader := bufio.NewReader(conn)
50
+	for {
51
+		msg, err := reader.ReadString('\n')
52
+		if err != nil {
53
+			break
54
+		}
55
+		msg = strings.Trim(msg, "\r\n")
56
+		log.Debugf("Message: %s", msg)
57
+		l.parseMessage(msg)
58
+	}
59
+}
60
+
61
+func (l *TCPListener) parseMessage(msg string) {
62
+	channels := viper.GetStringSlice("irc.channels")
63
+
64
+	if msg[0] == '#' || msg[0] == '@' {
65
+		parts := strings.SplitN(msg, " ", 2)
66
+		if parts[0] == "#*" {
67
+			for _, channel := range channels {
68
+				l.irc.Privmsg(channel, replaceFormatting(parts[1]))
69
+			}
70
+		} else {
71
+			targets := strings.Split(parts[0], ",")
72
+			for _, target := range targets {
73
+				if target[0] == '@' {
74
+					target = target[1:]
75
+				}
76
+				l.irc.Privmsg(target, replaceFormatting(parts[1]))
77
+			}
78
+		}
79
+	} else if msg[0:6] == "%TOPIC" {
80
+		parts := strings.SplitN(msg, " ", 3)
81
+		l.irc.SendRawf("TOPIC %s :%s", parts[1], replaceFormatting(parts[2]))
82
+	} else {
83
+		if len(channels) > 0 {
84
+			l.irc.Privmsg(channels[0], replaceFormatting(msg))
85
+		}
86
+	}
87
+}

Loading…
Cancel
Save