mirror of https://github.com/velour/catbase.git
babbler: Add all users in chan, add cfg'd users
Also misc small updates to the mock object for easier config usage
This commit is contained in:
parent
8c5a446b75
commit
e6324ad5a2
|
@ -16,11 +16,13 @@ type MockBot struct {
|
||||||
mock.Mock
|
mock.Mock
|
||||||
db *sqlx.DB
|
db *sqlx.DB
|
||||||
|
|
||||||
|
Cfg config.Config
|
||||||
|
|
||||||
Messages []string
|
Messages []string
|
||||||
Actions []string
|
Actions []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mb *MockBot) Config() *config.Config { return &config.Config{} }
|
func (mb *MockBot) Config() *config.Config { return &mb.Cfg }
|
||||||
func (mb *MockBot) DBVersion() int64 { return 1 }
|
func (mb *MockBot) DBVersion() int64 { return 1 }
|
||||||
func (mb *MockBot) DB() *sqlx.DB { return mb.db }
|
func (mb *MockBot) DB() *sqlx.DB { return mb.db }
|
||||||
func (mb *MockBot) Who(string) []user.User { return []user.User{} }
|
func (mb *MockBot) Who(string) []user.User { return []user.User{} }
|
||||||
|
|
|
@ -64,6 +64,9 @@ type Config struct {
|
||||||
QuoteTime int
|
QuoteTime int
|
||||||
StartupFact string
|
StartupFact string
|
||||||
}
|
}
|
||||||
|
Babbler struct {
|
||||||
|
DefaultUsers []string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Readconfig loads the config data out of a JSON file located in cfile
|
// Readconfig loads the config data out of a JSON file located in cfile
|
||||||
|
|
|
@ -58,5 +58,10 @@
|
||||||
"QuoteTime": 1,
|
"QuoteTime": 1,
|
||||||
"StartupFact": "speed test",
|
"StartupFact": "speed test",
|
||||||
"MinLen": 5
|
"MinLen": 5
|
||||||
|
},
|
||||||
|
"Babbler": {
|
||||||
|
"DefaultUsers": [
|
||||||
|
"seabass"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,59 +8,79 @@ import (
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"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/bot/user"
|
||||||
|
"github.com/velour/catbase/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BabblerPlugin struct {
|
type BabblerPlugin struct {
|
||||||
Bot bot.Bot
|
Bot bot.Bot
|
||||||
db *sqlx.DB
|
db *sqlx.DB
|
||||||
|
config *config.Config
|
||||||
babblers map[string]*babbler
|
babblers map[string]*babbler
|
||||||
}
|
}
|
||||||
|
|
||||||
type babbler struct {
|
type babbler struct {
|
||||||
start *node
|
start *node
|
||||||
end *node
|
end *node
|
||||||
lookup map[string]*node
|
lookup map[string]*node
|
||||||
}
|
}
|
||||||
|
|
||||||
type node struct {
|
type node struct {
|
||||||
wordFrequency int
|
wordFrequency int
|
||||||
arcs map[string]*arc
|
arcs map[string]*arc
|
||||||
}
|
}
|
||||||
|
|
||||||
type arc struct {
|
type arc struct {
|
||||||
transitionFrequency int
|
transitionFrequency int
|
||||||
next *node
|
next *node
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(bot bot.Bot) *BabblerPlugin {
|
func New(bot bot.Bot) *BabblerPlugin {
|
||||||
plugin := &BabblerPlugin{
|
plugin := &BabblerPlugin{
|
||||||
Bot: bot,
|
Bot: bot,
|
||||||
db: bot.DB(),
|
db: bot.DB(),
|
||||||
|
config: bot.Config(),
|
||||||
babblers: map[string]*babbler{},
|
babblers: map[string]*babbler{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// this who string isn't escaped, just sooo, you know.
|
|
||||||
babbler, err := getMarkovChain(plugin.db, "seabass")
|
|
||||||
if err == nil {
|
|
||||||
plugin.babblers["seabass"] = babbler
|
|
||||||
} else {
|
|
||||||
plugin.babblers["seabass"] = newBabbler()
|
|
||||||
}
|
|
||||||
|
|
||||||
return plugin
|
return plugin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *BabblerPlugin) makeBabbler(newUser user.User) {
|
||||||
|
name := newUser.Name
|
||||||
|
babbler, err := getMarkovChain(p.db, name)
|
||||||
|
if err == nil {
|
||||||
|
p.babblers[name] = babbler
|
||||||
|
} else {
|
||||||
|
p.babblers[name] = newBabbler()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *BabblerPlugin) makeBabblers(newUser user.User) {
|
||||||
|
users := p.Bot.Who(p.config.MainChannel)
|
||||||
|
users = append(users, newUser)
|
||||||
|
for _, name := range p.config.Babbler.DefaultUsers {
|
||||||
|
users = append(users, user.New(name))
|
||||||
|
}
|
||||||
|
for _, u := range users {
|
||||||
|
p.makeBabbler(u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (p *BabblerPlugin) Message(message msg.Message) bool {
|
func (p *BabblerPlugin) Message(message msg.Message) bool {
|
||||||
|
if len(p.babblers) == 0 {
|
||||||
|
p.makeBabblers(*message.User)
|
||||||
|
} else if _, ok := p.babblers[message.User.Name]; !ok {
|
||||||
|
p.makeBabbler(*message.User)
|
||||||
|
}
|
||||||
|
|
||||||
lowercase := strings.ToLower(message.Body)
|
lowercase := strings.ToLower(message.Body)
|
||||||
tokens := strings.Fields(lowercase)
|
tokens := strings.Fields(lowercase)
|
||||||
|
|
||||||
if _, ok := p.babblers[message.User.Name]; ok {
|
addToMarkovChain(p.babblers[message.User.Name], lowercase)
|
||||||
addToMarkovChain(p.babblers[message.User.Name], lowercase)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(tokens) == 4 && strings.Contains(lowercase, "initialize babbler for ") {
|
if len(tokens) == 4 && strings.Contains(lowercase, "initialize babbler for ") {
|
||||||
who := tokens[len(tokens)-1]
|
who := tokens[len(tokens)-1]
|
||||||
|
@ -71,20 +91,24 @@ func (p *BabblerPlugin) Message(message msg.Message) bool {
|
||||||
} else {
|
} else {
|
||||||
p.babblers[who] = newBabbler()
|
p.babblers[who] = newBabbler()
|
||||||
}
|
}
|
||||||
|
p.Bot.SendMessage(message.Channel, "Okay.")
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(tokens) == 2 && tokens[1] == "says" {
|
if len(tokens) == 2 && tokens[1] == "says" {
|
||||||
if _, ok := p.babblers[tokens[0]]; ok {
|
saying := p.babble(tokens[0])
|
||||||
p.Bot.SendMessage(message.Channel, p.babble(tokens[0]))
|
if saying == "" {
|
||||||
return true
|
p.Bot.SendMessage(message.Channel, "Ze ain't said nothin'")
|
||||||
}
|
}
|
||||||
|
p.Bot.SendMessage(message.Channel, saying)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BabblerPlugin) Help(channel string, parts []string) {
|
func (p *BabblerPlugin) Help(channel string, parts []string) {
|
||||||
p.Bot.SendMessage(channel, "seabass says")
|
p.Bot.SendMessage(channel, "initialize babbler for seabass\n\nseabass says")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BabblerPlugin) Event(kind string, message msg.Message) bool {
|
func (p *BabblerPlugin) Event(kind string, message msg.Message) bool {
|
||||||
|
@ -109,7 +133,7 @@ func addToMarkovChain(babble *babbler, phrase string) {
|
||||||
if _, ok := babble.lookup[words[i]]; !ok {
|
if _, ok := babble.lookup[words[i]]; !ok {
|
||||||
babble.lookup[words[i]] = &node{
|
babble.lookup[words[i]] = &node{
|
||||||
wordFrequency: 1,
|
wordFrequency: 1,
|
||||||
arcs: map[string]*arc{},
|
arcs: map[string]*arc{},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
babble.lookup[words[i]].wordFrequency++
|
babble.lookup[words[i]].wordFrequency++
|
||||||
|
@ -119,7 +143,7 @@ func addToMarkovChain(babble *babbler, phrase string) {
|
||||||
if _, ok := prev.arcs[words[i]]; !ok {
|
if _, ok := prev.arcs[words[i]]; !ok {
|
||||||
prev.arcs[words[i]] = &arc{
|
prev.arcs[words[i]] = &arc{
|
||||||
transitionFrequency: 1,
|
transitionFrequency: 1,
|
||||||
next: babble.lookup[words[i]],
|
next: babble.lookup[words[i]],
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
prev.arcs[words[i]].transitionFrequency++
|
prev.arcs[words[i]].transitionFrequency++
|
||||||
|
@ -131,7 +155,7 @@ func addToMarkovChain(babble *babbler, phrase string) {
|
||||||
if _, ok := prev.arcs[""]; !ok {
|
if _, ok := prev.arcs[""]; !ok {
|
||||||
prev.arcs[""] = &arc{
|
prev.arcs[""] = &arc{
|
||||||
transitionFrequency: 1,
|
transitionFrequency: 1,
|
||||||
next: babble.end,
|
next: babble.end,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
prev.arcs[""].transitionFrequency++
|
prev.arcs[""].transitionFrequency++
|
||||||
|
@ -139,15 +163,15 @@ func addToMarkovChain(babble *babbler, phrase string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBabbler() *babbler {
|
func newBabbler() *babbler {
|
||||||
return &babbler {
|
return &babbler{
|
||||||
start: &node {
|
start: &node{
|
||||||
wordFrequency: 0,
|
wordFrequency: 0,
|
||||||
arcs: map[string]*arc{},
|
arcs: map[string]*arc{},
|
||||||
},
|
},
|
||||||
end: &node {
|
end: &node{
|
||||||
wordFrequency: 0,
|
wordFrequency: 0,
|
||||||
arcs: map[string]*arc{},
|
arcs: map[string]*arc{},
|
||||||
},
|
},
|
||||||
lookup: map[string]*node{},
|
lookup: map[string]*node{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,10 +28,12 @@ func makeMessage(payload string) msg.Message {
|
||||||
func TestBabbler(t *testing.T) {
|
func TestBabbler(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
c := New(mb)
|
c := New(mb)
|
||||||
|
c.config.Babbler.DefaultUsers = []string{"seabass"}
|
||||||
assert.NotNil(t, c)
|
assert.NotNil(t, c)
|
||||||
seabass := makeMessage("This is a message")
|
seabass := makeMessage("This is a message")
|
||||||
seabass.User = &user.User{Name: "seabass"}
|
seabass.User = &user.User{Name: "seabass"}
|
||||||
res := c.Message(seabass)
|
res := c.Message(seabass)
|
||||||
|
assert.Len(t, c.babblers, 1)
|
||||||
seabass.Body = "This is another message"
|
seabass.Body = "This is another message"
|
||||||
res = c.Message(seabass)
|
res = c.Message(seabass)
|
||||||
seabass.Body = "This is a long message"
|
seabass.Body = "This is a long message"
|
||||||
|
|
|
@ -258,9 +258,14 @@ func (s *Slack) Who(id string) []string {
|
||||||
u := s.url + "channels.info"
|
u := s.url + "channels.info"
|
||||||
resp, err := http.PostForm(u,
|
resp, err := http.PostForm(u,
|
||||||
url.Values{"token": {s.config.Slack.Token}, "channel": {id}})
|
url.Values{"token": {s.config.Slack.Token}, "channel": {id}})
|
||||||
if err != nil || resp.StatusCode != 200 {
|
if err != nil {
|
||||||
log.Printf("Error posting user info request: %d %s",
|
log.Printf("Error posting user info request: %s",
|
||||||
resp.StatusCode, err)
|
err)
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
log.Printf("Error posting user info request: %d",
|
||||||
|
resp.StatusCode)
|
||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
Loading…
Reference in New Issue