Merge pull request #132 from velour/configadmin

admin: add ability to get/set config values
This commit is contained in:
Chris Sexton 2019-01-21 16:30:19 -05:00 committed by GitHub
commit dbc3b3646b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 102 additions and 131 deletions

View File

@ -1,123 +0,0 @@
config = {
Channels = {
"#CatBaseTest"
},
TwitterConsumerSecret = "<Consumer Secret>",
Reminder = {
MaxBatchAdd = 10
},
Nick = "CatBaseTest",
IconURL = "http://placekitten.com/g/200/300",
LeftPad = {
Who = "person",
MaxLen = 50
},
Factoid = {
StartupFact = "speed test",
QuoteTime = 1,
QuoteChance = 0.99,
MinLen = 5
},
CommandChar = {
"!",
"¡"
},
FullName = "CatBase",
Your = {
MaxLength = 140,
DuckingChance = 0.5,
FuckingChance = 0.15,
YourChance = 0.4
},
Emojify = {
Chance = 0.02,
Scoreless = {
"a",
"it"
}
},
DB = {
File = "catbase.db",
Server = "127.0.0.1"
},
Plugins = {
},
Untappd = {
Freq = 3600,
Channels = {
},
Token = "<Your Token>"
},
LogLength = 50,
RatePerSec = 10,
Reaction = {
HarrassChance = 0.05,
GeneralChance = 0.01,
NegativeHarrassmentMultiplier = 2,
HarrassList = {
"msherms"
},
NegativeReactions = {
"bullshit",
"fake",
"tableflip",
"vomit"
},
PositiveReactions = {
"+1",
"authorized",
"aw_yea",
"joy"
}
},
TwitterUserKey = "<User Key>",
MainChannel = "#CatBaseTest",
TwitterUserSecret = "<User Secret>",
WelcomeMsgs = {
"Real men use screen, %s.",
"Joins upset the hivemind's OCD, %s.",
"Joins upset the hivemind's CDO, %s.",
"%s, I WILL CUT YOU!"
},
Bad = {
Msgs = {
},
Hosts = {
},
Nicks = {
}
},
Irc = {
Server = "ircserver:6697",
Pass = "CatBaseTest:test"
},
Slack = {
Token = "<your slack token>"
},
TwitterConsumerKey = "<Consumer Key>",
Babbler = {
DefaultUsers = {
"seabass"
}
},
Type = "slack",
Admins = {
"<Admin Nick>"
},
Stats = {
Sightings = {
"user"
},
DBPath = "stats.db"
},
HttpAddr = "127.0.0.1:1337",
Inventory = {
Max = 5
},
Sisyphus = {
MinDecrement = 10,
MinPush = 1
}
}
}

View File

@ -3,12 +3,14 @@
package admin package admin
import ( import (
"fmt"
"log" "log"
"strings" "strings"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"github.com/velour/catbase/bot" "github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg" "github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/config"
) )
// This is a admin plugin to serve as an example and quick copy/paste for new plugins. // This is a admin plugin to serve as an example and quick copy/paste for new plugins.
@ -16,6 +18,7 @@ import (
type AdminPlugin struct { type AdminPlugin struct {
Bot bot.Bot Bot bot.Bot
db *sqlx.DB db *sqlx.DB
cfg *config.Config
} }
// NewAdminPlugin creates a new AdminPlugin with the Plugin interface // NewAdminPlugin creates a new AdminPlugin with the Plugin interface
@ -23,11 +26,18 @@ func New(bot bot.Bot) *AdminPlugin {
p := &AdminPlugin{ p := &AdminPlugin{
Bot: bot, Bot: bot,
db: bot.DB(), db: bot.DB(),
cfg: bot.Config(),
} }
p.LoadData()
return p return p
} }
var forbiddenKeys = map[string]bool{
"twitch.authorization": true,
"twitch.clientid": true,
"untappd.token": true,
"slack.token": true,
}
// Message responds to the bot hook on recieving messages. // 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. // 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. // Otherwise, the function returns false and the bot continues execution of other plugins.
@ -38,6 +48,28 @@ func (p *AdminPlugin) Message(message msg.Message) bool {
return p.handleVariables(message) return p.handleVariables(message)
} }
if !message.Command {
return false
}
parts := strings.Split(body, " ")
if parts[0] == "set" && len(parts) > 2 && forbiddenKeys[parts[1]] {
p.Bot.SendMessage(message.Channel, "You cannot access that key")
return true
} else if parts[0] == "set" && len(parts) > 2 {
p.cfg.Set(parts[1], strings.Join(parts[2:], " "))
p.Bot.SendMessage(message.Channel, fmt.Sprintf("Set %s", parts[1]))
return true
}
if parts[0] == "get" && len(parts) == 2 && forbiddenKeys[parts[1]] {
p.Bot.SendMessage(message.Channel, "You cannot access that key")
return true
} else if parts[0] == "get" && len(parts) == 2 {
v := p.cfg.Get(parts[1])
p.Bot.SendMessage(message.Channel, fmt.Sprintf("%s: %s", parts[1], v))
return true
}
return false return false
} }
@ -88,13 +120,6 @@ func (p *AdminPlugin) handleVariables(message msg.Message) bool {
return true return true
} }
// LoadData imports any configuration data into the plugin. This is not strictly necessary other
// than the fact that the Plugin interface demands it exist. This may be deprecated at a later
// date.
func (p *AdminPlugin) LoadData() {
// This bot has no data to load
}
// Help responds to help requests. Every plugin must implement a help function. // Help responds to help requests. Every plugin must implement a help function.
func (p *AdminPlugin) Help(channel string, parts []string) { func (p *AdminPlugin) Help(channel string, parts []string) {
p.Bot.SendMessage(channel, "This does super secret things that you're not allowed to know about.") p.Bot.SendMessage(channel, "This does super secret things that you're not allowed to know about.")

View File

@ -0,0 +1,69 @@
package admin
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/bot/user"
)
var (
a *AdminPlugin
mb *bot.MockBot
)
func setup(t *testing.T) (*AdminPlugin, *bot.MockBot) {
mb = bot.NewMockBot()
a = New(mb)
mb.DB().MustExec(`delete from config`)
return a, mb
}
func makeMessage(payload string) msg.Message {
isCmd := strings.HasPrefix(payload, "!")
if isCmd {
payload = payload[1:]
}
return msg.Message{
User: &user.User{Name: "tester"},
Channel: "test",
Body: payload,
Command: isCmd,
}
}
func TestSet(t *testing.T) {
a, mb := setup(t)
expected := "test value"
a.Message(makeMessage("!set test.key " + expected))
actual := mb.Config().Get("test.key")
assert.Equal(t, expected, actual)
}
func TestGetValue(t *testing.T) {
a, mb := setup(t)
expected := "value"
mb.Config().Set("test.key", "value")
a.Message(makeMessage("!get test.key"))
assert.Len(t, mb.Messages, 1)
assert.Contains(t, mb.Messages[0], expected)
}
func TestGetEmpty(t *testing.T) {
a, mb := setup(t)
expected := "test.key: "
a.Message(makeMessage("!get test.key"))
assert.Len(t, mb.Messages, 1)
assert.Equal(t, expected, mb.Messages[0])
}
func TestGetForbidden(t *testing.T) {
a, mb := setup(t)
expected := "cannot access"
a.Message(makeMessage("!get slack.token"))
assert.Len(t, mb.Messages, 1)
assert.Contains(t, mb.Messages[0], expected)
}