diff --git a/build/package/Dockerfile b/build/package/Dockerfile index 5401d5f..11fe7de 100755 --- a/build/package/Dockerfile +++ b/build/package/Dockerfile @@ -10,4 +10,6 @@ FROM scratch COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=builder /go/src/git.martyn.berlin/martyn/karaokards /app/ COPY strings.json /app/strings.json +COPY web/ /app/web/ +WORKDIR /app CMD ["/app/karaokards"] \ No newline at end of file diff --git a/internal/irc/irc.go b/internal/irc/irc.go index 475fd31..62c2c94 100644 --- a/internal/irc/irc.go +++ b/internal/irc/irc.go @@ -21,9 +21,9 @@ const PSTFormat = "Jan 2 15:04:05 PST" // Regex for parsing PRIVMSG strings. // -// First matched group is the user's name and the second matched group is the content of the +// 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 MsgRegex *regexp.Regexp = regexp.MustCompile(`^:(\w+)!\w+@\w+\.tmi\.twitch\.tv (PRIVMSG) #(\w+)(?: :(.*))?$`) // Regex for parsing user commands, from already parsed PRIVMSG strings. // @@ -38,6 +38,9 @@ type OAuthCred struct { // The developer application client ID. Used for API calls to Twitch. ClientID string `json:"client_id,omitempty"` + + // List of Channels to join + Channels []string `json:"channels,omitempty"` } type KardBot struct { @@ -111,10 +114,11 @@ func (bb *KardBot) HandleChat() error { if nil != matches { userName := matches[1] msgType := matches[2] + channel := matches[3] switch msgType { case "PRIVMSG": - msg := matches[3] + msg := matches[4] rgb.GPrintf("[%s] %s: %s\n", TimeStamp(), userName, msg) // parse commands from user message @@ -124,9 +128,9 @@ func (bb *KardBot) HandleChat() error { switch cmd { case "card": - rgb.CPrintf("[%s] Card asked for!\n", TimeStamp()) + 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))]) + bb.Say("Your prompt is : "+bb.Prompts[rand.Intn(len(bb.Prompts))], channel) } // channel-owner specific commands @@ -147,6 +151,7 @@ func (bb *KardBot) HandleChat() error { } default: // do nothing + rgb.YPrintf("[%s] unknown IRC message : %s\n", TimeStamp(), line) } } } @@ -154,14 +159,24 @@ func (bb *KardBot) HandleChat() error { } } -// Makes the bot join its pre-specified channel. -func (bb *KardBot) JoinChannel() { - rgb.YPrintf("[%s] Joining #%s...\n", TimeStamp(), bb.Channel) +// Login to the IRC server +func (bb *KardBot) Login() { + rgb.YPrintf("[%s] Logging into #%s...\n", TimeStamp(), bb.Channel) bb.conn.Write([]byte("PASS " + bb.Credentials.Password + "\r\n")) bb.conn.Write([]byte("NICK " + bb.Name + "\r\n")) - bb.conn.Write([]byte("JOIN #" + bb.Channel + "\r\n")) +} + +// Makes the bot join its pre-specified channel. +func (bb *KardBot) JoinChannel(channels ...string) { + if len(channels) == 0 { + channels = append(channels, bb.Channel) + } - rgb.YPrintf("[%s] Joined #%s as @%s!\n", TimeStamp(), bb.Channel, bb.Name) + for _, channel := range channels { + rgb.YPrintf("[%s] Joining #%s...\n", TimeStamp(), channel) + bb.conn.Write([]byte("JOIN #" + channel + "\r\n")) + rgb.YPrintf("[%s] Joined #%s as @%s!\n", TimeStamp(), channel, bb.Name) + } } // Reads from the private credentials file and stores the data in the bot's Credentials field. @@ -185,7 +200,7 @@ func (bb *KardBot) ReadCredentials() error { } // Makes the bot send a message to the chat channel. -func (bb *KardBot) Say(msg string) error { +func (bb *KardBot) Say(msg string, channels ...string) error { if "" == msg { return errors.New("BasicBot.Say: msg was empty.") } @@ -195,9 +210,17 @@ func (bb *KardBot) Say(msg string) error { return errors.New("BasicBot.Say: msg exceeded 512 bytes") } - _, err := bb.conn.Write([]byte(fmt.Sprintf("PRIVMSG #%s :%s\r\n", bb.Channel, msg))) - if nil != err { - return err + if len(channels) == 0 { + channels = append(channels, bb.Channel) + } + + rgb.YPrintf("[%s] sending %s to channels %v as @%s!\n", TimeStamp(), msg, channels, bb.Name) + for _, channel := range channels { + _, 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 } @@ -215,7 +238,12 @@ func (bb *KardBot) Start() { for { bb.Connect() - bb.JoinChannel() + bb.Login() + if len(bb.Credentials.Channels) > 0 { + bb.JoinChannel(bb.Credentials.Channels...) + } else { + bb.JoinChannel() + } err = bb.HandleChat() if nil != err { diff --git a/internal/webserver/webserver.go b/internal/webserver/webserver.go index e0fe2ef..d0e710a 100755 --- a/internal/webserver/webserver.go +++ b/internal/webserver/webserver.go @@ -1,9 +1,11 @@ package webserver import ( + "math/rand" + + irc "git.martyn.berlin/martyn/karaokards/internal/irc" "github.com/gorilla/handlers" "github.com/gorilla/mux" - "github.com/gorilla/sessions" "fmt" "html/template" @@ -15,7 +17,7 @@ import ( //var store = sessions.NewCookieStore(os.Getenv("SESSION_KEY")) -var store = sessions.NewCookieStore([]byte("GO_SESS")) +var ircBot irc.KardBot func HealthHandler(response http.ResponseWriter, request *http.Request) { response.Header().Add("Content-type", "text/plain") @@ -42,8 +44,10 @@ func RootHandler(response http.ResponseWriter, request *http.Request) { func TemplateHandler(response http.ResponseWriter, request *http.Request) { response.Header().Add("X-Template-File", "web"+request.URL.Path) type TemplateData struct { - Prompt string - AvailCount int + Prompt string + AvailCount int + ChannelCount int + MessageCount int } // tmpl, err := template.New("html"+request.URL.Path).Funcs(template.FuncMap{ // "ToUpper": strings.ToUpper, @@ -68,7 +72,7 @@ func TemplateHandler(response http.ResponseWriter, request *http.Request) { // NotFoundHandler(response, request) // return } - var td = TemplateData{"Hello", 1} + var td = TemplateData{ircBot.Prompts[rand.Intn(len(ircBot.Prompts))], len(ircBot.Prompts), len(ircBot.Credentials.Channels), 0} err = tmpl.Execute(response, td) if err != nil { http.Error(response, err.Error(), http.StatusInternalServerError) @@ -76,7 +80,8 @@ func TemplateHandler(response http.ResponseWriter, request *http.Request) { } } -func HandleHTTP() { +func HandleHTTP(passedIrcBot irc.KardBot) { + ircBot = passedIrcBot r := mux.NewRouter() loggedRouter := handlers.LoggingHandler(os.Stdout, r) r.NotFoundHandler = http.HandlerFunc(NotFoundHandler) diff --git a/main.go b/main.go index e63d772..4db57ae 100755 --- a/main.go +++ b/main.go @@ -86,7 +86,7 @@ func main() { } go func() { rgb.YPrintf("[%s] Starting webserver on port %s\n", irc.TimeStamp(), "5353") - webserver.HandleHTTP() + webserver.HandleHTTP(myBot) }() myBot.Start() } diff --git a/web/404.html b/web/404.html index 3926de0..d225779 100644 --- a/web/404.html +++ b/web/404.html @@ -4,9 +4,9 @@
- + -It seems you've gone somewhere you shouldn't! 404 NOT FOUND!
-This can happen if you enter the spotify id wrong and search, go back and check it!
-Spotify IDs look like this : 37i9dQZF1DX4UtSsGT1Sbe - 22 characters and can be got by clicking share and "Copy (Playlist|Album) Link".
+I'm not quite sure how you got here to be honest, if it was via a link on the site, let me know via twitch DM, if it was from someone else, let them know.
Shameless self-promotion : Follow me on twitch - iMartynOnTwitch, oddly enough, I do a lot of twitchsings!