diff --git a/internal/irc/irc.go b/internal/irc/irc.go index 0d36738..db7d928 100644 --- a/internal/irc/irc.go +++ b/internal/irc/irc.go @@ -22,11 +22,17 @@ import ( const PSTFormat = "Jan 2 15:04:05 PST" +// Regex for parsing connection messages +// +// First matched group is our real username - twitch doesn't complain at using NICK command but doesn't honor it. +var ConnectRegex *regexp.Regexp = regexp.MustCompile(`^:tmi.twitch.tv 001 ([^ ]+) .*`) + // Regex for parsing PRIVMSG strings. // // First matched group is the user's name, second is the channel? and the third matched group is the content of the // user's message. var MsgRegex *regexp.Regexp = regexp.MustCompile(`^:(\w+)!\w+@\w+\.tmi\.twitch\.tv (PRIVMSG) #(\w+)(?: :(.*))?$`) +var DirectMsgRegex *regexp.Regexp = regexp.MustCompile(`^:(\w+)!\w+@\w+\.tmi\.twitch\.tv (PRIVMSG) (\w+)(?: :(.*))?$`) // Regex for parsing user commands, from already parsed PRIVMSG strings. // @@ -119,9 +125,29 @@ func (bb *KardBot) HandleChat() error { bb.conn.Write([]byte("PONG :tmi.twitch.tv\r\n")) continue } else { + matches := ConnectRegex.FindStringSubmatch(line) + if nil != matches { + realUserName := matches[1] + if bb.ChannelData[realUserName].Name == "" { + record := ChannelData{Name: realUserName, JoinTime: time.Now(), Command: "card", ControlChannel: true} + bb.Database.Write("channelData", realUserName, record) + bb.ChannelData[realUserName] = record + } + bb.JoinChannel(realUserName) + } + + matches = DirectMsgRegex.FindStringSubmatch(line) + if nil != matches { + userName := matches[1] +// msgType := matches[2] +// channel := matches[3] + msg := matches[4] + rgb.GPrintf("[%s] Direct message %s: %s\n", TimeStamp(), userName, msg) + + } // handle a PRIVMSG message - matches := MsgRegex.FindStringSubmatch(line) + matches = MsgRegex.FindStringSubmatch(line) if nil != matches { userName := matches[1] msgType := matches[2] @@ -143,6 +169,16 @@ func (bb *KardBot) HandleChat() error { rgb.CPrintf("[%s] Card asked for by %s on %s' channel!\n", TimeStamp(), userName, channel) bb.Say("Your prompt is : "+bb.Prompts[rand.Intn(len(bb.Prompts))], channel) + case "join": + if bb.ChannelData[channel].ControlChannel { + rgb.CPrintf("[%s] Join asked for by %s on %s' channel!\n", TimeStamp(), userName, channel) + if bb.ChannelData[userName].Name == "" { + record := ChannelData{Name: userName, JoinTime: time.Now(), Command: "card", ControlChannel: true} + bb.Database.Write("channelData", userName, record) + bb.ChannelData[userName] = record + } + bb.JoinChannel(userName) + } } // channel-owner specific commands @@ -156,13 +192,17 @@ func (bb *KardBot) HandleChat() error { bb.Disconnect() return nil - case "wat": + case "kcardadmin": magicCode := bb.readOrCreateChannelKey(channel) rgb.CPrintf( "[%s] Magic code is %s - https://karaokards.ing.martyn.berlin/admin/%s/%s\n", TimeStamp(), magicCode, userName, magicCode, ) + err := bb.Msg("Welcome to Karaokards, your admin panel is https://karaokards.ing.martyn.berlin/admin/"+userName+"/"+magicCode, userName) + if err != nil { + rgb.RPrintf("[%s] ERROR %s\n",err) + } bb.Say("Ack.") default: // do nothing @@ -227,6 +267,31 @@ func (bb *KardBot) ReadCredentials() error { return nil } +func (bb *KardBot) Msg(msg string, users ...string) error { + if "" == msg { + return errors.New("BasicBot.Say: msg was empty.") + } + + // check if message is too large for IRC + if len(msg) > 512 { + return errors.New("BasicBot.Say: msg exceeded 512 bytes") + } + + if len(users) == 0 { + return errors.New("BasicBot.Say: users was empty.") + } + + rgb.YPrintf("[%s] sending %s to users %v as @%s!\n", TimeStamp(), msg, users, bb.Name) + for _, channel := range users { + _, err := bb.conn.Write([]byte(fmt.Sprintf("PRIVMSG %s :%s\r\n", channel, msg))) + rgb.YPrintf("[%s] PRIVMSG %s :%s\r\n", TimeStamp(), channel, msg) + if nil != err { + return err + } + } + return nil +} + // Makes the bot send a message to the chat channel. func (bb *KardBot) Say(msg string, channels ...string) error { if "" == msg {