From c47a4f7c6f956b07b62e77cafe02050f09e959d7 Mon Sep 17 00:00:00 2001 From: Chris Sexton Date: Wed, 21 Jul 2021 14:52:45 -0400 Subject: [PATCH] web: migrate endpoint registration to chi --- bot/bot.go | 36 +++-- bot/interfaces.go | 6 +- config/config.go | 10 +- connectors/discord/discord.go | 2 +- connectors/slackapp/slackApp.go | 1 - go.mod | 1 + go.sum | 2 + main.go | 7 +- plugins/admin/web.go | 17 ++- plugins/cli/cli.go | 8 +- plugins/counter/api.go | 128 +++++++++++++++++ plugins/counter/counter.go | 174 +++++++----------------- plugins/fact/factoid.go | 12 +- plugins/meme/webHandlers.go | 16 ++- plugins/newsbid/webshit/webshit_test.go | 2 +- plugins/remember/remember_test.go | 2 +- plugins/secrets/secrets.go | 14 +- 17 files changed, 260 insertions(+), 178 deletions(-) create mode 100644 plugins/counter/api.go diff --git a/bot/bot.go b/bot/bot.go index 51e5b9e..b59c29c 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -11,6 +11,8 @@ import ( "strings" "time" + "github.com/go-chi/chi/v5" + "github.com/go-chi/chi/v5/middleware" "github.com/jmoiron/sqlx" "github.com/rs/zerolog/log" "github.com/velour/catbase/bot/msg" @@ -59,6 +61,8 @@ type bot struct { passwordCreated time.Time quiet bool + + router *chi.Mux } type EndPoint struct { @@ -98,6 +102,7 @@ func New(config *config.Config, connector Connector) Bot { httpEndPoints: make([]EndPoint, 0), filters: make(map[string]func(string) string), callbacks: make(CallbackMap), + router: chi.NewRouter(), } bot.migrateDB() @@ -105,14 +110,31 @@ func New(config *config.Config, connector Connector) Bot { bot.RefreshPluginBlacklist() bot.RefreshPluginWhitelist() - http.HandleFunc("/", bot.serveRoot) - http.HandleFunc("/nav", bot.serveNav) + log.Debug().Msgf("created web router") + + bot.router.Use(middleware.Logger) + bot.router.Use(middleware.StripSlashes) + + bot.router.HandleFunc("/", bot.serveRoot) + bot.router.HandleFunc("/nav", bot.serveNav) connector.RegisterEvent(bot.Receive) return bot } +func (b *bot) ListenAndServe() { + addr := b.config.Get("HttpAddr", "127.0.0.1:1337") + log.Debug().Msgf("starting web service at %s", addr) + log.Fatal().Err(http.ListenAndServe(addr, b.router)).Msg("bot killed") +} + +func (b *bot) RegisterWeb(r http.Handler, root, name string) { + log.Debug().Msgf("registering %s at %s", name, root) + 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. @@ -143,19 +165,19 @@ func (b *bot) migrateDB() { name string, value string );`); err != nil { - log.Fatal().Err(err).Msgf("Initial DB migration create variables table") + log.Fatal().Err(err).Msgf("Initial db migration create variables table") } if _, err := b.DB().Exec(`create table if not exists pluginBlacklist ( channel string, name string, primary key (channel, name) );`); err != nil { - log.Fatal().Err(err).Msgf("Initial DB migration create blacklist table") + log.Fatal().Err(err).Msgf("Initial db migration create blacklist table") } if _, err := b.DB().Exec(`create table if not exists pluginWhitelist ( name string primary key );`); err != nil { - log.Fatal().Err(err).Msgf("Initial DB migration create whitelist table") + log.Fatal().Err(err).Msgf("Initial db migration create whitelist table") } } @@ -280,10 +302,6 @@ func (b *bot) Register(p Plugin, kind Kind, cb Callback) { b.RegisterRegex(p, kind, r, resp) } -func (b *bot) RegisterWeb(root, name string) { - b.httpEndPoints = append(b.httpEndPoints, EndPoint{name, root}) -} - // GetPassword returns a random password generated for the bot // Passwords expire in 24h and are used for the web interface func (b *bot) GetPassword() string { diff --git a/bot/interfaces.go b/bot/interfaces.go index a8ccfbf..531bb5c 100644 --- a/bot/interfaces.go +++ b/bot/interfaces.go @@ -3,6 +3,7 @@ package bot import ( + "net/http" "regexp" "github.com/jmoiron/sqlx" @@ -134,7 +135,10 @@ type Bot interface { RegisterFilter(string, func(string) string) // RegisterWeb records a web endpoint for the UI - RegisterWeb(string, string) + RegisterWeb(http.Handler, string, string) + + // Start the HTTP service + ListenAndServe() // DefaultConnector returns the base connector, which may not be the only connector DefaultConnector() Connector diff --git a/config/config.go b/config/config.go index ab61451..a9d58a2 100644 --- a/config/config.go +++ b/config/config.go @@ -36,7 +36,7 @@ type Secret struct { // GetFloat64 returns the config value for a string key // It will first look in the env vars for the key -// It will check the DB for the key if an env DNE +// It will check the db for the key if an env DNE // Finally, it will return a zero value if the key does not exist // It will attempt to convert the value to a float64 if it exists func (c *Config) GetFloat64(key string, fallback float64) float64 { @@ -49,7 +49,7 @@ func (c *Config) GetFloat64(key string, fallback float64) float64 { // GetInt64 returns the config value for a string key // It will first look in the env vars for the key -// It will check the DB for the key if an env DNE +// It will check the db for the key if an env DNE // Finally, it will return a zero value if the key does not exist // It will attempt to convert the value to an int if it exists func (c *Config) GetInt64(key string, fallback int64) int64 { @@ -62,7 +62,7 @@ func (c *Config) GetInt64(key string, fallback int64) int64 { // GetInt returns the config value for a string key // It will first look in the env vars for the key -// It will check the DB for the key if an env DNE +// It will check the db for the key if an env DNE // Finally, it will return a zero value if the key does not exist // It will attempt to convert the value to an int if it exists func (c *Config) GetInt(key string, fallback int) int { @@ -86,7 +86,7 @@ func envkey(key string) string { // GetString returns the config value for a string key // It will first look in the env vars for the key -// It will check the DB for the key if an env DNE +// It will check the db for the key if an env DNE // Finally, it will return a zero value if the key does not exist // It will convert the value to a string if it exists func (c *Config) GetString(key, fallback string) string { @@ -124,7 +124,7 @@ func (c *Config) GetMap(key string, fallback map[string]string) map[string]strin // GetArray returns the string slice config value for a string key // It will first look in the env vars for the key with ;; separated values // Look, I'm too lazy to do parsing to ensure that a comma is what the user meant -// It will check the DB for the key if an env DNE +// It will check the db for the key if an env DNE // Finally, it will return a zero value if the key does not exist // This will do no conversion. func (c *Config) GetArray(key string, fallback []string) []string { diff --git a/connectors/discord/discord.go b/connectors/discord/discord.go index 7f15b9e..2694f16 100644 --- a/connectors/discord/discord.go +++ b/connectors/discord/discord.go @@ -24,7 +24,7 @@ type Discord struct { } func New(config *config.Config) *Discord { - client, err := discordgo.New("Bot " + config.Get("DISCORDBOTTOKEN", "")) + client, err := discordgo.New("b " + config.Get("DISCORDBOTTOKEN", "")) if err != nil { log.Fatal().Err(err).Msg("Could not connect to Discord") } diff --git a/connectors/slackapp/slackApp.go b/connectors/slackapp/slackApp.go index d723c4b..09d4b40 100644 --- a/connectors/slackapp/slackApp.go +++ b/connectors/slackapp/slackApp.go @@ -696,7 +696,6 @@ func (s *SlackApp) Profile(identifier string) (user.User, error) { } for _, u := range users { - log.Debug().Str("Name", u.Name).Str("ID", u.ID).Msgf("Looking for %s", identifier) if u.Name == identifier || u.ID == identifier { return user.User{ ID: u.ID, diff --git a/go.mod b/go.mod index 12ac015..933be0c 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,7 @@ require ( github.com/dustin/gojson v0.0.0-20160307161227-2e71ec9dd5ad // indirect github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90 github.com/garyburd/go-oauth v0.0.0-20180319155456-bca2e7f09a17 // indirect + github.com/go-chi/chi/v5 v5.0.3 github.com/go-stack/stack v1.8.0 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gocolly/colly v1.2.0 diff --git a/go.sum b/go.sum index 66d962c..7d6ec64 100644 --- a/go.sum +++ b/go.sum @@ -45,6 +45,8 @@ github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90 h1:WXb3TSNmHp2vHoCro github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/garyburd/go-oauth v0.0.0-20180319155456-bca2e7f09a17 h1:GOfMz6cRgTJ9jWV0qAezv642OhPnKEG7gtUjJSdStHE= github.com/garyburd/go-oauth v0.0.0-20180319155456-bca2e7f09a17/go.mod h1:HfkOCN6fkKKaPSAeNq/er3xObxTW4VLeY6UUK895gLQ= +github.com/go-chi/chi/v5 v5.0.3 h1:khYQBdPivkYG1s1TAzDQG1f6eX4kD2TItYVZexL5rS4= +github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx+opk= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= diff --git a/main.go b/main.go index 063438c..c508924 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,6 @@ import ( "flag" "io" "math/rand" - "net/http" "os" "time" @@ -67,7 +66,7 @@ import ( var ( key = flag.String("set", "", "Configuration key to set") val = flag.String("val", "", "Configuration value to set") - initDB = flag.Bool("init", false, "Initialize the configuration DB") + initDB = flag.Bool("init", false, "Initialize the configuration db") prettyLog = flag.Bool("pretty", false, "Use pretty console logger") debug = flag.Bool("debug", false, "Turn on debug logging") ) @@ -169,7 +168,5 @@ func main() { b.Receive(client, bot.Startup, msg.Message{}) - addr := c.Get("HttpAddr", "127.0.0.1:1337") - log.Debug().Msgf("starting web service at %s", addr) - log.Fatal().Err(http.ListenAndServe(addr, nil)).Msg("bot killed") + b.ListenAndServe() } diff --git a/plugins/admin/web.go b/plugins/admin/web.go index 5d40267..de08bf6 100644 --- a/plugins/admin/web.go +++ b/plugins/admin/web.go @@ -9,18 +9,21 @@ import ( "net/http" "strings" + "github.com/go-chi/chi/v5" "github.com/rs/zerolog/log" "golang.org/x/crypto/bcrypt" ) func (p *AdminPlugin) registerWeb() { - http.HandleFunc("/vars/api", p.handleVarsAPI) - http.HandleFunc("/vars", p.handleVars) - p.bot.RegisterWeb("/vars", "Variables") - http.HandleFunc("/apppass/verify", p.handleAppPassCheck) - http.HandleFunc("/apppass/api", p.handleAppPassAPI) - http.HandleFunc("/apppass", p.handleAppPass) - p.bot.RegisterWeb("/apppass", "App Pass") + r := chi.NewRouter() + r.HandleFunc("/api", p.handleVarsAPI) + r.HandleFunc("/", p.handleVars) + p.bot.RegisterWeb(r, "/vars", "Variables") + r = chi.NewRouter() + r.HandleFunc("/verify", p.handleAppPassCheck) + r.HandleFunc("/api", p.handleAppPassAPI) + r.HandleFunc("/", p.handleAppPass) + p.bot.RegisterWeb(r, "/apppass", "App Pass") } func (p *AdminPlugin) handleAppPass(w http.ResponseWriter, r *http.Request) { diff --git a/plugins/cli/cli.go b/plugins/cli/cli.go index 2324236..16bcc68 100644 --- a/plugins/cli/cli.go +++ b/plugins/cli/cli.go @@ -8,6 +8,7 @@ import ( "net/http" "time" + "github.com/go-chi/chi/v5" "github.com/jmoiron/sqlx" "github.com/rs/zerolog/log" @@ -32,9 +33,10 @@ func New(b bot.Bot) *CliPlugin { } func (p *CliPlugin) registerWeb() { - http.HandleFunc("/cli/api", p.handleWebAPI) - http.HandleFunc("/cli", p.handleWeb) - p.bot.RegisterWeb("/cli", "CLI") + r := chi.NewRouter() + r.HandleFunc("/api", p.handleWebAPI) + r.HandleFunc("/", p.handleWeb) + p.bot.RegisterWeb(r, "/cli", "CLI") } func (p *CliPlugin) handleWebAPI(w http.ResponseWriter, r *http.Request) { diff --git a/plugins/counter/api.go b/plugins/counter/api.go new file mode 100644 index 0000000..66cab87 --- /dev/null +++ b/plugins/counter/api.go @@ -0,0 +1,128 @@ +package counter + +import ( + "encoding/json" + "fmt" + "net/http" + "time" + + "github.com/go-chi/chi/v5" + "github.com/rs/zerolog/log" + "github.com/velour/catbase/bot" + "github.com/velour/catbase/bot/msg" + "github.com/velour/catbase/bot/user" +) + +func (p *CounterPlugin) registerWeb() { + r := chi.NewRouter() + r.HandleFunc("/api/users/{user}/items/{item}/increment", p.mkIncrementAPI(1)) + r.HandleFunc("/api/users/{user}/items/{item}/decrement", p.mkIncrementAPI(-1)) + r.HandleFunc("/api", p.handleCounterAPI) + r.HandleFunc("/", p.handleCounter) + p.b.RegisterWeb(r, "/counter", "Counter") +} + +func (p *CounterPlugin) mkIncrementAPI(delta int) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + vars := map[string]string{} + userName := vars["user"] + itemName := vars["item"] + item, err := GetUserItem(p.db, userName, "", itemName) + if err != nil { + return + } + u := user.New(userName) + req := &bot.Request{ + Conn: p.b.DefaultConnector(), + Kind: bot.Message, + Msg: msg.Message{ + User: &u, + ChannelName: "#API", + Body: fmt.Sprintf("%s += %d", itemName, delta), + Time: time.Now(), + }, + Values: nil, + Args: nil, + } + item.UpdateDelta(req, delta) + msg := fmt.Sprintf("%s changed their %s counter by %d via the amazing %s API", + userName, itemName, delta, p.cfg.Get("nick", "catbase")) + for _, ch := range p.cfg.GetArray("channels", []string{}) { + p.b.Send(p.b.DefaultConnector(), bot.Message, ch, msg) + } + j, _ := json.Marshal(struct{ Status bool }{true}) + fmt.Fprint(w, string(j)) + } +} + +func (p *CounterPlugin) handleCounter(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, html) +} + +func (p *CounterPlugin) handleCounterAPI(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodPost { + info := struct { + User string + Thing string + Action string + Password string + }{} + decoder := json.NewDecoder(r.Body) + err := decoder.Decode(&info) + if err != nil { + w.WriteHeader(500) + fmt.Fprint(w, err) + return + } + log.Debug(). + Interface("postbody", info). + Msg("Got a POST") + if p.b.CheckPassword("", info.Password) { + w.WriteHeader(http.StatusForbidden) + j, _ := json.Marshal(struct{ Err string }{Err: "Invalid Password"}) + w.Write(j) + return + } + nick, id := p.resolveUser(bot.Request{Conn: p.b.DefaultConnector()}, info.User) + item, err := GetUserItem(p.db, nick, id, info.Thing) + if err != nil { + log.Error(). + Err(err). + Str("subject", info.User). + Str("itemName", info.Thing). + Msg("error finding item") + w.WriteHeader(404) + fmt.Fprint(w, err) + return + } + if info.Action == "++" { + item.UpdateDelta(nil, 1) + } else if info.Action == "--" { + item.UpdateDelta(nil, -1) + } else { + w.WriteHeader(400) + fmt.Fprint(w, "Invalid increment") + return + } + + } + all, err := GetAllItems(p.db) + if err != nil { + w.WriteHeader(500) + fmt.Fprint(w, err) + return + } + data, err := json.Marshal(all) + if err != nil { + w.WriteHeader(500) + fmt.Fprint(w, err) + return + } + fmt.Fprint(w, string(data)) +} + +type Update struct { + Who string + What string + Amount int +} diff --git a/plugins/counter/counter.go b/plugins/counter/counter.go index 36adf99..dcc87a8 100644 --- a/plugins/counter/counter.go +++ b/plugins/counter/counter.go @@ -2,15 +2,14 @@ package counter import ( "database/sql" - "encoding/json" "fmt" "math/rand" - "net/http" "regexp" "strconv" "strings" "github.com/rs/zerolog/log" + "github.com/velour/catbase/config" "github.com/jmoiron/sqlx" @@ -21,8 +20,9 @@ import ( // This is a counter plugin to count arbitrary things. type CounterPlugin struct { - Bot bot.Bot - DB *sqlx.DB + b bot.Bot + db *sqlx.DB + cfg *config.Config } type Item struct { @@ -50,7 +50,7 @@ func GetAllItems(db *sqlx.DB) ([]Item, error) { if err != nil { return nil, err } - // Don't forget to embed the DB into all of that shiz + // Don't forget to embed the db into all of that shiz for i := range items { items[i].DB = db } @@ -69,7 +69,7 @@ func GetItems(db *sqlx.DB, nick, id string) ([]Item, error) { if err != nil { return nil, err } - // Don't forget to embed the DB into all of that shiz + // Don't forget to embed the db into all of that shiz for i := range items { items[i].DB = db } @@ -254,7 +254,7 @@ func (i *Item) Delete() error { } func (p *CounterPlugin) migrate(r bot.Request) bool { - db := p.DB + db := p.db nicks := []string{} err := db.Select(&nicks, `select distinct nick from counter where userid is null`) @@ -321,8 +321,8 @@ func New(b bot.Bot) *CounterPlugin { } cp := &CounterPlugin{ - Bot: b, - DB: b.DB(), + b: b, + db: b.DB(), } b.RegisterRegex(cp, bot.Startup, regexp.MustCompile(`.*`), cp.migrate) @@ -367,15 +367,15 @@ func (p *CounterPlugin) mkAliasCmd(r bot.Request) bool { what := r.Values["what"] to := r.Values["to"] if what == "" || to == "" { - p.Bot.Send(r.Conn, bot.Message, fmt.Sprintf("You must provide all fields for an alias: %s", mkAliasRegex)) + p.b.Send(r.Conn, bot.Message, fmt.Sprintf("You must provide all fields for an alias: %s", mkAliasRegex)) return true } - if _, err := MkAlias(p.DB, what, to); err != nil { + if _, err := MkAlias(p.db, what, to); err != nil { log.Error().Err(err).Msg("Could not mkalias") - p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, "We're gonna need too much DB space to make an alias for your mom.") + p.b.Send(r.Conn, bot.Message, r.Msg.Channel, "We're gonna need too much db space to make an alias for your mom.") return true } - p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("Created alias %s -> %s", + p.b.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("Created alias %s -> %s", what, to)) return true } @@ -383,15 +383,15 @@ func (p *CounterPlugin) mkAliasCmd(r bot.Request) bool { func (p *CounterPlugin) rmAliasCmd(r bot.Request) bool { what := r.Values["what"] if what == "" { - p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, "You must specify an alias to remove.") + p.b.Send(r.Conn, bot.Message, r.Msg.Channel, "You must specify an alias to remove.") return true } - if err := RmAlias(p.DB, what); err != nil { + if err := RmAlias(p.db, what); err != nil { log.Error().Err(err).Msg("could not RmAlias") - p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, "`sudo rm your mom` => Nope, she's staying with me.") + p.b.Send(r.Conn, bot.Message, r.Msg.Channel, "`sudo rm your mom` => Nope, she's staying with me.") return true } - p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, "`sudo rm your mom`") + p.b.Send(r.Conn, bot.Message, r.Msg.Channel, "`sudo rm your mom`") return true } @@ -401,10 +401,10 @@ func (p *CounterPlugin) leaderboardCmd(r bot.Request) bool { what := r.Values["what"] if what == "" { - cmd = func() ([]Item, error) { return LeaderAll(p.DB) } + cmd = func() ([]Item, error) { return LeaderAll(p.db) } } else { itNameTxt = fmt.Sprintf(" for %s", what) - cmd = func() ([]Item, error) { return Leader(p.DB, what) } + cmd = func() ([]Item, error) { return Leader(p.db, what) } } its, err := cmd() @@ -412,7 +412,7 @@ func (p *CounterPlugin) leaderboardCmd(r bot.Request) bool { log.Error().Err(err).Msg("Error with leaderboard") return false } else if len(its) == 0 { - p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, "There are not enough entries for a leaderboard.") + p.b.Send(r.Conn, bot.Message, r.Msg.Channel, "There are not enough entries for a leaderboard.") return true } @@ -424,7 +424,7 @@ func (p *CounterPlugin) leaderboardCmd(r bot.Request) bool { it.Item, ) } - p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, out) + p.b.Send(r.Conn, bot.Message, r.Msg.Channel, out) return true } @@ -432,20 +432,20 @@ func (p *CounterPlugin) resetCmd(r bot.Request) bool { nick, id := p.resolveUser(r, "") channel := r.Msg.Channel - items, err := GetItems(p.DB, nick, id) + items, err := GetItems(p.db, nick, id) if err != nil { log.Error(). Err(err). Str("nick", nick). Msg("Error getting items to reset") - p.Bot.Send(r.Conn, bot.Message, channel, "Something is technically wrong with your counters.") + p.b.Send(r.Conn, bot.Message, channel, "Something is technically wrong with your counters.") return true } log.Debug().Msgf("Items: %+v", items) for _, item := range items { item.Delete() } - p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s, you are as new, my son.", nick)) + p.b.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s, you are as new, my son.", nick)) return true } @@ -466,14 +466,14 @@ func (p *CounterPlugin) inspectCmd(r bot.Request) bool { Str("id", id). Msg("Getting counter") // pull all of the items associated with "subject" - items, err := GetItems(p.DB, nick, id) + items, err := GetItems(p.db, nick, id) if err != nil { log.Error(). Err(err). Str("nick", nick). Str("id", id). Msg("Error retrieving items") - p.Bot.Send(c, bot.Message, channel, "Something went wrong finding that counter;") + p.b.Send(c, bot.Message, channel, "Something went wrong finding that counter;") return true } @@ -493,11 +493,11 @@ func (p *CounterPlugin) inspectCmd(r bot.Request) bool { resp += "." if count == 0 { - p.Bot.Send(c, bot.Message, channel, fmt.Sprintf("%s has no counters.", nick)) + p.b.Send(c, bot.Message, channel, fmt.Sprintf("%s has no counters.", nick)) return true } - p.Bot.Send(c, bot.Message, channel, resp) + p.b.Send(c, bot.Message, channel, resp) return true } @@ -507,7 +507,7 @@ func (p *CounterPlugin) clearCmd(r bot.Request) bool { channel := r.Msg.Channel c := r.Conn - it, err := GetUserItem(p.DB, nick, id, itemName) + it, err := GetUserItem(p.db, nick, id, itemName) if err != nil { log.Error(). Err(err). @@ -515,7 +515,7 @@ func (p *CounterPlugin) clearCmd(r bot.Request) bool { Str("id", id). Str("itemName", itemName). Msg("Error getting item to remove") - p.Bot.Send(c, bot.Message, channel, "Something went wrong removing that counter;") + p.b.Send(c, bot.Message, channel, "Something went wrong removing that counter;") return true } err = it.Delete() @@ -526,11 +526,11 @@ func (p *CounterPlugin) clearCmd(r bot.Request) bool { Str("id", id). Str("itemName", itemName). Msg("Error removing item") - p.Bot.Send(c, bot.Message, channel, "Something went wrong removing that counter;") + p.b.Send(c, bot.Message, channel, "Something went wrong removing that counter;") return true } - p.Bot.Send(c, bot.Action, channel, fmt.Sprintf("chops a few %s out of his brain", + p.b.Send(c, bot.Action, channel, fmt.Sprintf("chops a few %s out of his brain", itemName)) return true } @@ -545,10 +545,10 @@ func (p *CounterPlugin) countCmd(r bot.Request) bool { } var item Item - item, err := GetUserItem(p.DB, nick, id, itemName) + item, err := GetUserItem(p.db, nick, id, itemName) switch { case err == sql.ErrNoRows: - p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("I don't think %s has any %s.", + p.b.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("I don't think %s has any %s.", nick, itemName)) return true case err != nil: @@ -561,7 +561,7 @@ func (p *CounterPlugin) countCmd(r bot.Request) bool { return true } - p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("%s has %d %s.", nick, item.Count, + p.b.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("%s has %d %s.", nick, item.Count, itemName)) return true @@ -575,7 +575,7 @@ func (p *CounterPlugin) incrementCmd(r bot.Request) bool { itemName := r.Values["thing"] channel := r.Msg.Channel // ++ those fuckers - item, err := GetUserItem(p.DB, nick, id, itemName) + item, err := GetUserItem(p.db, nick, id, itemName) if err != nil { log.Error(). Err(err). @@ -588,7 +588,7 @@ func (p *CounterPlugin) incrementCmd(r bot.Request) bool { } log.Debug().Msgf("About to update item: %#v", item) item.UpdateDelta(&r, 1) - p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", nick, + p.b.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", nick, item.Count, item.Item)) return true } @@ -601,7 +601,7 @@ func (p *CounterPlugin) decrementCmd(r bot.Request) bool { itemName := r.Values["thing"] channel := r.Msg.Channel // -- those fuckers - item, err := GetUserItem(p.DB, nick, id, itemName) + item, err := GetUserItem(p.db, nick, id, itemName) if err != nil { log.Error(). Err(err). @@ -613,7 +613,7 @@ func (p *CounterPlugin) decrementCmd(r bot.Request) bool { return false } item.UpdateDelta(&r, -1) - p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", nick, + p.b.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", nick, item.Count, item.Item)) return true } @@ -623,7 +623,7 @@ func (p *CounterPlugin) addToCmd(r bot.Request) bool { itemName := r.Values["thing"] channel := r.Msg.Channel // += those fuckers - item, err := GetUserItem(p.DB, nick, id, itemName) + item, err := GetUserItem(p.db, nick, id, itemName) if err != nil { log.Error(). Err(err). @@ -637,7 +637,7 @@ func (p *CounterPlugin) addToCmd(r bot.Request) bool { n, _ := strconv.Atoi(r.Values["amount"]) log.Debug().Msgf("About to update item by %d: %#v", n, item) item.UpdateDelta(&r, n) - p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", nick, + p.b.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", nick, item.Count, item.Item)) return true } @@ -647,7 +647,7 @@ func (p *CounterPlugin) removeFromCmd(r bot.Request) bool { itemName := r.Values["thing"] channel := r.Msg.Channel // -= those fuckers - item, err := GetUserItem(p.DB, nick, id, itemName) + item, err := GetUserItem(p.db, nick, id, itemName) if err != nil { log.Error(). Err(err). @@ -661,19 +661,19 @@ func (p *CounterPlugin) removeFromCmd(r bot.Request) bool { n, _ := strconv.Atoi(r.Values["amount"]) log.Debug().Msgf("About to update item by -%d: %#v", n, item) item.UpdateDelta(&r, -n) - p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", nick, + p.b.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", nick, item.Count, item.Item)) return true } // Help responds to help requests. Every plugin must implement a help function. func (p *CounterPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool { - p.Bot.Send(c, bot.Message, message.Channel, "You can set counters incrementally by using "+ + p.b.Send(c, bot.Message, message.Channel, "You can set counters incrementally by using "+ "`++` and `--`. You can see all of your counters using "+ "`inspect`, erase them with `clear`, and view single counters with "+ "`count`.") - p.Bot.Send(c, bot.Message, message.Channel, "You can create aliases with `!mkalias `") - p.Bot.Send(c, bot.Message, message.Channel, "You can remove aliases with `!rmalias `") + p.b.Send(c, bot.Message, message.Channel, "You can create aliases with `!mkalias `") + p.b.Send(c, bot.Message, message.Channel, "You can remove aliases with `!rmalias `") return true } @@ -688,7 +688,7 @@ func (p *CounterPlugin) teaMatchCmd(r bot.Request) bool { itemName := strings.ToLower(submatches[1]) // We will specifically allow :tea: to keep compatability - item, err := GetUserItem(p.DB, nick, id, itemName) + item, err := GetUserItem(p.db, nick, id, itemName) if err != nil || (item.Count == 0 && item.Item != ":tea:") { log.Error(). Err(err). @@ -703,7 +703,7 @@ func (p *CounterPlugin) teaMatchCmd(r bot.Request) bool { delta = -1 } item.UpdateDelta(&r, delta) - p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s... %s has %d %s", + p.b.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s... %s has %d %s", strings.Join(everyDayImShuffling([]string{"bleep", "bloop", "blop"}), "-"), nick, item.Count, itemName)) return true } @@ -717,84 +717,6 @@ func everyDayImShuffling(vals []string) []string { return ret } -func (p *CounterPlugin) registerWeb() { - http.HandleFunc("/counter/api", p.handleCounterAPI) - http.HandleFunc("/counter", p.handleCounter) - p.Bot.RegisterWeb("/counter", "Counter") -} - -func (p *CounterPlugin) handleCounter(w http.ResponseWriter, r *http.Request) { - fmt.Fprint(w, html) -} - -func (p *CounterPlugin) handleCounterAPI(w http.ResponseWriter, r *http.Request) { - if r.Method == http.MethodPost { - info := struct { - User string - Thing string - Action string - Password string - }{} - decoder := json.NewDecoder(r.Body) - err := decoder.Decode(&info) - if err != nil { - w.WriteHeader(500) - fmt.Fprint(w, err) - return - } - log.Debug(). - Interface("postbody", info). - Msg("Got a POST") - if p.Bot.CheckPassword("", info.Password) { - w.WriteHeader(http.StatusForbidden) - j, _ := json.Marshal(struct{ Err string }{Err: "Invalid Password"}) - w.Write(j) - return - } - nick, id := p.resolveUser(bot.Request{Conn: p.Bot.DefaultConnector()}, info.User) - item, err := GetUserItem(p.DB, nick, id, info.Thing) - if err != nil { - log.Error(). - Err(err). - Str("subject", info.User). - Str("itemName", info.Thing). - Msg("error finding item") - w.WriteHeader(404) - fmt.Fprint(w, err) - return - } - if info.Action == "++" { - item.UpdateDelta(nil, 1) - } else if info.Action == "--" { - item.UpdateDelta(nil, -1) - } else { - w.WriteHeader(400) - fmt.Fprint(w, "Invalid increment") - return - } - - } - all, err := GetAllItems(p.DB) - if err != nil { - w.WriteHeader(500) - fmt.Fprint(w, err) - return - } - data, err := json.Marshal(all) - if err != nil { - w.WriteHeader(500) - fmt.Fprint(w, err) - return - } - fmt.Fprint(w, string(data)) -} - -type Update struct { - Who string - What string - Amount int -} - type updateFunc func(bot.Request, Update) var updateFuncs = []updateFunc{} diff --git a/plugins/fact/factoid.go b/plugins/fact/factoid.go index 91ad6d2..0794f1d 100644 --- a/plugins/fact/factoid.go +++ b/plugins/fact/factoid.go @@ -14,6 +14,7 @@ import ( "strings" "time" + "github.com/go-chi/chi/v5" "github.com/rs/zerolog/log" "github.com/jmoiron/sqlx" @@ -43,7 +44,7 @@ type alias struct { } func (a *alias) resolve(db *sqlx.DB) (*Factoid, error) { - // perform DB query to fill the To field + // perform db query to fill the To field q := `select fact, next from factoid_alias where fact=?` var next alias err := db.Get(&next, q, a.Next) @@ -801,10 +802,11 @@ func (p *FactoidPlugin) factTimer(c bot.Connector, channel string) { // Register any web URLs desired func (p *FactoidPlugin) registerWeb() { - http.HandleFunc("/factoid/api", p.serveAPI) - http.HandleFunc("/factoid/req", p.serveQuery) - http.HandleFunc("/factoid", p.serveQuery) - p.Bot.RegisterWeb("/factoid", "Factoid") + r := chi.NewRouter() + r.HandleFunc("/api", p.serveAPI) + r.HandleFunc("/req", p.serveQuery) + r.HandleFunc("/", p.serveQuery) + p.Bot.RegisterWeb(r, "/factoid", "Factoid") } func linkify(text string) template.HTML { diff --git a/plugins/meme/webHandlers.go b/plugins/meme/webHandlers.go index cc4ae5e..8ab0cdd 100644 --- a/plugins/meme/webHandlers.go +++ b/plugins/meme/webHandlers.go @@ -7,19 +7,21 @@ import ( "net/url" "sort" + "github.com/go-chi/chi/v5" "github.com/rs/zerolog/log" "github.com/velour/catbase/bot" ) func (p *MemePlugin) registerWeb(c bot.Connector) { - http.HandleFunc("/slash/meme", p.slashMeme(c)) - http.HandleFunc("/meme/img/", p.img) - http.HandleFunc("/meme/all", p.all) - http.HandleFunc("/meme/add", p.addMeme) - http.HandleFunc("/meme/rm", p.rmMeme) - http.HandleFunc("/meme", p.webRoot) - p.bot.RegisterWeb("/meme", "Memes") + r := chi.NewRouter() + r.HandleFunc("/slash", p.slashMeme(c)) + r.HandleFunc("/img", p.img) + r.HandleFunc("/all", p.all) + r.HandleFunc("/add", p.addMeme) + r.HandleFunc("/rm", p.rmMeme) + r.HandleFunc("/", p.webRoot) + p.bot.RegisterWeb(r, "/meme", "Memes") } type webResp struct { diff --git a/plugins/newsbid/webshit/webshit_test.go b/plugins/newsbid/webshit/webshit_test.go index 42e08ce..d782734 100644 --- a/plugins/newsbid/webshit/webshit_test.go +++ b/plugins/newsbid/webshit/webshit_test.go @@ -2,6 +2,6 @@ package webshit //func TestWebshit_Check(t *testing.T) { // mb := bot.NewMockBot() -// ws := New(mb.DB()) +// ws := New(mb.db()) // ws.checkBids() //} diff --git a/plugins/remember/remember_test.go b/plugins/remember/remember_test.go index 262f2e3..5f16a9c 100644 --- a/plugins/remember/remember_test.go +++ b/plugins/remember/remember_test.go @@ -34,7 +34,7 @@ func makeMessage(nick, payload string, r *regexp.Regexp) bot.Request { func makePlugin(t *testing.T) (*RememberPlugin, *fact.FactoidPlugin, *bot.MockBot) { mb := bot.NewMockBot() - f := fact.New(mb) // for DB table + f := fact.New(mb) // for db table p := New(mb) assert.NotNil(t, p) return p, f, mb diff --git a/plugins/secrets/secrets.go b/plugins/secrets/secrets.go index a3adf70..e5dbc05 100644 --- a/plugins/secrets/secrets.go +++ b/plugins/secrets/secrets.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" + "github.com/go-chi/chi/v5" "github.com/jmoiron/sqlx" "github.com/rs/zerolog/log" "github.com/velour/catbase/bot" @@ -28,16 +29,17 @@ func New(b bot.Bot) *SecretsPlugin { } func (p *SecretsPlugin) registerWeb() { - http.HandleFunc("/secrets/add", p.handleRegister) - http.HandleFunc("/secrets/remove", p.handleRemove) - http.HandleFunc("/secrets/all", p.handleAll) - http.HandleFunc("/secrets/test", func(w http.ResponseWriter, r *http.Request) { + r := chi.NewRouter() + r.HandleFunc("/add", p.handleRegister) + 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) }) - http.HandleFunc("/secrets", p.handleIndex) - p.b.RegisterWeb("/secrets", "Secrets") + r.HandleFunc("/", p.handleIndex) + p.b.RegisterWeb(r, "/secrets", "Secrets") } func (p *SecretsPlugin) registerSecret(key, value string) error {