main.go (view raw)
1package main
2
3import (
4 "fmt"
5 "log"
6 "net"
7 "strings"
8
9 "git.icyphox.sh/paprika/config"
10 "git.icyphox.sh/paprika/database"
11 "git.icyphox.sh/paprika/plugins"
12 "gopkg.in/irc.v3"
13)
14
15// A simple check func to find out if an incoming irc message
16// is supposed to be a CTCP message
17func isCTCPmessage(m *irc.Message) bool {
18 // CTCP messages are identified by their first character byte
19 // being equal to 0x01.
20 return m.Params[1][0] == 0x01
21}
22
23// CTCP responses are sent with a NOTICE, instead of a PRIVMSG
24func sendCTCPResponse(c *irc.Client, m *irc.Message, command string, message string) {
25 c.WriteMessage(&irc.Message{
26 Command: "NOTICE",
27 Params: []string{
28 m.Prefix.Name,
29 fmt.Sprintf("\x01%s %s\x01", command, message),
30 },
31 })
32}
33
34// for future use. Perhaps move all of this CTCP stuff out another file?
35func sendCTCPRequest(c *irc.Client, m *irc.Message, command string, message string) {
36 c.WriteMessage(&irc.Message{
37 Command: "PRIVMSG",
38 Params: []string{
39 m.Prefix.Name,
40 fmt.Sprintf("\x01%s %s\x01", command, message),
41 },
42 })
43}
44
45func handleCTCPMessage(c *irc.Client, m *irc.Message) {
46
47 // Refer to for further commands to implement and as a general
48 // guide on how CTCP works:
49 // https://tools.ietf.org/id/draft-oakley-irc-ctcp-01.html
50
51 var ctcpCommand = m.Params[1] // var might be named wrong
52
53 // start of the main if/else tree for CTCP checking. idk why, but
54 // for some reason a straight switch/case comparison simply did not work
55 if strings.Contains(ctcpCommand, "VERSION") {
56 sendCTCPResponse(c, m, "VERSION", "Paprika v0.0.1")
57 } else if strings.Contains(ctcpCommand, "PING") {
58 // lotsa ugly string processing here, but w/e
59
60 // split the incoming ping by word, strip out the first word (the command)
61 output := strings.Split(m.Params[1], " ")[1:]
62 outputStr := strings.Join(output, " ") // re-join
63
64 // send response while stripping out the last char,
65 // somehwere deep in the wirting a random char gets added
66 // to the start and end of the incomming message.
67 // the first char gets stripped out along with the command word.
68 // the last char gets stripped out here.
69 sendCTCPResponse(c, m, "PING", outputStr[0:len(outputStr)-1])
70 } else if strings.Contains(ctcpCommand, "CLIENTINFO") {
71
72 // UPDATE THIS WITH ANY NEW CTCP COMMAND YOU IMPLEMENT
73 sendCTCPResponse(
74 c, m,
75 "CLIENTINFO",
76 "VERSION PING",
77 )
78 }
79}
80
81func handleChatMessage(c *irc.Client, m *irc.Message) {
82 response, err := plugins.ProcessTrigger(m)
83 if err != nil {
84 log.Printf("error: %v", err)
85 }
86
87 // split the plugin output by it's newlines, send every line
88 // as a separate PRIVMSG
89 split := strings.Split(response, "\n")
90
91 for _, line := range split {
92 c.WriteMessage(&irc.Message{
93 Command: "PRIVMSG",
94 Params: []string{
95 m.Params[0],
96 line,
97 },
98 })
99 }
100}
101
102func ircHandler(c *irc.Client, m *irc.Message) {
103 switch m.Command {
104 case "001":
105 c.Write(config.SplitChannelList(config.C.Channels))
106 case "PRIVMSG":
107 if isCTCPmessage(m) {
108 handleCTCPMessage(c, m)
109 } else {
110 handleChatMessage(c, m)
111 }
112 }
113}
114
115func main() {
116 conn, err := net.Dial("tcp", config.C.Host)
117 if err != nil {
118 log.Fatal(err)
119 }
120 defer conn.Close()
121
122 ircConfig := irc.ClientConfig{
123 Nick: config.C.Nick,
124 Pass: config.C.Pass,
125 User: "paprikabot",
126 Name: config.C.Nick,
127 Handler: irc.HandlerFunc(ircHandler),
128 }
129
130 database.DB.DB, err = database.Open()
131 if err != nil {
132 log.Fatal(err)
133 }
134 defer database.DB.Close()
135
136 client := irc.NewClient(conn, ircConfig)
137 err = client.Run()
138 if err != nil {
139 log.Fatal(err)
140 }
141}