mirror of https://github.com/velour/catbase.git
bot: add ability to disable plugins per channel
admin: use 'enable/disable plugin <name>'
This commit is contained in:
parent
c68ca70964
commit
12ca34006f
45
bot/bot.go
45
bot/bot.go
|
@ -26,6 +26,9 @@ type bot struct {
|
|||
plugins map[string]Plugin
|
||||
pluginOrdering []string
|
||||
|
||||
// channel -> plugin
|
||||
pluginBlacklist map[string]bool
|
||||
|
||||
// Users holds information about all of our friends
|
||||
users []user.User
|
||||
// Represents the bot
|
||||
|
@ -80,6 +83,7 @@ func New(config *config.Config, connector Connector) Bot {
|
|||
config: config,
|
||||
plugins: make(map[string]Plugin),
|
||||
pluginOrdering: make([]string, 0),
|
||||
pluginBlacklist: make(map[string]bool),
|
||||
conn: connector,
|
||||
users: users,
|
||||
me: users[0],
|
||||
|
@ -92,6 +96,8 @@ func New(config *config.Config, connector Connector) Bot {
|
|||
|
||||
bot.migrateDB()
|
||||
|
||||
bot.RefreshPluginBlacklist()
|
||||
|
||||
http.HandleFunc("/", bot.serveRoot)
|
||||
|
||||
connector.RegisterEvent(bot.Receive)
|
||||
|
@ -127,6 +133,13 @@ func (b *bot) migrateDB() {
|
|||
);`); err != nil {
|
||||
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 variables table")
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a constructed handler to the bots handlers list
|
||||
|
@ -265,3 +278,35 @@ func (b *bot) GetPassword() string {
|
|||
func (b *bot) SetQuiet(status bool) {
|
||||
b.quiet = status
|
||||
}
|
||||
|
||||
func (b *bot) RefreshPluginBlacklist() error {
|
||||
blacklistItems := []struct {
|
||||
Channel string
|
||||
Name string
|
||||
}{}
|
||||
if err := b.DB().Select(&blacklistItems, `select channel, name from pluginBlacklist`); err != nil {
|
||||
return fmt.Errorf("%w", err)
|
||||
}
|
||||
b.pluginBlacklist = make(map[string]bool)
|
||||
for _, i := range blacklistItems {
|
||||
b.pluginBlacklist[i.Channel+i.Name] = true
|
||||
}
|
||||
log.Debug().Interface("blacklist", b.pluginBlacklist).Msgf("Refreshed plugin blacklist")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *bot) GetPluginNames() []string {
|
||||
names := []string{}
|
||||
for _, name := range b.pluginOrdering {
|
||||
names = append(names, pluginNameStem(name))
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
func (b *bot) onBlacklist(channel, plugin string) bool {
|
||||
return b.pluginBlacklist[channel+plugin]
|
||||
}
|
||||
|
||||
func pluginNameStem(name string) string {
|
||||
return strings.Split(strings.TrimPrefix(name, "*"), ".")[0]
|
||||
}
|
||||
|
|
|
@ -31,7 +31,11 @@ func (b *bot) Receive(conn Connector, kind Kind, msg msg.Message, args ...interf
|
|||
goto RET
|
||||
}
|
||||
|
||||
log.Debug().Msgf("checking blacklist %v", b.pluginBlacklist)
|
||||
for _, name := range b.pluginOrdering {
|
||||
if b.onBlacklist(msg.Channel, pluginNameStem(name)) {
|
||||
continue
|
||||
}
|
||||
if b.runCallback(conn, b.plugins[name], kind, msg, args...) {
|
||||
goto RET
|
||||
}
|
||||
|
@ -70,7 +74,7 @@ func (b *bot) checkHelp(conn Connector, channel string, parts []string) {
|
|||
// just print out a list of help topics
|
||||
topics := "Help topics: about variables"
|
||||
for name := range b.plugins {
|
||||
name = strings.Split(strings.TrimPrefix(name, "*"), ".")[0]
|
||||
name = pluginNameStem(name)
|
||||
topics = fmt.Sprintf("%s, %s", topics, name)
|
||||
}
|
||||
b.Send(conn, Message, channel, topics)
|
||||
|
|
|
@ -4,6 +4,7 @@ package bot
|
|||
|
||||
import (
|
||||
"github.com/jmoiron/sqlx"
|
||||
|
||||
"github.com/velour/catbase/bot/msg"
|
||||
"github.com/velour/catbase/bot/user"
|
||||
"github.com/velour/catbase/config"
|
||||
|
@ -69,6 +70,8 @@ type Bot interface {
|
|||
GetWebNavigation() []EndPoint
|
||||
GetPassword() string
|
||||
SetQuiet(bool)
|
||||
GetPluginNames() []string
|
||||
RefreshPluginBlacklist() error
|
||||
}
|
||||
|
||||
// Connector represents a server connection to a chat service
|
||||
|
|
|
@ -112,3 +112,6 @@ func NewMockBot() *MockBot {
|
|||
http.DefaultServeMux = new(http.ServeMux)
|
||||
return &b
|
||||
}
|
||||
|
||||
func (mb *MockBot) GetPluginNames() []string { return nil }
|
||||
func (mb *MockBot) RefreshPluginBlacklist() error { return nil }
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"html/template"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -51,6 +52,9 @@ var forbiddenKeys = map[string]bool{
|
|||
"meme.memes": true,
|
||||
}
|
||||
|
||||
var addBlacklist = regexp.MustCompile(`(?i)disable plugin (.*)`)
|
||||
var rmBlacklist = regexp.MustCompile(`(?i)enable plugin (.*)`)
|
||||
|
||||
// Message responds to the bot hook on recieving messages.
|
||||
// This function returns true if the plugin responds in a meaningful way to the users message.
|
||||
// Otherwise, the function returns false and the bot continues execution of other plugins.
|
||||
|
@ -103,6 +107,30 @@ func (p *AdminPlugin) message(conn bot.Connector, k bot.Kind, message msg.Messag
|
|||
return true
|
||||
}
|
||||
|
||||
if addBlacklist.MatchString(body) {
|
||||
submatches := addBlacklist.FindStringSubmatch(message.Body)
|
||||
plugin := submatches[1]
|
||||
if err := p.addBlacklist(message.Channel, plugin); err != nil {
|
||||
p.bot.Send(conn, bot.Message, message.Channel, fmt.Sprintf("I couldn't add that item: %s", err))
|
||||
log.Error().Err(err).Msgf("error adding blacklist item")
|
||||
return true
|
||||
}
|
||||
p.bot.Send(conn, bot.Message, message.Channel, fmt.Sprintf("%s disabled. Use `!enable plugin %s` to re-enable it.", plugin, plugin))
|
||||
return true
|
||||
}
|
||||
|
||||
if rmBlacklist.MatchString(body) {
|
||||
submatches := rmBlacklist.FindStringSubmatch(message.Body)
|
||||
plugin := submatches[1]
|
||||
if err := p.rmBlacklist(message.Channel, plugin); err != nil {
|
||||
p.bot.Send(conn, bot.Message, message.Channel, fmt.Sprintf("I couldn't remove that item: %s", err))
|
||||
log.Error().Err(err).Msgf("error removing blacklist item")
|
||||
return true
|
||||
}
|
||||
p.bot.Send(conn, bot.Message, message.Channel, fmt.Sprintf("%s enabled. Use `!disable plugin %s` to disable it.", plugin, plugin))
|
||||
return true
|
||||
}
|
||||
|
||||
if strings.ToLower(body) == "password" {
|
||||
p.bot.Send(conn, bot.Message, message.Channel, p.bot.GetPassword())
|
||||
return true
|
||||
|
@ -254,3 +282,32 @@ func (p *AdminPlugin) handleWebAPI(w http.ResponseWriter, r *http.Request) {
|
|||
j, _ := json.Marshal(configEntries)
|
||||
fmt.Fprintf(w, "%s", j)
|
||||
}
|
||||
|
||||
func (p *AdminPlugin) addBlacklist(channel, plugin string) error {
|
||||
if plugin == "admin" {
|
||||
return fmt.Errorf("you cannot disable the admin plugin")
|
||||
}
|
||||
return p.modBlacklist(`insert or replace into pluginBlacklist values (?, ?)`, channel, plugin)
|
||||
}
|
||||
|
||||
func (p *AdminPlugin) rmBlacklist(channel, plugin string) error {
|
||||
return p.modBlacklist(`delete from pluginBlacklist where channel=? and name=?`, channel, plugin)
|
||||
}
|
||||
|
||||
func (p *AdminPlugin) modBlacklist(query, channel, plugin string) error {
|
||||
plugins := p.bot.GetPluginNames()
|
||||
for _, pp := range plugins {
|
||||
if pp == plugin {
|
||||
if _, err := p.db.Exec(query, channel, plugin); err != nil {
|
||||
return fmt.Errorf("%w", err)
|
||||
}
|
||||
err := p.bot.RefreshPluginBlacklist()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
err := fmt.Errorf("unknown plugin named '%s'", plugin)
|
||||
return err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue