diff --git a/internal/irc/irc.go b/internal/irc/irc.go index 310916c..8a5965c 100644 --- a/internal/irc/irc.go +++ b/internal/irc/irc.go @@ -55,13 +55,13 @@ type KardBot struct { startTime time.Time Prompts []string Database scribble.Driver - channelData map[string]ChannelData + ChannelData map[string]ChannelData } type ChannelData struct { Name string `json:"name"` AdminKey string `json:"value,omitempty"` - CustomCommand string `json:"customcommand,omitempty"` + Command string `json:"customcommand,omitempty"` ExtraStrings string `json:"extrastrings,omitempty"` JoinTime time.Time `json:"jointime"` } @@ -136,8 +136,9 @@ func (bb *KardBot) HandleChat() error { if nil != cmdMatches { cmd := cmdMatches[1] + rgb.YPrintf("[%s] Checking cmd %s against %s\n", TimeStamp(), cmd, bb.ChannelData[channel].Command) switch cmd { - case "card": + case bb.ChannelData[channel].Command: 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) @@ -184,6 +185,15 @@ func (bb *KardBot) Login() { bb.conn.Write([]byte("NICK " + bb.Name + "\r\n")) } + +func (bb *KardBot) LeaveChannel(channels ...string) { + for _, channel := range channels { + rgb.YPrintf("[%s] Leaving #%s...\n", TimeStamp(), channel) + bb.conn.Write([]byte("PART #" + channel + "\r\n")) + rgb.YPrintf("[%s] Left #%s as @%s!\n", TimeStamp(), channel, bb.Name) + } +} + // Makes the bot join its pre-specified channel. func (bb *KardBot) JoinChannel(channels ...string) { if len(channels) == 0 { @@ -264,8 +274,8 @@ func (bb *KardBot) Start() { for { bb.Connect() bb.Login() - if len(bb.channelData) > 0 { - for channelName := range(bb.channelData) { + if len(bb.ChannelData) > 0 { + for channelName := range(bb.ChannelData) { bb.JoinChannel(channelName) } } else { @@ -288,15 +298,15 @@ func (bb *KardBot) readChannelData() error { records, err := bb.Database.ReadAll("channelData") if err != nil { // no db? initialise one? - record := ChannelData{Name: bb.Channel, JoinTime: time.Now()} - rgb.YPrintf("[%s] No channel data for #%s exists, creating...\n", TimeStamp(), bb.Channel) + record := ChannelData{Name: bb.Channel, JoinTime: time.Now(), Command: "card"} + rgb.YPrintf("[%s] No channel table for #%s exists, creating...\n", TimeStamp(), bb.Channel) if err := bb.Database.Write("channelData", bb.Channel, record); err != nil { return err } - bb.channelData = make(map[string]ChannelData) - bb.channelData[bb.Channel] = record; + bb.ChannelData = make(map[string]ChannelData) + bb.ChannelData[bb.Channel] = record; } else { - bb.channelData = make(map[string]ChannelData) + bb.ChannelData = make(map[string]ChannelData) } for _, data := range records { record := ChannelData{} @@ -304,8 +314,29 @@ func (bb *KardBot) readChannelData() error { if err != nil { return err } - bb.channelData[record.Name] = record + if record.Name != "" { + if record.Command == "" { + record.Command = "card" + + rgb.YPrintf("[%s] Rewriting data for #%s...\n", TimeStamp(), bb.Channel) + if err := bb.Database.Write("channelData", record.Name, record); err != nil { + return err + } + } + bb.ChannelData[record.Name] = record + } } + // Managed to leave the main channel!? + if bb.ChannelData[bb.Channel].Name == "" { + rgb.YPrintf("[%s] No channel data for #%s exists, creating...\n", TimeStamp(), bb.Channel) + record := ChannelData{Name: bb.Channel, JoinTime: time.Now(), Command: "card"} + bb.ChannelData[bb.Channel] = record + if err := bb.Database.Write("channelData", bb.Channel, record); err != nil { + return err + } + records, err = bb.Database.ReadAll("channelData") + } + rgb.YPrintf("[%s] Read channel data for %d channels\n", TimeStamp(), len(bb.ChannelData)) return nil } @@ -313,14 +344,14 @@ func (bb *KardBot) readOrCreateChannelKey(channel string) string { magicCode := "" var err error var record ChannelData - if record, ok := bb.channelData[channel]; !ok { + if record, ok := bb.ChannelData[channel]; !ok { rgb.YPrintf("[%s] No channel data for #%s exists, creating\n", TimeStamp(), channel) err = bb.Database.Read("channelData", channel, &record); if err == nil { - bb.channelData[channel] = record + bb.ChannelData[channel] = record } } - record = bb.channelData[channel] + record = bb.ChannelData[channel] if err != nil || record.AdminKey == "" { rgb.YPrintf("[%s] No channel key for #%s exists, creating one\n", TimeStamp(), channel) newuu, _ := uuid.NewRandom() @@ -332,7 +363,7 @@ func (bb *KardBot) readOrCreateChannelKey(channel string) string { if err := bb.Database.Write("channelData", channel, record); err != nil { rgb.RPrintf("[%s] Error writing channel data for #%s\n", TimeStamp(), channel) } - bb.channelData[record.Name] = record + bb.ChannelData[record.Name] = record rgb.YPrintf("[%s] Cached channel key for #%s\n", TimeStamp(), record.Name) } else { magicCode = record.AdminKey diff --git a/internal/webserver/webserver.go b/internal/webserver/webserver.go index 89ea4e1..afa09d5 100755 --- a/internal/webserver/webserver.go +++ b/internal/webserver/webserver.go @@ -17,7 +17,7 @@ import ( //var store = sessions.NewCookieStore(os.Getenv("SESSION_KEY")) -var ircBot irc.KardBot +var ircBot *irc.KardBot func HealthHandler(response http.ResponseWriter, request *http.Request) { response.Header().Add("Content-type", "text/plain") @@ -73,7 +73,7 @@ func TemplateHandler(response http.ResponseWriter, request *http.Request) { // NotFoundHandler(response, request) // return } - var td = TemplateData{ircBot.Prompts[rand.Intn(len(ircBot.Prompts))], len(ircBot.Prompts), 0, 0} + var td = TemplateData{ircBot.Prompts[rand.Intn(len(ircBot.Prompts))], len(ircBot.Prompts), len(ircBot.ChannelData), 0} err = tmpl.Execute(response, td) if err != nil { http.Error(response, err.Error(), http.StatusInternalServerError) @@ -81,19 +81,71 @@ func TemplateHandler(response http.ResponseWriter, request *http.Request) { } } -func AdminHandler(response http.ResponseWriter, request *http.Request) { - request.URL.Path = "/index.html" +func LeaveHandler(response http.ResponseWriter, request *http.Request) { + request.URL.Path = "/bye.html" TemplateHandler(response, request) } -func HandleHTTP(passedIrcBot irc.KardBot) { +func AdminHandler(response http.ResponseWriter, request *http.Request) { + vars := mux.Vars(request) + if vars["key"] != ircBot.ChannelData[vars["channel"]].AdminKey { + UnauthorizedHandler(response, request) + return + } + type TemplateData struct { + Channel string + Command string + ExtraStrings string + SinceTime time.Time + Leaving bool + } + channelData := ircBot.ChannelData[vars["channel"]] + var td = TemplateData{channelData.Name, channelData.Command, channelData.ExtraStrings, channelData.JoinTime, false} + + if request.Method == "POST" { + request.ParseForm() + if strings.Join(request.PostForm["leave"],",") == "Leave twitch channel" { + td.Leaving = true + } else if strings.Join(request.PostForm["reallyleave"],",") == "Really leave twitch channel" { + delete(ircBot.ChannelData,vars["channel"]) + ircBot.Database.Delete("channelData", vars["channel"]) + ircBot.LeaveChannel(vars["channel"]) + LeaveHandler(response, request) + return + } + sourceData := ircBot.ChannelData[vars["channel"]] + if strings.Join(request.PostForm["Command"],",") != "" { + sourceData.Command = strings.Join(request.PostForm["Command"],",") + td.Command = sourceData.Command + ircBot.ChannelData[vars["channel"]] = sourceData + } + if strings.Join(request.PostForm["ExtraStrings"],",") != sourceData.ExtraStrings { + sourceData.ExtraStrings = strings.Join(request.PostForm["ExtraStrings"],",") + td.ExtraStrings = sourceData.ExtraStrings + ircBot.ChannelData[vars["channel"]] = sourceData + } + ircBot.Database.Write("channelData", vars["channel"], sourceData); + } + tmpl := template.Must(template.ParseFiles("web/admin.html")) + tmpl.Execute(response, td) +} + +func UnauthorizedHandler(response http.ResponseWriter, request *http.Request) { + response.Header().Add("X-Template-File", "html"+request.URL.Path) + response.WriteHeader(401) + tmpl := template.Must(template.ParseFiles("web/401.html")) + tmpl.Execute(response, nil) +} + +func HandleHTTP(passedIrcBot *irc.KardBot) { ircBot = passedIrcBot r := mux.NewRouter() loggedRouter := handlers.LoggingHandler(os.Stdout, r) r.NotFoundHandler = http.HandlerFunc(NotFoundHandler) r.HandleFunc("/", RootHandler) r.HandleFunc("/healthz", HealthHandler) - r.HandleFunc("/example/{.*}", TemplateHandler) + r.HandleFunc("/web/{.*}", TemplateHandler) + r.PathPrefix("/static/").Handler(http.FileServer(http.Dir("./web/"))) r.HandleFunc("/cover.css", CSSHandler) r.HandleFunc("/admin/{channel}/{key}", AdminHandler) http.Handle("/", r) diff --git a/main.go b/main.go index 89c4225..1996938 100755 --- a/main.go +++ b/main.go @@ -208,7 +208,7 @@ func main() { } go func() { rgb.YPrintf("[%s] Starting webserver on port %s\n", irc.TimeStamp(), "5353") - webserver.HandleHTTP(myBot) + webserver.HandleHTTP(&myBot) }() myBot.Start() } diff --git a/web/401.html b/web/401.html new file mode 100755 index 0000000..80bc8a8 --- /dev/null +++ b/web/401.html @@ -0,0 +1,107 @@ + + + + + + + + + The great unknown! + + + + + + + + + +
+
+
+

k8s-zoo

+ +
+
+
+

Scary user alert!

+ Cat sat outside a door that has a sign depictinging no cats allowed +

It seems you've gone somewhere you shouldn't! 401 NOT AUTHORIZED!

+

+

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!

+
+ +
+ + + + + \ No newline at end of file diff --git a/web/admin.html b/web/admin.html new file mode 100755 index 0000000..4bb4a0f --- /dev/null +++ b/web/admin.html @@ -0,0 +1,136 @@ + + + + + + + + + Karaokards + + + + + + + + + +
+
+
+

Karaokards

+ +
+
+
+ + +

Karaokards admin panel for {{.Channel}}!!!

+
+ {{ if .Leaving }} +

Do you really want this bot to leave your channel? Right now you would have to ask Martyn to re-add it.

+

+ {{ else }} + + + + + + + + + + +
Channel Data :
Member of channel since {{.SinceTime}}
Command for prompt:{{.Command}}
Extra prompts (one per line):{{.ExtraStrings}}
 
Or... please don't go but...
+ {{ end }} +
+
+ +
+ + + + \ No newline at end of file diff --git a/web/bye.html b/web/bye.html new file mode 100755 index 0000000..093bed8 --- /dev/null +++ b/web/bye.html @@ -0,0 +1,75 @@ + + + + + + + + + Karaokards + + + + + + + + + +
+
+
+

Karaokards

+ +
+
+
+

Left channel!!!

+

animation of dissappointed sister from Frozen saying Okay, bye...

+
+ +
+ + + + \ No newline at end of file diff --git a/web/static/okaybye.gif b/web/static/okaybye.gif new file mode 100755 index 0000000..2267da9 Binary files /dev/null and b/web/static/okaybye.gif differ