mirror of https://github.com/velour/catbase.git
web: refactor and convert secrets
This commit is contained in:
parent
3e3cc3cf95
commit
f83cc32788
60
bot/bot.go
60
bot/bot.go
|
@ -4,10 +4,8 @@ package bot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-chi/chi/v5/middleware"
|
"github.com/velour/catbase/bot/web"
|
||||||
"github.com/go-chi/httprate"
|
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -15,7 +13,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/velour/catbase/bot/history"
|
"github.com/velour/catbase/bot/history"
|
||||||
|
@ -53,8 +50,7 @@ type bot struct {
|
||||||
|
|
||||||
version string
|
version string
|
||||||
|
|
||||||
// The entries to the bot's HTTP interface
|
web *web.Web
|
||||||
httpEndPoints []EndPoint
|
|
||||||
|
|
||||||
// filters registered by plugins
|
// filters registered by plugins
|
||||||
filters map[string]func(string) string
|
filters map[string]func(string) string
|
||||||
|
@ -66,16 +62,9 @@ type bot struct {
|
||||||
|
|
||||||
quiet bool
|
quiet bool
|
||||||
|
|
||||||
router *chi.Mux
|
|
||||||
|
|
||||||
history *history.History
|
history *history.History
|
||||||
}
|
}
|
||||||
|
|
||||||
type EndPoint struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
URL string `json:"url"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variable represents a $var replacement
|
// Variable represents a $var replacement
|
||||||
type Variable struct {
|
type Variable struct {
|
||||||
Variable, Value string
|
Variable, Value string
|
||||||
|
@ -107,10 +96,8 @@ func New(config *config.Config, connector Connector) Bot {
|
||||||
me: users[0],
|
me: users[0],
|
||||||
logIn: logIn,
|
logIn: logIn,
|
||||||
logOut: logOut,
|
logOut: logOut,
|
||||||
httpEndPoints: make([]EndPoint, 0),
|
|
||||||
filters: make(map[string]func(string) string),
|
filters: make(map[string]func(string) string),
|
||||||
callbacks: make(CallbackMap),
|
callbacks: make(CallbackMap),
|
||||||
router: chi.NewRouter(),
|
|
||||||
history: history.New(historySz),
|
history: history.New(historySz),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,60 +106,25 @@ func New(config *config.Config, connector Connector) Bot {
|
||||||
bot.RefreshPluginBlacklist()
|
bot.RefreshPluginBlacklist()
|
||||||
bot.RefreshPluginWhitelist()
|
bot.RefreshPluginWhitelist()
|
||||||
|
|
||||||
log.Debug().Msgf("created web router")
|
bot.web = web.New(bot.config)
|
||||||
|
|
||||||
bot.setupHTTP()
|
|
||||||
|
|
||||||
connector.RegisterEvent(bot.Receive)
|
connector.RegisterEvent(bot.Receive)
|
||||||
|
|
||||||
return bot
|
return bot
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bot) setupHTTP() {
|
|
||||||
// Make the http logger optional
|
|
||||||
// It has never served a purpose in production and with the emojy page, can make a rather noisy log
|
|
||||||
if b.Config().GetInt("bot.useLogger", 0) == 1 {
|
|
||||||
b.router.Use(middleware.Logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
reqCount := b.Config().GetInt("bot.httprate.requests", 500)
|
|
||||||
reqTime := time.Duration(b.Config().GetInt("bot.httprate.seconds", 5))
|
|
||||||
if reqCount > 0 && reqTime > 0 {
|
|
||||||
b.router.Use(httprate.LimitByIP(reqCount, reqTime*time.Second))
|
|
||||||
}
|
|
||||||
|
|
||||||
b.router.Use(middleware.RequestID)
|
|
||||||
b.router.Use(middleware.Recoverer)
|
|
||||||
b.router.Use(middleware.StripSlashes)
|
|
||||||
|
|
||||||
b.router.HandleFunc("/", b.serveRoot)
|
|
||||||
b.router.HandleFunc("/nav", b.serveNav)
|
|
||||||
b.router.HandleFunc("/navHTML", b.serveNavHTML)
|
|
||||||
b.router.HandleFunc("/navHTML/{currentPage}", b.serveNavHTML)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bot) ListenAndServe() {
|
func (b *bot) ListenAndServe() {
|
||||||
addr := b.config.Get("HttpAddr", "127.0.0.1:1337")
|
addr := b.config.Get("HttpAddr", "127.0.0.1:1337")
|
||||||
stop := make(chan os.Signal, 1)
|
stop := make(chan os.Signal, 1)
|
||||||
signal.Notify(stop, os.Interrupt)
|
signal.Notify(stop, os.Interrupt)
|
||||||
go func() {
|
go func() {
|
||||||
log.Debug().Msgf("starting web service at %s", addr)
|
b.web.ListenAndServe(addr)
|
||||||
log.Fatal().Err(http.ListenAndServe(addr, b.router)).Msg("bot killed")
|
|
||||||
}()
|
}()
|
||||||
<-stop
|
<-stop
|
||||||
b.DefaultConnector().Shutdown()
|
b.DefaultConnector().Shutdown()
|
||||||
b.Receive(b.DefaultConnector(), Shutdown, msg.Message{})
|
b.Receive(b.DefaultConnector(), Shutdown, msg.Message{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bot) RegisterWeb(r http.Handler, root string) {
|
|
||||||
b.router.Mount(root, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bot) RegisterWebName(r http.Handler, root, name string) {
|
|
||||||
b.httpEndPoints = append(b.httpEndPoints, EndPoint{name, root})
|
|
||||||
b.router.Mount(root, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultConnector is the main connector used for the bot
|
// DefaultConnector is the main connector used for the bot
|
||||||
// If more than one connector is on, some users may not see all messages if this is used.
|
// If more than one connector is on, some users may not see all messages if this is used.
|
||||||
// Usage should be limited to out-of-band communications such as timed messages.
|
// Usage should be limited to out-of-band communications such as timed messages.
|
||||||
|
@ -458,3 +410,7 @@ func (b *bot) CheckPassword(secret, password string) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *bot) GetWeb() *web.Web {
|
||||||
|
return b.web
|
||||||
|
}
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
package bot
|
|
||||||
|
|
||||||
templ (b *bot) index() {
|
|
||||||
<!DOCTYPE html />
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<!-- Load required Bootstrap and BootstrapVue CSS -->
|
|
||||||
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>catbase</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div id="app">
|
|
||||||
@b.Nav("", b.GetWebNavigation())
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="//unpkg.com/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.2.543
|
|
||||||
package bot
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import "context"
|
|
||||||
import "io"
|
|
||||||
import "bytes"
|
|
||||||
|
|
||||||
func (b *bot) index() templ.Component {
|
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
|
||||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html /><html lang=\"en\"><head><!-- Load required Bootstrap and BootstrapVue CSS --><link type=\"text/css\" rel=\"stylesheet\" href=\"//unpkg.com/bootstrap/dist/css/bootstrap.min.css\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><meta charset=\"UTF-8\"><title>catbase</title></head><body><div id=\"app\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = b.Nav("", b.GetWebNavigation()).Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><script src=\"//unpkg.com/bootstrap/dist/js/bootstrap.bundle.min.js\"></script></body></html>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
|
||||||
}
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -4,6 +4,7 @@ package bot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gabriel-vasile/mimetype"
|
"github.com/gabriel-vasile/mimetype"
|
||||||
|
"github.com/velour/catbase/bot/web"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -168,20 +169,14 @@ type Bot interface {
|
||||||
// RegisterFilter creates a filter function for message processing
|
// RegisterFilter creates a filter function for message processing
|
||||||
RegisterFilter(string, func(string) string)
|
RegisterFilter(string, func(string) string)
|
||||||
|
|
||||||
// RegisterWeb records a web endpoint for the UI
|
|
||||||
RegisterWebName(http.Handler, string, string)
|
|
||||||
|
|
||||||
// RegisterWeb records a web endpoint for the API
|
|
||||||
RegisterWeb(http.Handler, string)
|
|
||||||
|
|
||||||
// Start the HTTP service
|
// Start the HTTP service
|
||||||
ListenAndServe()
|
ListenAndServe()
|
||||||
|
|
||||||
// DefaultConnector returns the base connector, which may not be the only connector
|
// DefaultConnector returns the base connector, which may not be the only connector
|
||||||
DefaultConnector() Connector
|
DefaultConnector() Connector
|
||||||
|
|
||||||
// GetWebNavigation returns the current known web endpoints
|
// GetWeb returns the bot's webserver structure
|
||||||
GetWebNavigation() []EndPoint
|
GetWeb() *web.Web
|
||||||
|
|
||||||
// GetPassword generates a unique password for modification commands on the public website
|
// GetPassword generates a unique password for modification commands on the public website
|
||||||
GetPassword() string
|
GetPassword() string
|
||||||
|
|
|
@ -4,6 +4,7 @@ package bot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/velour/catbase/bot/web"
|
||||||
"net/http"
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -26,6 +27,8 @@ type MockBot struct {
|
||||||
Messages []string
|
Messages []string
|
||||||
Actions []string
|
Actions []string
|
||||||
Reactions []string
|
Reactions []string
|
||||||
|
|
||||||
|
web *web.Web
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mb *MockBot) Config() *config.Config { return mb.Cfg }
|
func (mb *MockBot) Config() *config.Config { return mb.Cfg }
|
||||||
|
@ -60,9 +63,7 @@ func (mb *MockBot) Register(p Plugin, kind Kind, cb Callback)
|
||||||
func (mb *MockBot) RegisterTable(p Plugin, hs HandlerTable) {}
|
func (mb *MockBot) RegisterTable(p Plugin, hs HandlerTable) {}
|
||||||
func (mb *MockBot) RegisterRegex(p Plugin, kind Kind, r *regexp.Regexp, h ResponseHandler) {}
|
func (mb *MockBot) RegisterRegex(p Plugin, kind Kind, r *regexp.Regexp, h ResponseHandler) {}
|
||||||
func (mb *MockBot) RegisterRegexCmd(p Plugin, kind Kind, r *regexp.Regexp, h ResponseHandler) {}
|
func (mb *MockBot) RegisterRegexCmd(p Plugin, kind Kind, r *regexp.Regexp, h ResponseHandler) {}
|
||||||
func (mb *MockBot) RegisterWebName(_ http.Handler, _, _ string) {}
|
func (mb *MockBot) GetWeb() *web.Web { return mb.web }
|
||||||
func (mb *MockBot) RegisterWeb(_ http.Handler, _ string) {}
|
|
||||||
func (mb *MockBot) GetWebNavigation() []EndPoint { return nil }
|
|
||||||
func (mb *MockBot) Receive(c Connector, kind Kind, msg msg.Message, args ...any) bool {
|
func (mb *MockBot) Receive(c Connector, kind Kind, msg msg.Message, args ...any) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -118,6 +119,7 @@ func NewMockBot() *MockBot {
|
||||||
Messages: make([]string, 0),
|
Messages: make([]string, 0),
|
||||||
Actions: make([]string, 0),
|
Actions: make([]string, 0),
|
||||||
}
|
}
|
||||||
|
b.web = web.New(cfg)
|
||||||
// If any plugin registered a route, we need to reset those before any new test
|
// If any plugin registered a route, we need to reset those before any new test
|
||||||
http.DefaultServeMux = new(http.ServeMux)
|
http.DefaultServeMux = new(http.ServeMux)
|
||||||
return &b
|
return &b
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
package bot
|
|
||||||
|
|
||||||
templ (b *bot) Nav(currentPage string, items []EndPoint) {
|
|
||||||
<nav class="navbar navbar-expand-lg bg-body-tertiary">
|
|
||||||
<div class="container-fluid">
|
|
||||||
<a class="navbar-brand" href="/">catbase</a>
|
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
|
||||||
<span class="navbar-toggler-icon"></span>
|
|
||||||
</button>
|
|
||||||
<div class="collapse navbar-collapse" id="navbarNav">
|
|
||||||
<ul class="navbar-nav">
|
|
||||||
for _, item := range items {
|
|
||||||
<li class="nav-item">
|
|
||||||
if currentPage == item.Name {
|
|
||||||
<a class="nav-link active" aria-current="page" href={ templ.URL(item.URL) }>{ item.Name }</a>
|
|
||||||
} else {
|
|
||||||
<a class="nav-link" href={ templ.URL(item.URL) }>{ item.Name }</a>
|
|
||||||
}
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
}
|
|
104
bot/nav_templ.go
104
bot/nav_templ.go
|
@ -1,104 +0,0 @@
|
||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.2.543
|
|
||||||
package bot
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import "context"
|
|
||||||
import "io"
|
|
||||||
import "bytes"
|
|
||||||
|
|
||||||
func (b *bot) Nav(currentPage string, items []EndPoint) templ.Component {
|
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
|
||||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<nav class=\"navbar navbar-expand-lg bg-body-tertiary\"><div class=\"container-fluid\"><a class=\"navbar-brand\" href=\"/\">catbase</a> <button class=\"navbar-toggler\" type=\"button\" data-bs-toggle=\"collapse\" data-bs-target=\"#navbarNav\" aria-controls=\"navbarNav\" aria-expanded=\"false\" aria-label=\"Toggle navigation\"><span class=\"navbar-toggler-icon\"></span></button><div class=\"collapse navbar-collapse\" id=\"navbarNav\"><ul class=\"navbar-nav\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
for _, item := range items {
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"nav-item\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if currentPage == item.Name {
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"nav-link active\" aria-current=\"page\" href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 templ.SafeURL = templ.URL(item.URL)
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var2)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(item.Name)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bot/nav.templ`, Line: 14, Col: 119}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"nav-link\" href=\"")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var4 templ.SafeURL = templ.URL(item.URL)
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var5 string
|
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(item.Name)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bot/nav.templ`, Line: 16, Col: 92}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</li>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ul></div></div></nav>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
|
||||||
}
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
})
|
|
||||||
}
|
|
43
bot/web.go
43
bot/web.go
|
@ -1,43 +0,0 @@
|
||||||
package bot
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"github.com/go-chi/chi/v5"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (b *bot) serveRoot(w http.ResponseWriter, r *http.Request) {
|
|
||||||
b.index().Render(r.Context(), w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bot) serveNavHTML(w http.ResponseWriter, r *http.Request) {
|
|
||||||
currentPage := chi.URLParam(r, "currentPage")
|
|
||||||
b.Nav(currentPage, b.GetWebNavigation()).Render(r.Context(), w)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *bot) serveNav(w http.ResponseWriter, r *http.Request) {
|
|
||||||
enc := json.NewEncoder(w)
|
|
||||||
err := enc.Encode(b.GetWebNavigation())
|
|
||||||
if err != nil {
|
|
||||||
jsonErr, _ := json.Marshal(err)
|
|
||||||
w.WriteHeader(500)
|
|
||||||
w.Write(jsonErr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetWebNavigation returns a list of bootstrap-vue <b-nav-item> links
|
|
||||||
// The parent <nav> is not included so each page may display it as
|
|
||||||
// best fits
|
|
||||||
func (b *bot) GetWebNavigation() []EndPoint {
|
|
||||||
endpoints := b.httpEndPoints
|
|
||||||
moreEndpoints := b.config.GetArray("bot.links", []string{})
|
|
||||||
for _, e := range moreEndpoints {
|
|
||||||
link := strings.SplitN(e, ":", 2)
|
|
||||||
if len(link) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
endpoints = append(endpoints, EndPoint{link[0], link[1]})
|
|
||||||
}
|
|
||||||
return endpoints
|
|
||||||
}
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
package web
|
||||||
|
|
||||||
|
templ (w *Web) Header(title string) {
|
||||||
|
<head>
|
||||||
|
<!-- Load required Bootstrap and BootstrapVue CSS -->
|
||||||
|
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
if title != "" {
|
||||||
|
<title>catbase - { title }</title>
|
||||||
|
} else {
|
||||||
|
<title>catbase</title>
|
||||||
|
}
|
||||||
|
</head>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ (w *Web) Footer() {
|
||||||
|
<script src="//unpkg.com/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script src="//unpkg.com/htmx.org@1.9.10" integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC" crossorigin="anonymous"></script>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ (w *Web) Index(title string, contents templ.Component) {
|
||||||
|
<!DOCTYPE html />
|
||||||
|
<html lang="en">
|
||||||
|
@w.Header(title)
|
||||||
|
<body>
|
||||||
|
|
||||||
|
@w.Nav(title)
|
||||||
|
|
||||||
|
if contents != nil {
|
||||||
|
@contents
|
||||||
|
}
|
||||||
|
|
||||||
|
@w.Footer()
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ (w *Web) Nav(currentPage string) {
|
||||||
|
<nav class="navbar navbar-expand-lg bg-body-tertiary">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<a class="navbar-brand" href="/">catbase</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
for _, item := range w.GetWebNavigation() {
|
||||||
|
<li class="nav-item">
|
||||||
|
if currentPage == item.Name {
|
||||||
|
<a class="nav-link active" aria-current="page" href={ templ.URL(item.URL) }>{ item.Name }</a>
|
||||||
|
} else {
|
||||||
|
<a class="nav-link" href={ templ.URL(item.URL) }>{ item.Name }</a>
|
||||||
|
}
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
}
|
|
@ -0,0 +1,230 @@
|
||||||
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
|
// templ: version: v0.2.543
|
||||||
|
package web
|
||||||
|
|
||||||
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
|
import "github.com/a-h/templ"
|
||||||
|
import "context"
|
||||||
|
import "io"
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
func (w *Web) Header(title string) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var1 == nil {
|
||||||
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<head><!-- Load required Bootstrap and BootstrapVue CSS --><link type=\"text/css\" rel=\"stylesheet\" href=\"//unpkg.com/bootstrap/dist/css/bootstrap.min.css\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><meta charset=\"UTF-8\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if title != "" {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<title>catbase - ")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var2 string
|
||||||
|
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bot/web/index.templ`, Line: 9, Col: 36}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</title>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<title>catbase</title>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</head>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Web) Footer() templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var3 == nil {
|
||||||
|
templ_7745c5c3_Var3 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<script src=\"//unpkg.com/bootstrap/dist/js/bootstrap.bundle.min.js\"></script><script src=\"//unpkg.com/htmx.org@1.9.10\" integrity=\"sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC\" crossorigin=\"anonymous\"></script>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Web) Index(title string, contents templ.Component) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var4 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var4 == nil {
|
||||||
|
templ_7745c5c3_Var4 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html /><html lang=\"en\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = w.Header(title).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<body>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = w.Nav(title).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if contents != nil {
|
||||||
|
templ_7745c5c3_Err = contents.Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = w.Footer().Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</body></html>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Web) Nav(currentPage string) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var5 == nil {
|
||||||
|
templ_7745c5c3_Var5 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<nav class=\"navbar navbar-expand-lg bg-body-tertiary\"><div class=\"container-fluid\"><a class=\"navbar-brand\" href=\"/\">catbase</a> <button class=\"navbar-toggler\" type=\"button\" data-bs-toggle=\"collapse\" data-bs-target=\"#navbarNav\" aria-controls=\"navbarNav\" aria-expanded=\"false\" aria-label=\"Toggle navigation\"><span class=\"navbar-toggler-icon\"></span></button><div class=\"collapse navbar-collapse\" id=\"navbarNav\"><ul class=\"navbar-nav\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
for _, item := range w.GetWebNavigation() {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"nav-item\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if currentPage == item.Name {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"nav-link active\" aria-current=\"page\" href=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var6 templ.SafeURL = templ.URL(item.URL)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var6)))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var7 string
|
||||||
|
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(item.Name)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bot/web/index.templ`, Line: 50, Col: 119}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a class=\"nav-link\" href=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var8 templ.SafeURL = templ.URL(item.URL)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var8)))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var9 string
|
||||||
|
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(item.Name)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `bot/web/index.templ`, Line: 52, Col: 92}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</li>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ul></div></div></nav>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
package web
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
|
"github.com/go-chi/httprate"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"github.com/velour/catbase/config"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Web struct {
|
||||||
|
config *config.Config
|
||||||
|
router *chi.Mux
|
||||||
|
httpEndPoints []EndPoint
|
||||||
|
}
|
||||||
|
|
||||||
|
type EndPoint struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWebNavigation returns a list of bootstrap-vue <b-nav-item> links
|
||||||
|
// The parent <nav> is not included so each page may display it as
|
||||||
|
// best fits
|
||||||
|
func (ws *Web) GetWebNavigation() []EndPoint {
|
||||||
|
endpoints := ws.httpEndPoints
|
||||||
|
moreEndpoints := ws.config.GetArray("bot.links", []string{})
|
||||||
|
for _, e := range moreEndpoints {
|
||||||
|
link := strings.SplitN(e, ":", 2)
|
||||||
|
if len(link) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
endpoints = append(endpoints, EndPoint{link[0], link[1]})
|
||||||
|
}
|
||||||
|
return endpoints
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *Web) serveRoot(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ws.Index("Home", nil).Render(r.Context(), w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *Web) serveNavHTML(w http.ResponseWriter, r *http.Request) {
|
||||||
|
currentPage := chi.URLParam(r, "currentPage")
|
||||||
|
ws.Nav(currentPage).Render(r.Context(), w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *Web) serveNav(w http.ResponseWriter, r *http.Request) {
|
||||||
|
enc := json.NewEncoder(w)
|
||||||
|
err := enc.Encode(ws.GetWebNavigation())
|
||||||
|
if err != nil {
|
||||||
|
jsonErr, _ := json.Marshal(err)
|
||||||
|
w.WriteHeader(500)
|
||||||
|
w.Write(jsonErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *Web) setupHTTP() {
|
||||||
|
// Make the http logger optional
|
||||||
|
// It has never served a purpose in production and with the emojy page, can make a rather noisy log
|
||||||
|
if ws.config.GetInt("bot.useLogger", 0) == 1 {
|
||||||
|
ws.router.Use(middleware.Logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
reqCount := ws.config.GetInt("bot.httprate.requests", 500)
|
||||||
|
reqTime := time.Duration(ws.config.GetInt("bot.httprate.seconds", 5))
|
||||||
|
if reqCount > 0 && reqTime > 0 {
|
||||||
|
ws.router.Use(httprate.LimitByIP(reqCount, reqTime*time.Second))
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.router.Use(middleware.RequestID)
|
||||||
|
ws.router.Use(middleware.Recoverer)
|
||||||
|
ws.router.Use(middleware.StripSlashes)
|
||||||
|
|
||||||
|
ws.router.HandleFunc("/", ws.serveRoot)
|
||||||
|
ws.router.HandleFunc("/nav", ws.serveNav)
|
||||||
|
ws.router.HandleFunc("/navHTML", ws.serveNavHTML)
|
||||||
|
ws.router.HandleFunc("/navHTML/{currentPage}", ws.serveNavHTML)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *Web) RegisterWeb(r http.Handler, root string) {
|
||||||
|
ws.router.Mount(root, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *Web) RegisterWebName(r http.Handler, root, name string) {
|
||||||
|
ws.httpEndPoints = append(ws.httpEndPoints, EndPoint{name, root})
|
||||||
|
ws.router.Mount(root, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *Web) ListenAndServe(addr string) {
|
||||||
|
log.Debug().Msgf("starting web service at %s", addr)
|
||||||
|
log.Fatal().Err(http.ListenAndServe(addr, ws.router)).Msg("bot killed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(config *config.Config) *Web {
|
||||||
|
w := &Web{
|
||||||
|
config: config,
|
||||||
|
router: chi.NewRouter(),
|
||||||
|
}
|
||||||
|
w.setupHTTP()
|
||||||
|
return w
|
||||||
|
}
|
2
main.go
2
main.go
|
@ -130,7 +130,7 @@ func main() {
|
||||||
b := bot.New(c, client)
|
b := bot.New(c, client)
|
||||||
|
|
||||||
if r, path := client.GetRouter(); r != nil {
|
if r, path := client.GetRouter(); r != nil {
|
||||||
b.RegisterWeb(r, path)
|
b.GetWeb().RegisterWeb(r, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.AddPlugin(admin.New(b))
|
b.AddPlugin(admin.New(b))
|
||||||
|
|
|
@ -3,18 +3,6 @@ package admin
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
templ (a *AdminPlugin) page() {
|
templ (a *AdminPlugin) page() {
|
||||||
<!DOCTYPE html />
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<!-- Load required Bootstrap and BootstrapVue CSS -->
|
|
||||||
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Vars</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div hx-get="/navHTML/Variables" hx-trigger="load" hx-swap="outerHTML"></div>
|
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<form>
|
<form>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -39,10 +27,6 @@ templ (a *AdminPlugin) page() {
|
||||||
<div id="data"></div>
|
<div id="data"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="//unpkg.com/htmx.org@1.9.10" integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC" crossorigin="anonymous"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
templ (a *AdminPlugin) showPassword(entry PassEntry) {
|
templ (a *AdminPlugin) showPassword(entry PassEntry) {
|
||||||
|
@ -74,4 +58,29 @@ templ (a *AdminPlugin) entries(items []PassEntry) {
|
||||||
|
|
||||||
templ renderError(err error) {
|
templ renderError(err error) {
|
||||||
<div>{ err.Error() }</div>
|
<div>{ err.Error() }</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
templ vars(items []configEntry) {
|
||||||
|
<div class="container">
|
||||||
|
<table class="table-responsive table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Key</th>
|
||||||
|
<th>Value</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
for _, item := range items {
|
||||||
|
<tr>
|
||||||
|
<td>{ item.Key }</td><td>{ item.Value }</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
if len(items) == 0 {
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">No data</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
}
|
|
@ -25,7 +25,7 @@ func (a *AdminPlugin) page() templ.Component {
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html /><html lang=\"en\"><head><!-- Load required Bootstrap and BootstrapVue CSS --><link type=\"text/css\" rel=\"stylesheet\" href=\"//unpkg.com/bootstrap/dist/css/bootstrap.min.css\"><meta charset=\"UTF-8\"><title>Vars</title></head><body><div hx-get=\"/navHTML/Variables\" hx-trigger=\"load\" hx-swap=\"outerHTML\"></div><div class=\"container\"><form><div class=\"row\"><div class=\"col-auto\"><label for=\"password\">Password: <input type=\"text\" name=\"password\"></label></div><div class=\"col-auto\"><label for=\"secret\">Secret: <input type=\"text\" name=\"secret\"></label></div><div class=\"col-auto\"><button hx-post=\"/apppass/api\" hx-target=\"#data\" class=\"btn btn-primary\">List</button> <button hx-put=\"/apppass/api\" hx-target=\"#data\" class=\"btn btn-secondary\">New</button></div></div></form><div class=\"row\"><div id=\"data\"></div></div></div><script src=\"//unpkg.com/htmx.org@1.9.10\" integrity=\"sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC\" crossorigin=\"anonymous\"></script></body></html>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"container\"><form><div class=\"row\"><div class=\"col\"><label for=\"password\">Password: <input type=\"text\" name=\"password\"></label></div><div class=\"col\"><label for=\"secret\">Secret: <input type=\"text\" name=\"secret\"></label></div><div class=\"col\"><button hx-post=\"/apppass/api\" hx-target=\"#data\" class=\"btn btn-primary\">List</button> <button hx-put=\"/apppass/api\" hx-target=\"#data\" class=\"btn btn-secondary\">New</button></div></div></form><div class=\"row\"><div id=\"data\"></div></div></div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ func (a *AdminPlugin) showPassword(entry PassEntry) templ.Component {
|
||||||
var templ_7745c5c3_Var3 string
|
var templ_7745c5c3_Var3 string
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", entry.ID))
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", entry.ID))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/admin/apppass.templ`, Line: 48, Col: 59}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/admin/admin.templ`, Line: 32, Col: 59}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
@ -69,7 +69,7 @@ func (a *AdminPlugin) showPassword(entry PassEntry) templ.Component {
|
||||||
var templ_7745c5c3_Var4 string
|
var templ_7745c5c3_Var4 string
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Secret)
|
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Secret)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/admin/apppass.templ`, Line: 49, Col: 50}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/admin/admin.templ`, Line: 33, Col: 50}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
@ -82,7 +82,7 @@ func (a *AdminPlugin) showPassword(entry PassEntry) templ.Component {
|
||||||
var templ_7745c5c3_Var5 string
|
var templ_7745c5c3_Var5 string
|
||||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Pass)
|
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Pass)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/admin/apppass.templ`, Line: 49, Col: 65}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/admin/admin.templ`, Line: 33, Col: 65}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
@ -150,7 +150,7 @@ func (a *AdminPlugin) entries(items []PassEntry) templ.Component {
|
||||||
var templ_7745c5c3_Var7 string
|
var templ_7745c5c3_Var7 string
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", entry.ID))
|
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", entry.ID))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/admin/apppass.templ`, Line: 67, Col: 57}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/admin/admin.templ`, Line: 51, Col: 57}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
@ -192,7 +192,7 @@ func renderError(err error) templ.Component {
|
||||||
var templ_7745c5c3_Var9 string
|
var templ_7745c5c3_Var9 string
|
||||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(err.Error())
|
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(err.Error())
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/admin/apppass.templ`, Line: 75, Col: 22}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/admin/admin.templ`, Line: 59, Col: 22}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
@ -208,3 +208,69 @@ func renderError(err error) templ.Component {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func vars(items []configEntry) templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var10 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var10 == nil {
|
||||||
|
templ_7745c5c3_Var10 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"container\"><table class=\"table-responsive table-striped\"><thead><tr><th>Key</th><th>Value</th></tr></thead> <tbody>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
for _, item := range items {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<tr><td>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var11 string
|
||||||
|
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(item.Key)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/admin/admin.templ`, Line: 74, Col: 38}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var12 string
|
||||||
|
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(item.Value)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/admin/admin.templ`, Line: 74, Col: 61}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td></tr>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(items) == 0 {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<tr><td colspan=\"2\">No data</td></tr>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</tbody></table></div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,42 +0,0 @@
|
||||||
package admin
|
|
||||||
|
|
||||||
templ vars(items []configEntry) {
|
|
||||||
<!doctype html />
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<title>vars</title>
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous" />
|
|
||||||
<script src="https://unpkg.com/htmx.org@1.9.4"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div hx-get="/navHTML/Variables" hx-trigger="load" hx-swap="outerHTML"></div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<table class="table-responsive table-striped">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Key</th>
|
|
||||||
<th>Value</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
for _, item := range items {
|
|
||||||
<tr>
|
|
||||||
<td>{ item.Key }</td><td>{ item.Value }</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
if len(items) == 0 {
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">No data</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" crossorigin="anonymous"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
// Code generated by templ - DO NOT EDIT.
|
|
||||||
|
|
||||||
// templ: version: v0.2.543
|
|
||||||
package admin
|
|
||||||
|
|
||||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
|
||||||
|
|
||||||
import "github.com/a-h/templ"
|
|
||||||
import "context"
|
|
||||||
import "io"
|
|
||||||
import "bytes"
|
|
||||||
|
|
||||||
func vars(items []configEntry) templ.Component {
|
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
|
||||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
|
||||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
|
||||||
}
|
|
||||||
ctx = templ.InitializeContext(ctx)
|
|
||||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
|
||||||
if templ_7745c5c3_Var1 == nil {
|
|
||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
|
||||||
}
|
|
||||||
ctx = templ.ClearChildren(ctx)
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html /><html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>vars</title><link href=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9\" crossorigin=\"anonymous\"><script src=\"https://unpkg.com/htmx.org@1.9.4\"></script></head><body><div hx-get=\"/navHTML/Variables\" hx-trigger=\"load\" hx-swap=\"outerHTML\"></div><div class=\"container\"><table class=\"table-responsive table-striped\"><thead><tr><th>Key</th><th>Value</th></tr></thead> <tbody>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
for _, item := range items {
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<tr><td>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var2 string
|
|
||||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(item.Key)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/admin/vars.templ`, Line: 27, Col: 38}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
var templ_7745c5c3_Var3 string
|
|
||||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(item.Value)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/admin/vars.templ`, Line: 27, Col: 61}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td></tr>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(items) == 0 {
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<tr><td colspan=\"2\">No data</td></tr>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</tbody></table></div><script src=\"https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js\" integrity=\"sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm\" crossorigin=\"anonymous\"></script></body></html>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
if !templ_7745c5c3_IsBuffer {
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
|
||||||
}
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -19,16 +19,16 @@ import (
|
||||||
func (p *AdminPlugin) registerWeb() {
|
func (p *AdminPlugin) registerWeb() {
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.HandleFunc("/", p.handleVars)
|
r.HandleFunc("/", p.handleVars)
|
||||||
p.bot.RegisterWebName(r, "/vars", "Variables")
|
p.bot.GetWeb().RegisterWebName(r, "/vars", "Variables")
|
||||||
r = chi.NewRouter()
|
r = chi.NewRouter()
|
||||||
r.HandleFunc("/verify", p.handleAppPassCheck)
|
r.HandleFunc("/verify", p.handleAppPassCheck)
|
||||||
r.HandleFunc("/api", p.handleAppPassAPI)
|
r.HandleFunc("/api", p.handleAppPassAPI)
|
||||||
r.HandleFunc("/", p.handleAppPass)
|
r.HandleFunc("/", p.handleAppPass)
|
||||||
p.bot.RegisterWebName(r, "/apppass", "App Pass")
|
p.bot.GetWeb().RegisterWebName(r, "/apppass", "App Pass")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *AdminPlugin) handleAppPass(w http.ResponseWriter, r *http.Request) {
|
func (p *AdminPlugin) handleAppPass(w http.ResponseWriter, r *http.Request) {
|
||||||
p.page().Render(r.Context(), w)
|
p.bot.GetWeb().Index("App Pass", p.page()).Render(r.Context(), w)
|
||||||
}
|
}
|
||||||
|
|
||||||
type PassEntry struct {
|
type PassEntry struct {
|
||||||
|
@ -188,5 +188,5 @@ func (p *AdminPlugin) handleVars(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
vars(configEntries).Render(r.Context(), w)
|
p.bot.GetWeb().Index("Variables", vars(configEntries)).Render(r.Context(), w)
|
||||||
}
|
}
|
||||||
|
|
|
@ -598,7 +598,7 @@ func (p *BeersPlugin) untappdLoop(c bot.Connector, channel string) {
|
||||||
func (p *BeersPlugin) registerWeb() {
|
func (p *BeersPlugin) registerWeb() {
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.HandleFunc("/img/{id}", p.img)
|
r.HandleFunc("/img/{id}", p.img)
|
||||||
p.b.RegisterWeb(r, "/beers")
|
p.b.GetWeb().RegisterWeb(r, "/beers")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BeersPlugin) img(w http.ResponseWriter, r *http.Request) {
|
func (p *BeersPlugin) img(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -40,7 +40,7 @@ func (p *CliPlugin) registerWeb() {
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.HandleFunc("/api", p.handleWebAPI)
|
r.HandleFunc("/api", p.handleWebAPI)
|
||||||
r.HandleFunc("/", p.handleWeb)
|
r.HandleFunc("/", p.handleWeb)
|
||||||
p.bot.RegisterWebName(r, "/cli", "CLI")
|
p.bot.GetWeb().RegisterWebName(r, "/cli", "CLI")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *CliPlugin) Shutdown() {}
|
func (p *CliPlugin) Shutdown() {}
|
||||||
|
|
|
@ -35,7 +35,7 @@ func (p *CounterPlugin) registerWeb() {
|
||||||
r.Mount("/", subrouter)
|
r.Mount("/", subrouter)
|
||||||
r.HandleFunc("/api", p.handleCounterAPI)
|
r.HandleFunc("/api", p.handleCounterAPI)
|
||||||
r.HandleFunc("/", p.handleCounter)
|
r.HandleFunc("/", p.handleCounter)
|
||||||
p.b.RegisterWebName(r, "/counter", "Counter")
|
p.b.GetWeb().RegisterWebName(r, "/counter", "Counter")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *CounterPlugin) mkIncrementByNAPI(direction int) func(w http.ResponseWriter, r *http.Request) {
|
func (p *CounterPlugin) mkIncrementByNAPI(direction int) func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
func (p *Cowboy) registerWeb() {
|
func (p *Cowboy) registerWeb() {
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.HandleFunc("/img/{overlay}/{what}", p.handleImage)
|
r.HandleFunc("/img/{overlay}/{what}", p.handleImage)
|
||||||
p.b.RegisterWeb(r, "/cowboy")
|
p.b.GetWeb().RegisterWeb(r, "/cowboy")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Cowboy) handleImage(w http.ResponseWriter, r *http.Request) {
|
func (p *Cowboy) handleImage(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ func (p *EmojyPlugin) registerWeb() {
|
||||||
r.HandleFunc("/list", p.handlePage("list.html"))
|
r.HandleFunc("/list", p.handlePage("list.html"))
|
||||||
r.HandleFunc("/new", p.handlePage("upload.html"))
|
r.HandleFunc("/new", p.handlePage("upload.html"))
|
||||||
r.HandleFunc("/", p.handleIndex)
|
r.HandleFunc("/", p.handleIndex)
|
||||||
p.b.RegisterWebName(r, "/emojy", "Emojys")
|
p.b.GetWeb().RegisterWebName(r, "/emojy", "Emojys")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *EmojyPlugin) handleIndex(w http.ResponseWriter, r *http.Request) {
|
func (p *EmojyPlugin) handleIndex(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ func (p *FactoidPlugin) registerWeb() {
|
||||||
r.HandleFunc("/api", p.serveAPI)
|
r.HandleFunc("/api", p.serveAPI)
|
||||||
r.HandleFunc("/req", p.serveQuery)
|
r.HandleFunc("/req", p.serveQuery)
|
||||||
r.HandleFunc("/", p.serveQuery)
|
r.HandleFunc("/", p.serveQuery)
|
||||||
p.b.RegisterWebName(r, "/factoid", "Factoid")
|
p.b.GetWeb().RegisterWebName(r, "/factoid", "Factoid")
|
||||||
}
|
}
|
||||||
|
|
||||||
func linkify(text string) template.HTML {
|
func linkify(text string) template.HTML {
|
||||||
|
|
|
@ -81,5 +81,5 @@ func (p *GitPlugin) registerWeb() {
|
||||||
r.HandleFunc("/gitea/event", p.giteaEvent)
|
r.HandleFunc("/gitea/event", p.giteaEvent)
|
||||||
r.HandleFunc("/github/event", p.githubEvent)
|
r.HandleFunc("/github/event", p.githubEvent)
|
||||||
r.HandleFunc("/gitlab/event", p.gitlabEvent)
|
r.HandleFunc("/gitlab/event", p.gitlabEvent)
|
||||||
p.b.RegisterWeb(r, "/git")
|
p.b.GetWeb().RegisterWeb(r, "/git")
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ func (p *MemePlugin) registerWeb(c bot.Connector) {
|
||||||
r.HandleFunc("/add", p.addMeme)
|
r.HandleFunc("/add", p.addMeme)
|
||||||
r.HandleFunc("/rm", p.rmMeme)
|
r.HandleFunc("/rm", p.rmMeme)
|
||||||
r.HandleFunc("/", p.webRoot)
|
r.HandleFunc("/", p.webRoot)
|
||||||
p.bot.RegisterWebName(r, "/meme", "Memes")
|
p.bot.GetWeb().RegisterWebName(r, "/meme", "Memes")
|
||||||
}
|
}
|
||||||
|
|
||||||
type webResp struct {
|
type webResp struct {
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<!-- Load required Bootstrap and BootstrapVue CSS -->
|
|
||||||
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
|
|
||||||
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@^2/dist/bootstrap-vue.min.css" />
|
|
||||||
|
|
||||||
<!-- Load polyfills to support older browsers -->
|
|
||||||
<script src="//polyfill.io/v3/polyfill.min.js?features=es2015%2CMutationObserver"></script>
|
|
||||||
|
|
||||||
<!-- Load Vue followed by BootstrapVue -->
|
|
||||||
<script src="//unpkg.com/vue@^2/dist/vue.min.js"></script>
|
|
||||||
<script src="//unpkg.com/bootstrap-vue@^2/dist/bootstrap-vue.min.js"></script>
|
|
||||||
<script src="https://unpkg.com/vue-router@^2"></script>
|
|
||||||
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>Memes</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div id="app">
|
|
||||||
<b-navbar>
|
|
||||||
<b-navbar-brand>Memes</b-navbar-brand>
|
|
||||||
<b-navbar-nav>
|
|
||||||
<b-nav-item v-for="item in nav" :href="item.url" :active="item.name === 'Meme'" :key="item.key">{{ item.name }}</b-nav-item>
|
|
||||||
</b-navbar-nav>
|
|
||||||
</b-navbar>
|
|
||||||
<b-alert
|
|
||||||
dismissable
|
|
||||||
variant="error"
|
|
||||||
:show="err != ''"
|
|
||||||
@dismissed="err = ''">
|
|
||||||
{{ err }}
|
|
||||||
</b-alert>
|
|
||||||
<b-form @submit="add">
|
|
||||||
<b-container>
|
|
||||||
<b-row>
|
|
||||||
<b-col cols="3">
|
|
||||||
<b-input placeholder="Key..." v-model="secret.key"></b-input>
|
|
||||||
</b-col>
|
|
||||||
<b-col cols="3">
|
|
||||||
<b-input placeholder="Value..." v-model="secret.value"></b-input>
|
|
||||||
</b-col>
|
|
||||||
<b-col cols="3">
|
|
||||||
<b-button type="submit">Add Secret</b-button>
|
|
||||||
</b-col>
|
|
||||||
</b-row>
|
|
||||||
<b-row style="padding-top: 2em;">
|
|
||||||
<b-col>
|
|
||||||
<ul>
|
|
||||||
<li v-for="key in results" key="key"><a @click="rm(key)" href="#">X</a> {{key}}</li>
|
|
||||||
</ul>
|
|
||||||
</b-col>
|
|
||||||
</b-row>
|
|
||||||
</b-container>
|
|
||||||
</b-form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
var router = new VueRouter({
|
|
||||||
mode: 'history',
|
|
||||||
routes: []
|
|
||||||
});
|
|
||||||
var app = new Vue({
|
|
||||||
el: '#app',
|
|
||||||
router,
|
|
||||||
data: {
|
|
||||||
err: '',
|
|
||||||
nav: [],
|
|
||||||
secret: {key: '', value: ''},
|
|
||||||
results: [],
|
|
||||||
fields: [
|
|
||||||
{key: 'key', sortable: true},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
axios.get('/nav')
|
|
||||||
.then(resp => {
|
|
||||||
this.nav = resp.data;
|
|
||||||
})
|
|
||||||
.catch(err => console.log(err))
|
|
||||||
this.refresh();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
refresh: function () {
|
|
||||||
axios.get('/secrets/all')
|
|
||||||
.then(resp => {
|
|
||||||
this.results = resp.data
|
|
||||||
this.err = ''
|
|
||||||
})
|
|
||||||
.catch(err => (this.err = err))
|
|
||||||
},
|
|
||||||
add: function (evt) {
|
|
||||||
if (evt) {
|
|
||||||
evt.preventDefault();
|
|
||||||
evt.stopPropagation();
|
|
||||||
}
|
|
||||||
axios.post('/secrets/add', this.secret)
|
|
||||||
.then(resp => {
|
|
||||||
this.results = resp.data;
|
|
||||||
this.secret.key = '';
|
|
||||||
this.secret.value = '';
|
|
||||||
this.refresh();
|
|
||||||
})
|
|
||||||
.catch(err => this.err = err)
|
|
||||||
},
|
|
||||||
rm: function (key) {
|
|
||||||
if (confirm("Are you sure you want to delete this meme?")) {
|
|
||||||
axios.delete('/secrets/remove', {data: {key: key}})
|
|
||||||
.then(resp => {
|
|
||||||
this.refresh();
|
|
||||||
})
|
|
||||||
.catch(err => this.err = err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,21 +1,18 @@
|
||||||
package secrets
|
package secrets
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/velour/catbase/bot"
|
"github.com/velour/catbase/bot"
|
||||||
"github.com/velour/catbase/config"
|
"github.com/velour/catbase/config"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed *.html
|
|
||||||
var embeddedFS embed.FS
|
|
||||||
|
|
||||||
type SecretsPlugin struct {
|
type SecretsPlugin struct {
|
||||||
b bot.Bot
|
b bot.Bot
|
||||||
c *config.Config
|
c *config.Config
|
||||||
|
@ -36,14 +33,8 @@ func (p *SecretsPlugin) registerWeb() {
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.HandleFunc("/add", p.handleRegister)
|
r.HandleFunc("/add", p.handleRegister)
|
||||||
r.HandleFunc("/remove", p.handleRemove)
|
r.HandleFunc("/remove", p.handleRemove)
|
||||||
r.HandleFunc("/all", p.handleAll)
|
|
||||||
r.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
value := r.URL.Query().Get("test")
|
|
||||||
j, _ := json.Marshal(map[string]string{"value": value})
|
|
||||||
w.Write(j)
|
|
||||||
})
|
|
||||||
r.HandleFunc("/", p.handleIndex)
|
r.HandleFunc("/", p.handleIndex)
|
||||||
p.b.RegisterWebName(r, "/secrets", "Secrets")
|
p.b.GetWeb().RegisterWebName(r, "/secrets", "Secrets")
|
||||||
}
|
}
|
||||||
|
|
||||||
func mkCheckError(w http.ResponseWriter) func(error) bool {
|
func mkCheckError(w http.ResponseWriter) func(error) bool {
|
||||||
|
@ -68,20 +59,12 @@ func checkMethod(method string, w http.ResponseWriter, r *http.Request) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *SecretsPlugin) keys() []string {
|
||||||
|
return p.c.SecretKeys()
|
||||||
|
}
|
||||||
|
|
||||||
func (p *SecretsPlugin) sendKeys(w http.ResponseWriter, r *http.Request) {
|
func (p *SecretsPlugin) sendKeys(w http.ResponseWriter, r *http.Request) {
|
||||||
checkError := mkCheckError(w)
|
p.keysList().Render(r.Context(), w)
|
||||||
log.Debug().Msgf("Keys before refresh: %v", p.c.SecretKeys())
|
|
||||||
err := p.c.RefreshSecrets()
|
|
||||||
log.Debug().Msgf("Keys after refresh: %v", p.c.SecretKeys())
|
|
||||||
if checkError(err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
keys, err := json.Marshal(p.c.SecretKeys())
|
|
||||||
if checkError(err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.WriteHeader(200)
|
|
||||||
w.Write(keys)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SecretsPlugin) handleAll(w http.ResponseWriter, r *http.Request) {
|
func (p *SecretsPlugin) handleAll(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -89,21 +72,13 @@ func (p *SecretsPlugin) handleAll(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SecretsPlugin) handleRegister(w http.ResponseWriter, r *http.Request) {
|
func (p *SecretsPlugin) handleRegister(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Debug().Msgf("handleRegister")
|
|
||||||
if checkMethod(http.MethodPost, w, r) {
|
if checkMethod(http.MethodPost, w, r) {
|
||||||
log.Debug().Msgf("failed post %s", r.Method)
|
log.Debug().Msgf("failed post %s", r.Method)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
checkError := mkCheckError(w)
|
checkError := mkCheckError(w)
|
||||||
decoder := json.NewDecoder(r.Body)
|
key, value := r.FormValue("key"), r.FormValue("value")
|
||||||
secret := config.Secret{}
|
err := p.c.RegisterSecret(key, value)
|
||||||
err := decoder.Decode(&secret)
|
|
||||||
log.Debug().Msgf("decoding: %s", err)
|
|
||||||
if checkError(err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Debug().Msgf("Secret: %s", secret)
|
|
||||||
err = p.c.RegisterSecret(secret.Key, secret.Value)
|
|
||||||
if checkError(err) {
|
if checkError(err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -115,13 +90,16 @@ func (p *SecretsPlugin) handleRemove(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
checkError := mkCheckError(w)
|
checkError := mkCheckError(w)
|
||||||
decoder := json.NewDecoder(r.Body)
|
b, err := io.ReadAll(r.Body)
|
||||||
secret := config.Secret{}
|
|
||||||
err := decoder.Decode(&secret)
|
|
||||||
if checkError(err) {
|
if checkError(err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = p.c.RemoveSecret(secret.Key)
|
q, err := url.ParseQuery(string(b))
|
||||||
|
if checkError(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
secret := q.Get("key")
|
||||||
|
err = p.c.RemoveSecret(secret)
|
||||||
if checkError(err) {
|
if checkError(err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -129,6 +107,5 @@ func (p *SecretsPlugin) handleRemove(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SecretsPlugin) handleIndex(w http.ResponseWriter, r *http.Request) {
|
func (p *SecretsPlugin) handleIndex(w http.ResponseWriter, r *http.Request) {
|
||||||
index, _ := embeddedFS.ReadFile("index.html")
|
p.b.GetWeb().Index("Secrets", p.index()).Render(r.Context(), w)
|
||||||
w.Write(index)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
package secrets
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
templ (s *SecretsPlugin) index() {
|
||||||
|
<div class="container">
|
||||||
|
<form hx-post="/secrets/add" hx-target="#data">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-3">
|
||||||
|
<input placeholder="Key..." name="key" />
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<input placeholder="Value..." name="value" />
|
||||||
|
</div>
|
||||||
|
<div class="col-3">
|
||||||
|
<button class="btn btn-primary" type="submit">Add Secret</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div class="row" style="padding-top: 2em;">
|
||||||
|
<div id="data">
|
||||||
|
@s.keysList()
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
templ (s *SecretsPlugin) keysList() {
|
||||||
|
<ul>
|
||||||
|
for _, key := range s.keys() {
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
class="btn btn-danger"
|
||||||
|
hx-delete="/secrets/remove"
|
||||||
|
hx-confirm={ fmt.Sprintf("Are you sure you want to delete %s?", key) }
|
||||||
|
hx-target="#data"
|
||||||
|
hx-include="this"
|
||||||
|
name="key" value={ key }>X</button>
|
||||||
|
{ key }</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
|
// templ: version: v0.2.543
|
||||||
|
package secrets
|
||||||
|
|
||||||
|
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||||
|
|
||||||
|
import "github.com/a-h/templ"
|
||||||
|
import "context"
|
||||||
|
import "io"
|
||||||
|
import "bytes"
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func (s *SecretsPlugin) index() templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var1 == nil {
|
||||||
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"container\"><form hx-post=\"/secrets/add\" hx-target=\"#data\"><div class=\"row\"><div class=\"col-3\"><input placeholder=\"Key...\" name=\"key\"></div><div class=\"col-3\"><input placeholder=\"Value...\" name=\"value\"></div><div class=\"col-3\"><button class=\"btn btn-primary\" type=\"submit\">Add Secret</button></div></div></form><div class=\"row\" style=\"padding-top: 2em;\"><div id=\"data\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = s.keysList().Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div></div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SecretsPlugin) keysList() templ.Component {
|
||||||
|
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||||
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||||
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
|
}
|
||||||
|
ctx = templ.InitializeContext(ctx)
|
||||||
|
templ_7745c5c3_Var2 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var2 == nil {
|
||||||
|
templ_7745c5c3_Var2 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<ul>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
for _, key := range s.keys() {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li><button class=\"btn btn-danger\" hx-delete=\"/secrets/remove\" hx-confirm=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(fmt.Sprintf("Are you sure you want to delete %s?", key)))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" hx-target=\"#data\" hx-include=\"this\" name=\"key\" value=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(key))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">X</button> ")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var3 string
|
||||||
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(key)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `plugins/secrets/secrets.templ`, Line: 38, Col: 17}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</li>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ul>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
|
@ -121,7 +121,7 @@ func (p *SMSPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, ar
|
||||||
func (p *SMSPlugin) registerWeb() {
|
func (p *SMSPlugin) registerWeb() {
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.HandleFunc("/new", p.receive)
|
r.HandleFunc("/new", p.receive)
|
||||||
p.b.RegisterWeb(r, "/sms")
|
p.b.GetWeb().RegisterWeb(r, "/sms")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SMSPlugin) receive(w http.ResponseWriter, r *http.Request) {
|
func (p *SMSPlugin) receive(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -186,5 +186,5 @@ func (p *TalkerPlugin) registerWeb(c bot.Connector) {
|
||||||
p.bot.Send(c, bot.Message, channel, msg)
|
p.bot.Send(c, bot.Message, channel, msg)
|
||||||
w.WriteHeader(200)
|
w.WriteHeader(200)
|
||||||
})
|
})
|
||||||
p.bot.RegisterWeb(r, "/cowsay")
|
p.bot.GetWeb().RegisterWeb(r, "/cowsay")
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
func (p *Tappd) registerWeb() {
|
func (p *Tappd) registerWeb() {
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.HandleFunc("/", p.serveImage)
|
r.HandleFunc("/", p.serveImage)
|
||||||
p.b.RegisterWeb(r, "/tappd/{id}")
|
p.b.GetWeb().RegisterWeb(r, "/tappd/{id}")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Tappd) getImg(id string) ([]byte, error) {
|
func (p *Tappd) getImg(id string) ([]byte, error) {
|
||||||
|
|
|
@ -102,7 +102,7 @@ func (p *Twitch) registerWeb() {
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.HandleFunc("/online", p.onlineCB)
|
r.HandleFunc("/online", p.onlineCB)
|
||||||
r.HandleFunc("/offline", p.offlineCB)
|
r.HandleFunc("/offline", p.offlineCB)
|
||||||
p.b.RegisterWeb(r, "/twitch")
|
p.b.GetWeb().RegisterWeb(r, "/twitch")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Twitch) register() {
|
func (p *Twitch) register() {
|
||||||
|
|
Loading…
Reference in New Issue