all repos — paprika @ 3a6f4cb1fc53b08fb810de6293a22718bb8ce9ef

go rewrite of taigabot

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}