bettercap/modules/ui/ui.go
Simone Margaritelli d8aeecb99f new: embedded ui
2024-08-21 17:33:47 +02:00

115 lines
2.1 KiB
Go

package ui
import (
"context"
"embed"
"fmt"
"io/fs"
"net/http"
"time"
"github.com/bettercap/bettercap/v2/session"
)
var (
//go:embed ui/dist/ui
web embed.FS
)
type UIModule struct {
session.SessionModule
server *http.Server
}
func NewUIModule(s *session.Session) *UIModule {
mod := &UIModule{
SessionModule: session.NewSessionModule("ui", s),
server: &http.Server{},
}
mod.SessionModule.Requires("api.rest")
mod.AddHandler(session.NewModuleHandler("ui on", "",
"Start the web user interface.",
func(args []string) error {
return mod.Start()
}))
mod.AddHandler(session.NewModuleHandler("ui off", "",
"Stop the web user interface.",
func(args []string) error {
return mod.Stop()
}))
mod.AddParam(session.NewStringParameter("ui.address",
"127.0.0.1",
session.IPv4Validator,
"Address to bind the web ui to."))
mod.AddParam(session.NewIntParameter("ui.port",
"8080",
"Port to bind the web ui server to."))
return mod
}
func (mod *UIModule) Name() string {
return "ui"
}
func (mod *UIModule) Description() string {
return "Web User Interface."
}
func (mod *UIModule) Author() string {
return "Simone Margaritelli <evilsocket@gmail.com>"
}
func (mod *UIModule) Configure() (err error) {
var ip string
var port int
if mod.Running() {
return session.ErrAlreadyStarted(mod.Name())
} else if err, ip = mod.StringParam("ui.address"); err != nil {
return err
} else if err, port = mod.IntParam("ui.port"); err != nil {
return err
}
mod.server.Addr = fmt.Sprintf("%s:%d", ip, port)
dist, _ := fs.Sub(web, "ui/dist/ui")
mod.server.Handler = http.FileServer(http.FS(dist))
return nil
}
func (mod *UIModule) Start() error {
if err := mod.Configure(); err != nil {
return err
}
mod.SetRunning(true, func() {
var err error
mod.Info("web ui starting on http://%s", mod.server.Addr)
err = mod.server.ListenAndServe()
if err != nil && err != http.ErrServerClosed {
panic(err)
}
})
return nil
}
func (mod *UIModule) Stop() error {
return mod.SetRunning(false, func() {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
mod.server.Shutdown(ctx)
})
}