mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-12-20 20:01:17 +00:00
253 lines
7 KiB
Go
253 lines
7 KiB
Go
package quotedb
|
|
|
|
import (
|
|
_ "embed"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/gorilla/mux"
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/Luzifer/twitch-bot/v3/plugins"
|
|
)
|
|
|
|
var (
|
|
//go:embed list.html
|
|
listFrontend []byte
|
|
//go:embed list.js
|
|
listScript []byte
|
|
)
|
|
|
|
//nolint:funlen
|
|
func registerAPI(register plugins.HTTPRouteRegistrationFunc) (err error) {
|
|
if err = register(plugins.HTTPRouteRegistrationArgs{
|
|
HandlerFunc: handleScript,
|
|
Method: http.MethodGet,
|
|
Module: "quotedb",
|
|
Path: "/app.js",
|
|
SkipDocumentation: true,
|
|
}); err != nil {
|
|
return fmt.Errorf("registering API route: %w", err)
|
|
}
|
|
|
|
if err = register(plugins.HTTPRouteRegistrationArgs{
|
|
Description: "Add quotes for the given {channel}",
|
|
HandlerFunc: handleAddQuotes,
|
|
Method: http.MethodPost,
|
|
Module: "quotedb",
|
|
Name: "Add Quotes",
|
|
Path: "/{channel}",
|
|
RequiresWriteAuth: true,
|
|
ResponseType: plugins.HTTPRouteResponseTypeTextPlain,
|
|
RouteParams: []plugins.HTTPRouteParamDocumentation{
|
|
{
|
|
Description: "Channel to delete the quote in",
|
|
Name: "channel",
|
|
},
|
|
},
|
|
}); err != nil {
|
|
return fmt.Errorf("registering API route: %w", err)
|
|
}
|
|
|
|
if err = register(plugins.HTTPRouteRegistrationArgs{
|
|
Description: "Deletes quote with given {idx} from {channel}",
|
|
HandlerFunc: handleDeleteQuote,
|
|
Method: http.MethodDelete,
|
|
Module: "quotedb",
|
|
Name: "Delete Quote",
|
|
Path: "/{channel}/{idx:[0-9]+}",
|
|
RequiresWriteAuth: true,
|
|
ResponseType: plugins.HTTPRouteResponseTypeTextPlain,
|
|
RouteParams: []plugins.HTTPRouteParamDocumentation{
|
|
{
|
|
Description: "Channel to delete the quote in",
|
|
Name: "channel",
|
|
},
|
|
{
|
|
Description: "Index of the quote to delete",
|
|
Name: "idx",
|
|
},
|
|
},
|
|
}); err != nil {
|
|
return fmt.Errorf("registering API route: %w", err)
|
|
}
|
|
|
|
if err = register(plugins.HTTPRouteRegistrationArgs{
|
|
Accept: []string{"application/json", "text/html"},
|
|
Description: "Lists all quotes for the given {channel}",
|
|
HandlerFunc: handleListQuotes,
|
|
Method: http.MethodGet,
|
|
Module: "quotedb",
|
|
Name: "List Quotes",
|
|
Path: "/{channel}",
|
|
ResponseType: plugins.HTTPRouteResponseTypeMultiple,
|
|
RouteParams: []plugins.HTTPRouteParamDocumentation{
|
|
{
|
|
Description: "Channel to delete the quote in",
|
|
Name: "channel",
|
|
},
|
|
},
|
|
}); err != nil {
|
|
return fmt.Errorf("registering API route: %w", err)
|
|
}
|
|
|
|
if err = register(plugins.HTTPRouteRegistrationArgs{
|
|
Description: "Set quotes for the given {channel} (will overwrite ALL quotes!)",
|
|
HandlerFunc: handleReplaceQuotes,
|
|
Method: http.MethodPut,
|
|
Module: "quotedb",
|
|
Name: "Set Quotes",
|
|
Path: "/{channel}",
|
|
RequiresWriteAuth: true,
|
|
ResponseType: plugins.HTTPRouteResponseTypeTextPlain,
|
|
RouteParams: []plugins.HTTPRouteParamDocumentation{
|
|
{
|
|
Description: "Channel to delete the quote in",
|
|
Name: "channel",
|
|
},
|
|
},
|
|
}); err != nil {
|
|
return fmt.Errorf("registering API route: %w", err)
|
|
}
|
|
|
|
if err = register(plugins.HTTPRouteRegistrationArgs{
|
|
Description: "Updates quote with given {idx} from {channel}",
|
|
HandlerFunc: handleUpdateQuote,
|
|
Method: http.MethodPut,
|
|
Module: "quotedb",
|
|
Name: "Update Quote",
|
|
Path: "/{channel}/{idx:[0-9]+}",
|
|
RequiresWriteAuth: true,
|
|
ResponseType: plugins.HTTPRouteResponseTypeTextPlain,
|
|
RouteParams: []plugins.HTTPRouteParamDocumentation{
|
|
{
|
|
Description: "Channel to delete the quote in",
|
|
Name: "channel",
|
|
},
|
|
{
|
|
Description: "Index of the quote to delete",
|
|
Name: "idx",
|
|
},
|
|
},
|
|
}); err != nil {
|
|
return fmt.Errorf("registering API route: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func handleAddQuotes(w http.ResponseWriter, r *http.Request) {
|
|
channel := "#" + strings.TrimLeft(mux.Vars(r)["channel"], "#")
|
|
|
|
var quotes []string
|
|
if err := json.NewDecoder(r.Body).Decode("es); err != nil {
|
|
http.Error(w, errors.Wrap(err, "parsing input").Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
for _, q := range quotes {
|
|
if err := addQuote(db, channel, q); err != nil {
|
|
http.Error(w, errors.Wrap(err, "adding quote").Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
w.WriteHeader(http.StatusCreated)
|
|
}
|
|
|
|
func handleDeleteQuote(w http.ResponseWriter, r *http.Request) {
|
|
var (
|
|
channel = "#" + strings.TrimLeft(mux.Vars(r)["channel"], "#")
|
|
idxStr = mux.Vars(r)["idx"]
|
|
)
|
|
|
|
idx, err := strconv.Atoi(idxStr)
|
|
if err != nil {
|
|
http.Error(w, errors.Wrap(err, "parsing index").Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err = delQuote(db, channel, idx); err != nil {
|
|
http.Error(w, errors.Wrap(err, "deleting quote").Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
func handleListQuotes(w http.ResponseWriter, r *http.Request) {
|
|
if strings.HasPrefix(r.Header.Get("Accept"), "text/html") {
|
|
w.Header().Set("Content-Type", "text/html")
|
|
w.Write(listFrontend) //nolint:errcheck,gosec,revive
|
|
return
|
|
}
|
|
|
|
channel := "#" + strings.TrimLeft(mux.Vars(r)["channel"], "#")
|
|
|
|
quotes, err := getChannelQuotes(db, channel)
|
|
if err != nil {
|
|
http.Error(w, errors.Wrap(err, "getting quotes").Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if err = json.NewEncoder(w).Encode(quotes); err != nil {
|
|
http.Error(w, errors.Wrap(err, "enocding quote list").Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
}
|
|
|
|
func handleReplaceQuotes(w http.ResponseWriter, r *http.Request) {
|
|
channel := "#" + strings.TrimLeft(mux.Vars(r)["channel"], "#")
|
|
|
|
var quotes []string
|
|
if err := json.NewDecoder(r.Body).Decode("es); err != nil {
|
|
http.Error(w, errors.Wrap(err, "parsing input").Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := setQuotes(db, channel, quotes); err != nil {
|
|
http.Error(w, errors.Wrap(err, "replacing quotes").Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
func handleScript(w http.ResponseWriter, _ *http.Request) {
|
|
w.Header().Set("Content-Type", "text/javascript")
|
|
w.Write(listScript) //nolint:errcheck,gosec,revive
|
|
}
|
|
|
|
func handleUpdateQuote(w http.ResponseWriter, r *http.Request) {
|
|
var (
|
|
channel = "#" + strings.TrimLeft(mux.Vars(r)["channel"], "#")
|
|
idxStr = mux.Vars(r)["idx"]
|
|
)
|
|
|
|
idx, err := strconv.Atoi(idxStr)
|
|
if err != nil {
|
|
http.Error(w, errors.Wrap(err, "parsing index").Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var quotes []string
|
|
if err := json.NewDecoder(r.Body).Decode("es); err != nil {
|
|
http.Error(w, errors.Wrap(err, "parsing input").Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if len(quotes) != 1 {
|
|
http.Error(w, "input must be list with one quote", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err = updateQuote(db, channel, idx, quotes[0]); err != nil {
|
|
http.Error(w, errors.Wrap(err, "updating quote").Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|