diff --git a/bot/bot.go b/bot/bot.go
index d8a3b51..7441945 100644
--- a/bot/bot.go
+++ b/bot/bot.go
@@ -4,10 +4,8 @@ package bot
import (
"fmt"
- "github.com/go-chi/chi/v5/middleware"
- "github.com/go-chi/httprate"
+ "github.com/velour/catbase/bot/web"
"math/rand"
- "net/http"
"os"
"os/signal"
"reflect"
@@ -15,7 +13,6 @@ import (
"strings"
"time"
- "github.com/go-chi/chi/v5"
"github.com/jmoiron/sqlx"
"github.com/rs/zerolog/log"
"github.com/velour/catbase/bot/history"
@@ -53,8 +50,7 @@ type bot struct {
version string
- // The entries to the bot's HTTP interface
- httpEndPoints []EndPoint
+ web *web.Web
// filters registered by plugins
filters map[string]func(string) string
@@ -66,16 +62,9 @@ type bot struct {
quiet bool
- router *chi.Mux
-
history *history.History
}
-type EndPoint struct {
- Name string `json:"name"`
- URL string `json:"url"`
-}
-
// Variable represents a $var replacement
type Variable struct {
Variable, Value string
@@ -107,10 +96,8 @@ func New(config *config.Config, connector Connector) Bot {
me: users[0],
logIn: logIn,
logOut: logOut,
- httpEndPoints: make([]EndPoint, 0),
filters: make(map[string]func(string) string),
callbacks: make(CallbackMap),
- router: chi.NewRouter(),
history: history.New(historySz),
}
@@ -119,60 +106,25 @@ func New(config *config.Config, connector Connector) Bot {
bot.RefreshPluginBlacklist()
bot.RefreshPluginWhitelist()
- log.Debug().Msgf("created web router")
-
- bot.setupHTTP()
+ bot.web = web.New(bot.config)
connector.RegisterEvent(bot.Receive)
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() {
addr := b.config.Get("HttpAddr", "127.0.0.1:1337")
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
go func() {
- log.Debug().Msgf("starting web service at %s", addr)
- log.Fatal().Err(http.ListenAndServe(addr, b.router)).Msg("bot killed")
+ b.web.ListenAndServe(addr)
}()
<-stop
b.DefaultConnector().Shutdown()
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
// 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.
@@ -458,3 +410,7 @@ func (b *bot) CheckPassword(secret, password string) bool {
}
return false
}
+
+func (b *bot) GetWeb() *web.Web {
+ return b.web
+}
diff --git a/bot/index.templ b/bot/index.templ
deleted file mode 100644
index 8397b71..0000000
--- a/bot/index.templ
+++ /dev/null
@@ -1,22 +0,0 @@
-package bot
-
-templ (b *bot) index() {
-
-
-
-
-
-
-
- catbase
-
-
-
-
- @b.Nav("", b.GetWebNavigation())
-
-
-
-
-
-}
\ No newline at end of file
diff --git a/bot/index_templ.go b/bot/index_templ.go
deleted file mode 100644
index 33e4dd7..0000000
--- a/bot/index_templ.go
+++ /dev/null
@@ -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("catbase")
- 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("
")
- 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
- })
-}
diff --git a/bot/interfaces.go b/bot/interfaces.go
index c238409..3fb0224 100644
--- a/bot/interfaces.go
+++ b/bot/interfaces.go
@@ -4,6 +4,7 @@ package bot
import (
"github.com/gabriel-vasile/mimetype"
+ "github.com/velour/catbase/bot/web"
"net/http"
"regexp"
"strings"
@@ -168,20 +169,14 @@ type Bot interface {
// RegisterFilter creates a filter function for message processing
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
ListenAndServe()
// DefaultConnector returns the base connector, which may not be the only connector
DefaultConnector() Connector
- // GetWebNavigation returns the current known web endpoints
- GetWebNavigation() []EndPoint
+ // GetWeb returns the bot's webserver structure
+ GetWeb() *web.Web
// GetPassword generates a unique password for modification commands on the public website
GetPassword() string
diff --git a/bot/mock.go b/bot/mock.go
index cab54c9..9cdb757 100644
--- a/bot/mock.go
+++ b/bot/mock.go
@@ -4,6 +4,7 @@ package bot
import (
"fmt"
+ "github.com/velour/catbase/bot/web"
"net/http"
"regexp"
"strconv"
@@ -26,6 +27,8 @@ type MockBot struct {
Messages []string
Actions []string
Reactions []string
+
+ web *web.Web
}
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) 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) RegisterWebName(_ http.Handler, _, _ string) {}
-func (mb *MockBot) RegisterWeb(_ http.Handler, _ string) {}
-func (mb *MockBot) GetWebNavigation() []EndPoint { return nil }
+func (mb *MockBot) GetWeb() *web.Web { return mb.web }
func (mb *MockBot) Receive(c Connector, kind Kind, msg msg.Message, args ...any) bool {
return false
}
@@ -118,6 +119,7 @@ func NewMockBot() *MockBot {
Messages: 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
http.DefaultServeMux = new(http.ServeMux)
return &b
diff --git a/bot/nav.templ b/bot/nav.templ
deleted file mode 100644
index 100fc6c..0000000
--- a/bot/nav.templ
+++ /dev/null
@@ -1,25 +0,0 @@
-package bot
-
-templ (b *bot) Nav(currentPage string, items []EndPoint) {
-
-}
\ No newline at end of file
diff --git a/bot/nav_templ.go b/bot/nav_templ.go
deleted file mode 100644
index b23b217..0000000
--- a/bot/nav_templ.go
+++ /dev/null
@@ -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("")
- 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
- })
-}
diff --git a/bot/web.go b/bot/web.go
deleted file mode 100644
index 7898331..0000000
--- a/bot/web.go
+++ /dev/null
@@ -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 links
-// The parent