Admin panel with leave option
Signed-off-by: Martyn Ranyard <m@rtyn.berlin>
This commit is contained in:
parent
3950f8b672
commit
4803122aad
|
@ -55,13 +55,13 @@ type KardBot struct {
|
||||||
startTime time.Time
|
startTime time.Time
|
||||||
Prompts []string
|
Prompts []string
|
||||||
Database scribble.Driver
|
Database scribble.Driver
|
||||||
channelData map[string]ChannelData
|
ChannelData map[string]ChannelData
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChannelData struct {
|
type ChannelData struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
AdminKey string `json:"value,omitempty"`
|
AdminKey string `json:"value,omitempty"`
|
||||||
CustomCommand string `json:"customcommand,omitempty"`
|
Command string `json:"customcommand,omitempty"`
|
||||||
ExtraStrings string `json:"extrastrings,omitempty"`
|
ExtraStrings string `json:"extrastrings,omitempty"`
|
||||||
JoinTime time.Time `json:"jointime"`
|
JoinTime time.Time `json:"jointime"`
|
||||||
}
|
}
|
||||||
|
@ -136,8 +136,9 @@ func (bb *KardBot) HandleChat() error {
|
||||||
if nil != cmdMatches {
|
if nil != cmdMatches {
|
||||||
cmd := cmdMatches[1]
|
cmd := cmdMatches[1]
|
||||||
|
|
||||||
|
rgb.YPrintf("[%s] Checking cmd %s against %s\n", TimeStamp(), cmd, bb.ChannelData[channel].Command)
|
||||||
switch cmd {
|
switch cmd {
|
||||||
case "card":
|
case bb.ChannelData[channel].Command:
|
||||||
rgb.CPrintf("[%s] Card asked for by %s on %s' channel!\n", TimeStamp(), userName, channel)
|
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)
|
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"))
|
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.
|
// Makes the bot join its pre-specified channel.
|
||||||
func (bb *KardBot) JoinChannel(channels ...string) {
|
func (bb *KardBot) JoinChannel(channels ...string) {
|
||||||
if len(channels) == 0 {
|
if len(channels) == 0 {
|
||||||
|
@ -264,8 +274,8 @@ func (bb *KardBot) Start() {
|
||||||
for {
|
for {
|
||||||
bb.Connect()
|
bb.Connect()
|
||||||
bb.Login()
|
bb.Login()
|
||||||
if len(bb.channelData) > 0 {
|
if len(bb.ChannelData) > 0 {
|
||||||
for channelName := range(bb.channelData) {
|
for channelName := range(bb.ChannelData) {
|
||||||
bb.JoinChannel(channelName)
|
bb.JoinChannel(channelName)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -288,15 +298,15 @@ func (bb *KardBot) readChannelData() error {
|
||||||
records, err := bb.Database.ReadAll("channelData")
|
records, err := bb.Database.ReadAll("channelData")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// no db? initialise one?
|
// no db? initialise one?
|
||||||
record := ChannelData{Name: bb.Channel, JoinTime: time.Now()}
|
record := ChannelData{Name: bb.Channel, JoinTime: time.Now(), Command: "card"}
|
||||||
rgb.YPrintf("[%s] No channel data for #%s exists, creating...\n", TimeStamp(), bb.Channel)
|
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 {
|
if err := bb.Database.Write("channelData", bb.Channel, record); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
bb.channelData = make(map[string]ChannelData)
|
bb.ChannelData = make(map[string]ChannelData)
|
||||||
bb.channelData[bb.Channel] = record;
|
bb.ChannelData[bb.Channel] = record;
|
||||||
} else {
|
} else {
|
||||||
bb.channelData = make(map[string]ChannelData)
|
bb.ChannelData = make(map[string]ChannelData)
|
||||||
}
|
}
|
||||||
for _, data := range records {
|
for _, data := range records {
|
||||||
record := ChannelData{}
|
record := ChannelData{}
|
||||||
|
@ -304,8 +314,29 @@ func (bb *KardBot) readChannelData() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,14 +344,14 @@ func (bb *KardBot) readOrCreateChannelKey(channel string) string {
|
||||||
magicCode := ""
|
magicCode := ""
|
||||||
var err error
|
var err error
|
||||||
var record ChannelData
|
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)
|
rgb.YPrintf("[%s] No channel data for #%s exists, creating\n", TimeStamp(), channel)
|
||||||
err = bb.Database.Read("channelData", channel, &record);
|
err = bb.Database.Read("channelData", channel, &record);
|
||||||
if err == nil {
|
if err == nil {
|
||||||
bb.channelData[channel] = record
|
bb.ChannelData[channel] = record
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
record = bb.channelData[channel]
|
record = bb.ChannelData[channel]
|
||||||
if err != nil || record.AdminKey == "" {
|
if err != nil || record.AdminKey == "" {
|
||||||
rgb.YPrintf("[%s] No channel key for #%s exists, creating one\n", TimeStamp(), channel)
|
rgb.YPrintf("[%s] No channel key for #%s exists, creating one\n", TimeStamp(), channel)
|
||||||
newuu, _ := uuid.NewRandom()
|
newuu, _ := uuid.NewRandom()
|
||||||
|
@ -332,7 +363,7 @@ func (bb *KardBot) readOrCreateChannelKey(channel string) string {
|
||||||
if err := bb.Database.Write("channelData", channel, record); err != nil {
|
if err := bb.Database.Write("channelData", channel, record); err != nil {
|
||||||
rgb.RPrintf("[%s] Error writing channel data for #%s\n", TimeStamp(), channel)
|
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)
|
rgb.YPrintf("[%s] Cached channel key for #%s\n", TimeStamp(), record.Name)
|
||||||
} else {
|
} else {
|
||||||
magicCode = record.AdminKey
|
magicCode = record.AdminKey
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
|
|
||||||
//var store = sessions.NewCookieStore(os.Getenv("SESSION_KEY"))
|
//var store = sessions.NewCookieStore(os.Getenv("SESSION_KEY"))
|
||||||
|
|
||||||
var ircBot irc.KardBot
|
var ircBot *irc.KardBot
|
||||||
|
|
||||||
func HealthHandler(response http.ResponseWriter, request *http.Request) {
|
func HealthHandler(response http.ResponseWriter, request *http.Request) {
|
||||||
response.Header().Add("Content-type", "text/plain")
|
response.Header().Add("Content-type", "text/plain")
|
||||||
|
@ -73,7 +73,7 @@ func TemplateHandler(response http.ResponseWriter, request *http.Request) {
|
||||||
// NotFoundHandler(response, request)
|
// NotFoundHandler(response, request)
|
||||||
// return
|
// 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)
|
err = tmpl.Execute(response, td)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(response, err.Error(), http.StatusInternalServerError)
|
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) {
|
func LeaveHandler(response http.ResponseWriter, request *http.Request) {
|
||||||
request.URL.Path = "/index.html"
|
request.URL.Path = "/bye.html"
|
||||||
TemplateHandler(response, request)
|
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
|
ircBot = passedIrcBot
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
loggedRouter := handlers.LoggingHandler(os.Stdout, r)
|
loggedRouter := handlers.LoggingHandler(os.Stdout, r)
|
||||||
r.NotFoundHandler = http.HandlerFunc(NotFoundHandler)
|
r.NotFoundHandler = http.HandlerFunc(NotFoundHandler)
|
||||||
r.HandleFunc("/", RootHandler)
|
r.HandleFunc("/", RootHandler)
|
||||||
r.HandleFunc("/healthz", HealthHandler)
|
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("/cover.css", CSSHandler)
|
||||||
r.HandleFunc("/admin/{channel}/{key}", AdminHandler)
|
r.HandleFunc("/admin/{channel}/{key}", AdminHandler)
|
||||||
http.Handle("/", r)
|
http.Handle("/", r)
|
||||||
|
|
2
main.go
2
main.go
|
@ -208,7 +208,7 @@ func main() {
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
rgb.YPrintf("[%s] Starting webserver on port %s\n", irc.TimeStamp(), "5353")
|
rgb.YPrintf("[%s] Starting webserver on port %s\n", irc.TimeStamp(), "5353")
|
||||||
webserver.HandleHTTP(myBot)
|
webserver.HandleHTTP(&myBot)
|
||||||
}()
|
}()
|
||||||
myBot.Start()
|
myBot.Start()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
<html>
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="Karaokards">
|
||||||
|
<meta name="author" content="Martyn Ranyard">
|
||||||
|
<title>The great unknown!</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="/cover.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.bd-placeholder-img {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
text-anchor: middle;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.bd-placeholder-img-lg {
|
||||||
|
font-size: 3.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
li.match-nomatch{
|
||||||
|
background-color: #1e2122;
|
||||||
|
}
|
||||||
|
li.match-matchtrack{
|
||||||
|
background-color: #E9B000;
|
||||||
|
}
|
||||||
|
li.match-fullmatch{
|
||||||
|
background-color: #008F95;
|
||||||
|
}
|
||||||
|
li.match-matchtrackfuzzt{
|
||||||
|
background-color: darkgray;
|
||||||
|
}
|
||||||
|
li.match-fullmatchfuzzy{
|
||||||
|
background-color: darkgray;
|
||||||
|
}
|
||||||
|
a{
|
||||||
|
text-decoration-line: underline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="text-center">
|
||||||
|
<div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column">
|
||||||
|
<header class="masthead mb-auto">
|
||||||
|
<div class="inner">
|
||||||
|
<h3 class="masthead-brand">k8s-zoo</h3>
|
||||||
|
<nav class="nav nav-masthead justify-content-center">
|
||||||
|
<a class="nav-link active" href="/">Home</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<main role="main" class="inner cover">
|
||||||
|
<h1 class="cover-heading">Scary user alert!</h1>
|
||||||
|
<img src="https://http.cat/401" alt="Cat sat outside a door that has a sign depictinging no cats allowed" />
|
||||||
|
<p>It seems you've gone somewhere you shouldn't! 401 NOT AUTHORIZED!</p>
|
||||||
|
<p/>
|
||||||
|
<p>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.</p>
|
||||||
|
<p>Shameless self-promotion : Follow me on twitch - <a href="https://www.twitch.tv/iMartynOnTwitch">iMartynOnTwitch</a>, oddly enough, I do a lot of twitchsings!</p>
|
||||||
|
</main>
|
||||||
|
<footer class="mastfoot mt-auto">
|
||||||
|
<div class="inner">
|
||||||
|
<p>Cover template for <a href="https://getbootstrap.com/">Bootstrap</a>, by <a href="https://twitter.com/mdo">@mdo</a>.</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
function directToResults() {
|
||||||
|
var url = document.createElement('a');
|
||||||
|
url.setAttribute("href", window.location.href);
|
||||||
|
if ((url.port != 80) && (url.port != 443)) {
|
||||||
|
customPort = ":"+url.port
|
||||||
|
} else {
|
||||||
|
customPort = ""
|
||||||
|
}
|
||||||
|
var destination = url.protocol + "//" + url.hostname + customPort + "/" + document.getElementById("mode").value + "/" + document.getElementById("spotifyid").value
|
||||||
|
window.location.href = destination
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleUnfound() {
|
||||||
|
var unmatched = document.getElementsByClassName('match-nomatch'), i;
|
||||||
|
if (document.getElementById("showhidebutton").getAttribute("tracksHidden") != "true") {
|
||||||
|
document.getElementById("showhidebutton").setAttribute("tracksHidden","true")
|
||||||
|
for (i = 0; i < unmatched.length; i += 1) {
|
||||||
|
unmatched[i].style.display = 'none';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
document.getElementById("showhidebutton").setAttribute("tracksHidden","false")
|
||||||
|
for (i = 0; i < unmatched.length; i += 1) {
|
||||||
|
unmatched[i].style.display = 'list-item';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,136 @@
|
||||||
|
<html>
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="Karaokards bot for twitch chat">
|
||||||
|
<meta name="author" content="Martyn Ranyard">
|
||||||
|
<title>Karaokards</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="/cover.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.bd-placeholder-img {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
text-anchor: middle;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.bd-placeholder-img-lg {
|
||||||
|
font-size: 3.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
li.match-nomatch{
|
||||||
|
background-color: #1e2122;
|
||||||
|
}
|
||||||
|
li.match-matchtrack{
|
||||||
|
background-color: #E9B000;
|
||||||
|
}
|
||||||
|
li.match-fullmatch{
|
||||||
|
background-color: #008F95;
|
||||||
|
}
|
||||||
|
li.match-matchtrackfuzzt{
|
||||||
|
background-color: darkgray;
|
||||||
|
}
|
||||||
|
li.match-fullmatchfuzzy{
|
||||||
|
background-color: darkgray;
|
||||||
|
}
|
||||||
|
a{
|
||||||
|
text-decoration-line: underline;
|
||||||
|
}
|
||||||
|
.displaySetting{
|
||||||
|
display: inline
|
||||||
|
}
|
||||||
|
.hiddenDisplaySetting{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.hiddenSave {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.editSetting{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.visibleEditSetting{
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.visibleSave {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="text-center">
|
||||||
|
<div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column">
|
||||||
|
<header class="masthead mb-auto">
|
||||||
|
<div class="inner">
|
||||||
|
<h3 class="masthead-brand">Karaokards</h3>
|
||||||
|
<nav class="nav nav-masthead justify-content-center">
|
||||||
|
<a class="nav-link active" href="/">Home</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<main role="main" class="inner cover">
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function editMode() {
|
||||||
|
var alldisps = document.getElementsByClassName("displaySetting");
|
||||||
|
for (item of alldisps) {
|
||||||
|
item.classList.add("hiddenDisplaySetting")
|
||||||
|
}
|
||||||
|
for (item of alldisps) {
|
||||||
|
item.classList.remove("displaySetting")
|
||||||
|
}
|
||||||
|
var alldisps = document.getElementsByClassName("editSetting");
|
||||||
|
for (item of alldisps) {
|
||||||
|
item.classList.add("visibleEditSetting")
|
||||||
|
}
|
||||||
|
for (item of alldisps) {
|
||||||
|
item.classList.remove("editSetting")
|
||||||
|
}
|
||||||
|
document.getElementById("saveButton").classList.remove("hiddenSave")
|
||||||
|
document.getElementById("saveButton").classList.add("visibleSave")
|
||||||
|
document.getElementById("leaveButton").classList.remove("hiddenSave")
|
||||||
|
document.getElementById("leaveButton").classList.add("visibleSave")
|
||||||
|
document.getElementById("yuhateme").classList.remove("hiddenSave")
|
||||||
|
document.getElementById("yuhateme").classList.add("visibleSave")
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<h1 class="cover-heading">Karaokards admin panel for {{.Channel}}!!!</h1>
|
||||||
|
<form method="POST">
|
||||||
|
{{ if .Leaving }}
|
||||||
|
<h2>Do you really want this bot to leave your channel? Right now you would have to ask Martyn to re-add it.</h2>
|
||||||
|
<p><input id="leaveButton" type="submit" name="reallyleave" value="Really leave twitch channel"></p>
|
||||||
|
{{ else }}
|
||||||
|
<table>
|
||||||
|
<thead><tr><td>Channel Data :</td><td><input type="button" value="Edit" onclick="javascript:editMode();"></td></tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>Member of channel since {{.SinceTime}}</td></tr>
|
||||||
|
<tr><td>Command for prompt:</td><td class="displaySetting"></tdclass>{{.Command}}</td><td class="editSetting"><input type="text" name="Command" value="{{.Command}}"></td></tr>
|
||||||
|
<tr><td>Extra prompts (one per line):</td><td class="displaySetting">{{.ExtraStrings}}</td><td class="editSetting"><textarea name="ExtraStrings" >{{.ExtraStrings}}</textarea></td></tr>
|
||||||
|
<tr><td> </td><td><input id="saveButton" type="submit" class="hiddenSave" name="save" value="Save changes"></td></tr>
|
||||||
|
<tr id="yuhateme" class="hiddenSave"><td>Or... please don't go but...</td></tr>
|
||||||
|
<tr><td><input id="leaveButton" type="submit" class="hiddenSave" name="leave" value="Leave twitch channel"></td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{{ end }}
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
<footer class="mastfoot mt-auto">
|
||||||
|
<div class="inner">
|
||||||
|
<p>Cover template for <a href="https://getbootstrap.com/">Bootstrap</a>, by <a href="https://twitter.com/mdo">@mdo</a>.</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,75 @@
|
||||||
|
<html>
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="Karaokards bot for twitch chat">
|
||||||
|
<meta name="author" content="Martyn Ranyard">
|
||||||
|
<title>Karaokards</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="/cover.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.bd-placeholder-img {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
text-anchor: middle;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.bd-placeholder-img-lg {
|
||||||
|
font-size: 3.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
li.match-nomatch{
|
||||||
|
background-color: #1e2122;
|
||||||
|
}
|
||||||
|
li.match-matchtrack{
|
||||||
|
background-color: #E9B000;
|
||||||
|
}
|
||||||
|
li.match-fullmatch{
|
||||||
|
background-color: #008F95;
|
||||||
|
}
|
||||||
|
li.match-matchtrackfuzzt{
|
||||||
|
background-color: darkgray;
|
||||||
|
}
|
||||||
|
li.match-fullmatchfuzzy{
|
||||||
|
background-color: darkgray;
|
||||||
|
}
|
||||||
|
a{
|
||||||
|
text-decoration-line: underline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="text-center">
|
||||||
|
<div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column">
|
||||||
|
<header class="masthead mb-auto">
|
||||||
|
<div class="inner">
|
||||||
|
<h3 class="masthead-brand">Karaokards</h3>
|
||||||
|
<nav class="nav nav-masthead justify-content-center">
|
||||||
|
<a class="nav-link active" href="/">Home</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<main role="main" class="inner cover">
|
||||||
|
<h1 class="cover-heading">Left channel!!!</h1>
|
||||||
|
<p><img src="/static/okaybye.gif" alt="animation of dissappointed sister from Frozen saying Okay, bye..."/></p>
|
||||||
|
</main>
|
||||||
|
<footer class="mastfoot mt-auto">
|
||||||
|
<div class="inner">
|
||||||
|
<p>Cover template for <a href="https://getbootstrap.com/">Bootstrap</a>, by <a href="https://twitter.com/mdo">@mdo</a>.</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
</body>
|
||||||
|
</html>
|
Binary file not shown.
After Width: | Height: | Size: 263 KiB |
Loading…
Reference in New Issue