mirror of https://github.com/velour/catbase.git
wip but tests seem to pass
This commit is contained in:
parent
748e39c290
commit
84a2f54a6b
|
@ -115,6 +115,7 @@ func NewMockBot() *MockBot {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
log.Debug().Msgf("MockBot temp store: %s", storeFile.Name())
|
||||||
cfg := config.ReadConfig("file::memory:?mode=memory&cache=shared", storeFile.Name())
|
cfg := config.ReadConfig("file::memory:?mode=memory&cache=shared", storeFile.Name())
|
||||||
b := MockBot{
|
b := MockBot{
|
||||||
Cfg: cfg,
|
Cfg: cfg,
|
||||||
|
|
|
@ -1,13 +1,20 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSetGet(t *testing.T) {
|
func TestSetGet(t *testing.T) {
|
||||||
cfg := ReadConfig(":memory:")
|
storeFile, err := ioutil.TempFile(os.TempDir(), "prefix-")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer os.Remove(storeFile.Name())
|
||||||
|
cfg := ReadConfig(":memory:", storeFile.Name())
|
||||||
expected := "value"
|
expected := "value"
|
||||||
cfg.Set("test", expected)
|
cfg.Set("test", expected)
|
||||||
actual := cfg.Get("test", "NOPE")
|
actual := cfg.Get("test", "NOPE")
|
||||||
|
@ -15,7 +22,12 @@ func TestSetGet(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSetGetArray(t *testing.T) {
|
func TestSetGetArray(t *testing.T) {
|
||||||
cfg := ReadConfig(":memory:")
|
storeFile, err := ioutil.TempFile(os.TempDir(), "prefix-")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer os.Remove(storeFile.Name())
|
||||||
|
cfg := ReadConfig(":memory:", storeFile.Name())
|
||||||
expected := []string{"a", "b", "c"}
|
expected := []string{"a", "b", "c"}
|
||||||
cfg.SetArray("test", expected)
|
cfg.SetArray("test", expected)
|
||||||
actual := cfg.GetArray("test", []string{"NOPE"})
|
actual := cfg.GetArray("test", []string{"NOPE"})
|
||||||
|
|
|
@ -18,15 +18,16 @@ var (
|
||||||
mb *bot.MockBot
|
mb *bot.MockBot
|
||||||
)
|
)
|
||||||
|
|
||||||
func setup(t *testing.T) (*AdminPlugin, *bot.MockBot) {
|
func setup(t *testing.T) (*AdminPlugin, *bot.MockBot, func()) {
|
||||||
mb = bot.NewMockBot()
|
mb = bot.NewMockBot()
|
||||||
a = New(mb)
|
a = New(mb)
|
||||||
mb.DB().MustExec(`delete from config`)
|
|
||||||
err := mb.Config().Set("admins", "tester")
|
err := mb.Config().Set("admins", "tester")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
return a, mb
|
return a, mb, func() {
|
||||||
|
mb.TearDown()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeMessage(payload string, r *regexp.Regexp) bot.Request {
|
func makeMessage(payload string, r *regexp.Regexp) bot.Request {
|
||||||
|
@ -50,7 +51,8 @@ func makeMessage(payload string, r *regexp.Regexp) bot.Request {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSet(t *testing.T) {
|
func TestSet(t *testing.T) {
|
||||||
a, mb := setup(t)
|
a, mb, td := setup(t)
|
||||||
|
defer td()
|
||||||
expected := "test value"
|
expected := "test value"
|
||||||
a.setConfigCmd(makeMessage("!set test.key "+expected, setConfigRegex))
|
a.setConfigCmd(makeMessage("!set test.key "+expected, setConfigRegex))
|
||||||
actual := mb.Config().Get("test.key", "ERR")
|
actual := mb.Config().Get("test.key", "ERR")
|
||||||
|
@ -58,7 +60,8 @@ func TestSet(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetValue(t *testing.T) {
|
func TestGetValue(t *testing.T) {
|
||||||
a, mb := setup(t)
|
a, mb, td := setup(t)
|
||||||
|
defer td()
|
||||||
expected := "value"
|
expected := "value"
|
||||||
mb.Config().Set("test.key", "value")
|
mb.Config().Set("test.key", "value")
|
||||||
a.getConfigCmd(makeMessage("!get test.key", getConfigRegex))
|
a.getConfigCmd(makeMessage("!get test.key", getConfigRegex))
|
||||||
|
@ -67,7 +70,8 @@ func TestGetValue(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetEmpty(t *testing.T) {
|
func TestGetEmpty(t *testing.T) {
|
||||||
a, mb := setup(t)
|
a, mb, td := setup(t)
|
||||||
|
defer td()
|
||||||
expected := "test.key: <unknown>"
|
expected := "test.key: <unknown>"
|
||||||
a.getConfigCmd(makeMessage("!get test.key", getConfigRegex))
|
a.getConfigCmd(makeMessage("!get test.key", getConfigRegex))
|
||||||
assert.Len(t, mb.Messages, 1)
|
assert.Len(t, mb.Messages, 1)
|
||||||
|
@ -75,7 +79,8 @@ func TestGetEmpty(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetForbidden(t *testing.T) {
|
func TestGetForbidden(t *testing.T) {
|
||||||
a, mb := setup(t)
|
a, mb, td := setup(t)
|
||||||
|
defer td()
|
||||||
expected := "cannot access"
|
expected := "cannot access"
|
||||||
a.getConfigCmd(makeMessage("!get slack.token", getConfigRegex))
|
a.getConfigCmd(makeMessage("!get slack.token", getConfigRegex))
|
||||||
assert.Len(t, mb.Messages, 1)
|
assert.Len(t, mb.Messages, 1)
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
package babbler
|
package babbler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
bh "github.com/timshannon/bolthold"
|
bh "github.com/timshannon/bolthold"
|
||||||
"github.com/velour/catbase/plugins/remember"
|
"github.com/velour/catbase/plugins/remember"
|
||||||
|
"math"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -33,8 +33,8 @@ type BabblerPlugin struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Babbler struct {
|
type Babbler struct {
|
||||||
BabblerID int64 `db:"id" boltholdid:"BabblerID"`
|
BabblerID uint64 `db:"BabblerID" boltholdKey:"BabblerID"`
|
||||||
Name string `db:"babbler"`
|
Name string `db:"Name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBabbler(store *bh.Store, id int64) (*Babbler, error) {
|
func getBabbler(store *bh.Store, id int64) (*Babbler, error) {
|
||||||
|
@ -44,38 +44,48 @@ func getBabbler(store *bh.Store, id int64) (*Babbler, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type BabblerWord struct {
|
type BabblerWord struct {
|
||||||
WordID int64 `db:"ID" boltholdid:"WordID"`
|
WordID uint64 `db:"WordID" boltholdKey:"WordID"`
|
||||||
Word string `db:"Word"`
|
Word string `db:"Word"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getWord(store *bh.Store, id int64) (*BabblerWord, error) {
|
func getWord(store *bh.Store, id uint64) (*BabblerWord, error) {
|
||||||
res := &BabblerWord{}
|
res := &BabblerWord{}
|
||||||
err := store.Get(id, res)
|
err := store.Get(id, res)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
type BabblerNode struct {
|
type BabblerNode struct {
|
||||||
NodeId int64 `db:"ID" boltholdid:"NodeId"`
|
NodeID uint64 `db:"NodeID" boltholdKey:"NodeID"`
|
||||||
BabblerID int64 `db:"BabblerID"`
|
BabblerID uint64 `db:"BabblerID"`
|
||||||
WordID int64 `db:"WordID"`
|
WordID uint64 `db:"WordID"`
|
||||||
Root int64 `db:"Root"`
|
Root uint64 `db:"Root"`
|
||||||
RootFrequency int64 `db:"RootFrequency"`
|
RootFrequency int64 `db:"RootFrequency"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNode(store *bh.Store, id int64) (*BabblerNode, error) {
|
func getNode(store *bh.Store, id uint64) (*BabblerNode, error) {
|
||||||
res := &BabblerNode{}
|
res := &BabblerNode{}
|
||||||
err := store.Get(id, res)
|
all := []BabblerNode{}
|
||||||
|
err := store.Find(&all, &bh.Query{})
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("error finding all")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = store.Get(id, res)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msgf("error getting %v", id)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
type BabblerArc struct {
|
type BabblerArc struct {
|
||||||
ArcId int64 `db:"ID" boltholdid:"ArcId"`
|
ArcID uint64 `db:"ArcID" boltholdKey:"ArcID"`
|
||||||
FromNodeId int64 `db:"FromNodeId"`
|
FromNodeID uint64 `db:"FromNodeID"`
|
||||||
ToNodeId int64 `db:"ToNodeId"`
|
ToNodeID uint64 `db:"ToNodeID"`
|
||||||
Frequency int64 `db:"Frequency"`
|
Frequency int64 `db:"Frequency"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func getArc(store *bh.Store, id int64) (*BabblerArc, error) {
|
func getArc(store *bh.Store, id uint64) (*BabblerArc, error) {
|
||||||
res := &BabblerArc{}
|
res := &BabblerArc{}
|
||||||
err := store.Get(id, res)
|
err := store.Get(id, res)
|
||||||
return res, err
|
return res, err
|
||||||
|
@ -200,13 +210,13 @@ func (p *BabblerPlugin) makeBabbler(name string) (*Babbler, error) {
|
||||||
|
|
||||||
func (p *BabblerPlugin) getBabbler(name string) (*Babbler, error) {
|
func (p *BabblerPlugin) getBabbler(name string) (*Babbler, error) {
|
||||||
var bblr Babbler
|
var bblr Babbler
|
||||||
err := p.store.FindOne(&bblr, bh.Where("Babbler").Eq(name))
|
err := p.store.FindOne(&bblr, bh.Where("Name").Eq(name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == bh.ErrNotFound {
|
||||||
log.Error().Msg("failed to find babbler")
|
log.Error().Msgf("failed to find babbler for %s", name)
|
||||||
return nil, NO_BABBLER
|
return nil, NO_BABBLER
|
||||||
}
|
}
|
||||||
log.Error().Err(err).Msg("encountered problem in babbler lookup")
|
log.Error().Err(err).Msg("encountered problem in babbler lookup for %s")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &bblr, nil
|
return &bblr, nil
|
||||||
|
@ -217,14 +227,14 @@ func (p *BabblerPlugin) getOrCreateBabbler(name string) (*Babbler, error) {
|
||||||
if err == NO_BABBLER {
|
if err == NO_BABBLER {
|
||||||
babbler, err = p.makeBabbler(name)
|
babbler, err = p.makeBabbler(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("error making babbler")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
quotes := remember.AllQuotesFrom(p.store, babbler.Name)
|
quotes := remember.AllQuotesFrom(p.store, babbler.Name)
|
||||||
for _, q := range quotes {
|
for _, q := range quotes {
|
||||||
if err = p.addToMarkovChain(babbler, q.Tidbit); err != nil {
|
if err = p.addToMarkovChain(babbler, q.Tidbit); err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("error adding to chain")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -289,6 +299,7 @@ func (p *BabblerPlugin) createBabblerNode(babbler *Babbler, word string) (*Babbl
|
||||||
}
|
}
|
||||||
|
|
||||||
bn := &BabblerNode{
|
bn := &BabblerNode{
|
||||||
|
BabblerID: babbler.BabblerID,
|
||||||
WordID: w.WordID,
|
WordID: w.WordID,
|
||||||
Root: 0,
|
Root: 0,
|
||||||
RootFrequency: 0,
|
RootFrequency: 0,
|
||||||
|
@ -314,17 +325,16 @@ func (p *BabblerPlugin) getOrCreateBabblerNode(babbler *Babbler, word string) (*
|
||||||
func (p *BabblerPlugin) incrementRootWordFrequency(babbler *Babbler, word string) (*BabblerNode, error) {
|
func (p *BabblerPlugin) incrementRootWordFrequency(babbler *Babbler, word string) (*BabblerNode, error) {
|
||||||
node, err := p.getOrCreateBabblerNode(babbler, word)
|
node, err := p.getOrCreateBabblerNode(babbler, word)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("error getOrCreateBabblerNode")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = p.store.UpdateMatching(BabblerNode{}, bh.Where("ID").Eq(node.NodeId), func(record interface{}) error {
|
|
||||||
r := record.(BabblerNode)
|
node.RootFrequency += 1
|
||||||
r.RootFrequency += 1
|
node.Root = 1
|
||||||
r.Root = 1
|
err = p.store.Update(node.NodeID, node)
|
||||||
return p.store.Update(r.NodeId, r)
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("error updating matching")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
node.RootFrequency += 1
|
node.RootFrequency += 1
|
||||||
|
@ -333,7 +343,7 @@ func (p *BabblerPlugin) incrementRootWordFrequency(babbler *Babbler, word string
|
||||||
|
|
||||||
func (p *BabblerPlugin) getBabblerArc(fromNode, toNode *BabblerNode) (*BabblerArc, error) {
|
func (p *BabblerPlugin) getBabblerArc(fromNode, toNode *BabblerNode) (*BabblerArc, error) {
|
||||||
var arc BabblerArc
|
var arc BabblerArc
|
||||||
err := p.store.FindOne(&arc, bh.Where("FromNodeID").Eq(fromNode.NodeId).And("ToNodeID").Eq(toNode.NodeId))
|
err := p.store.FindOne(&arc, bh.Where("FromNodeID").Eq(fromNode.NodeID).And("ToNodeID").Eq(toNode.NodeID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == bh.ErrNotFound {
|
if err == bh.ErrNotFound {
|
||||||
return nil, NEVER_SAID
|
return nil, NEVER_SAID
|
||||||
|
@ -346,26 +356,29 @@ func (p *BabblerPlugin) getBabblerArc(fromNode, toNode *BabblerNode) (*BabblerAr
|
||||||
func (p *BabblerPlugin) incrementWordArc(fromNode, toNode *BabblerNode) (*BabblerArc, error) {
|
func (p *BabblerPlugin) incrementWordArc(fromNode, toNode *BabblerNode) (*BabblerArc, error) {
|
||||||
affectedRows := 0
|
affectedRows := 0
|
||||||
err := p.store.UpdateMatching(BabblerArc{},
|
err := p.store.UpdateMatching(BabblerArc{},
|
||||||
bh.Where("FromNodeId").Eq(fromNode.NodeId).And("ToNodeId").Eq(toNode.NodeId),
|
bh.Where("FromNodeID").Eq(fromNode.NodeID).And("ToNodeID").Eq(toNode.NodeID),
|
||||||
func(record interface{}) error {
|
func(record interface{}) error {
|
||||||
affectedRows++
|
affectedRows++
|
||||||
r := record.(BabblerArc)
|
r, ok := record.(*BabblerArc)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("incorrect type: expected BabblerArc, got %T", record)
|
||||||
|
}
|
||||||
r.Frequency += 1
|
r.Frequency += 1
|
||||||
return p.store.Update(r.ArcId, r)
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("error updating arcs")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if affectedRows == 0 {
|
if affectedRows == 0 {
|
||||||
p.store.Insert(bh.NextSequence(), BabblerArc{
|
err = p.store.Insert(bh.NextSequence(), BabblerArc{
|
||||||
FromNodeId: fromNode.NodeId,
|
FromNodeID: fromNode.NodeID,
|
||||||
ToNodeId: toNode.NodeId,
|
ToNodeID: toNode.NodeID,
|
||||||
Frequency: 1,
|
Frequency: 1,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("error inserting arc")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -390,19 +403,19 @@ func (p *BabblerPlugin) addToMarkovChain(babbler *Babbler, phrase string) error
|
||||||
|
|
||||||
curNode, err := p.incrementRootWordFrequency(babbler, words[0])
|
curNode, err := p.incrementRootWordFrequency(babbler, words[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("incrementRootWordFrequency")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 1; i < len(words); i++ {
|
for i := 1; i < len(words); i++ {
|
||||||
nextNode, err := p.getOrCreateBabblerNode(babbler, words[i])
|
nextNode, err := p.getOrCreateBabblerNode(babbler, words[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("getOrCreateBabblerNode")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = p.incrementWordArc(curNode, nextNode)
|
_, err = p.incrementWordArc(curNode, nextNode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("incrementWordArc")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
curNode = nextNode
|
curNode = nextNode
|
||||||
|
@ -414,7 +427,7 @@ func (p *BabblerPlugin) addToMarkovChain(babbler *Babbler, phrase string) error
|
||||||
|
|
||||||
func (p *BabblerPlugin) getWeightedRootNode(babbler *Babbler) (*BabblerNode, *BabblerWord, error) {
|
func (p *BabblerPlugin) getWeightedRootNode(babbler *Babbler) (*BabblerNode, *BabblerWord, error) {
|
||||||
rootNodes := []*BabblerNode{}
|
rootNodes := []*BabblerNode{}
|
||||||
err := p.store.Find(&rootNodes, bh.Where("BabblerID").Eq(babbler.BabblerID).And("Root").Eq(1))
|
err := p.store.Find(&rootNodes, bh.Where("BabblerID").Eq(babbler.BabblerID).And("Root").Eq(uint64(1)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -450,7 +463,7 @@ func (p *BabblerPlugin) getWeightedRootNode(babbler *Babbler) (*BabblerNode, *Ba
|
||||||
|
|
||||||
func (p *BabblerPlugin) getWeightedNextWord(fromNode *BabblerNode) (*BabblerNode, *BabblerWord, error) {
|
func (p *BabblerPlugin) getWeightedNextWord(fromNode *BabblerNode) (*BabblerNode, *BabblerWord, error) {
|
||||||
arcs := []BabblerArc{}
|
arcs := []BabblerArc{}
|
||||||
err := p.store.Find(&arcs, bh.Where("FromNodeID").Eq(fromNode.NodeId))
|
err := p.store.Find(&arcs, bh.Where("FromNodeID").Eq(fromNode.NodeID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
|
@ -471,15 +484,15 @@ func (p *BabblerPlugin) getWeightedNextWord(fromNode *BabblerNode) (*BabblerNode
|
||||||
total += arc.Frequency
|
total += arc.Frequency
|
||||||
|
|
||||||
if total >= which {
|
if total >= which {
|
||||||
node, err := getNode(p.store, arc.ToNodeId)
|
node, err := getNode(p.store, arc.ToNodeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("getNode")
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
w, err := getWord(p.store, node.WordID)
|
w, err := getWord(p.store, node.WordID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("getWord")
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
return node, w, nil
|
return node, w, nil
|
||||||
|
@ -492,7 +505,7 @@ func (p *BabblerPlugin) getWeightedNextWord(fromNode *BabblerNode) (*BabblerNode
|
||||||
|
|
||||||
func (p *BabblerPlugin) getWeightedPreviousWord(toNode *BabblerNode) (*BabblerNode, *BabblerWord, bool, error) {
|
func (p *BabblerPlugin) getWeightedPreviousWord(toNode *BabblerNode) (*BabblerNode, *BabblerWord, bool, error) {
|
||||||
arcs := []*BabblerArc{}
|
arcs := []*BabblerArc{}
|
||||||
err := p.store.Find(&arcs, bh.Where("ToNodeID").Eq(toNode.NodeId))
|
err := p.store.Find(&arcs, bh.Where("ToNodeID").Eq(toNode.NodeID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err)
|
||||||
return nil, nil, false, err
|
return nil, nil, false, err
|
||||||
|
@ -519,7 +532,7 @@ func (p *BabblerPlugin) getWeightedPreviousWord(toNode *BabblerNode) (*BabblerNo
|
||||||
total += arc.Frequency
|
total += arc.Frequency
|
||||||
|
|
||||||
if total >= which {
|
if total >= which {
|
||||||
node, err := getNode(p.store, arc.FromNodeId)
|
node, err := getNode(p.store, arc.FromNodeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err)
|
||||||
return nil, nil, false, err
|
return nil, nil, false, err
|
||||||
|
@ -568,7 +581,7 @@ func (p *BabblerPlugin) babble(who string) (string, error) {
|
||||||
func (p *BabblerPlugin) babbleSeed(babblerName string, seed []string) (string, error) {
|
func (p *BabblerPlugin) babbleSeed(babblerName string, seed []string) (string, error) {
|
||||||
babbler, err := p.getBabbler(babblerName)
|
babbler, err := p.getBabbler(babblerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("error getting babbler")
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -579,14 +592,14 @@ func (p *BabblerPlugin) babbleSeed(babblerName string, seed []string) (string, e
|
||||||
if len(seed) == 0 {
|
if len(seed) == 0 {
|
||||||
curNode, curWord, err = p.getWeightedRootNode(babbler)
|
curNode, curWord, err = p.getWeightedRootNode(babbler)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("error getWeightedRootNode")
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
words = append(words, curWord.Word)
|
words = append(words, curWord.Word)
|
||||||
} else {
|
} else {
|
||||||
_, curNode, err = p.verifyPhrase(babbler, seed)
|
_, curNode, err = p.verifyPhrase(babbler, seed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("error verifyPhrase")
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -594,7 +607,7 @@ func (p *BabblerPlugin) babbleSeed(babblerName string, seed []string) (string, e
|
||||||
for {
|
for {
|
||||||
curNode, curWord, err = p.getWeightedNextWord(curNode)
|
curNode, curWord, err = p.getWeightedNextWord(curNode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("err getWeightedNextWord")
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if curWord.Word == " " {
|
if curWord.Word == " " {
|
||||||
|
@ -622,7 +635,7 @@ func (p *BabblerPlugin) mergeBabblers(intoBabbler, otherBabbler *Babbler, intoNa
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mapping := map[int64]*BabblerNode{}
|
mapping := map[uint64]*BabblerNode{}
|
||||||
|
|
||||||
nodes := []*BabblerNode{}
|
nodes := []*BabblerNode{}
|
||||||
err = p.store.Find(&nodes, bh.Where("BabblerID").Eq(otherBabbler.BabblerID))
|
err = p.store.Find(&nodes, bh.Where("BabblerID").Eq(otherBabbler.BabblerID))
|
||||||
|
@ -632,7 +645,7 @@ func (p *BabblerPlugin) mergeBabblers(intoBabbler, otherBabbler *Babbler, intoNa
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
if node.NodeId == otherNode.NodeId {
|
if node.NodeID == otherNode.NodeID {
|
||||||
node.WordID = intoNode.WordID
|
node.WordID = intoNode.WordID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,11 +654,14 @@ func (p *BabblerPlugin) mergeBabblers(intoBabbler, otherBabbler *Babbler, intoNa
|
||||||
err = p.store.UpdateMatching(BabblerNode{},
|
err = p.store.UpdateMatching(BabblerNode{},
|
||||||
bh.Where("BabblerID").Eq(intoBabbler.BabblerID).And("WordID").Eq(node.WordID),
|
bh.Where("BabblerID").Eq(intoBabbler.BabblerID).And("WordID").Eq(node.WordID),
|
||||||
func(record interface{}) error {
|
func(record interface{}) error {
|
||||||
|
r, ok := record.(*BabblerNode)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("expected BabblerNode, got %T", record)
|
||||||
|
}
|
||||||
affected++
|
affected++
|
||||||
r := record.(BabblerNode)
|
|
||||||
r.RootFrequency += node.RootFrequency
|
r.RootFrequency += node.RootFrequency
|
||||||
r.Root = 1
|
r.Root = 1
|
||||||
return p.store.Update(r.BabblerID, r)
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err)
|
||||||
|
@ -654,10 +670,13 @@ func (p *BabblerPlugin) mergeBabblers(intoBabbler, otherBabbler *Babbler, intoNa
|
||||||
err = p.store.UpdateMatching(BabblerNode{},
|
err = p.store.UpdateMatching(BabblerNode{},
|
||||||
bh.Where("BabblerID").Eq(intoBabbler.BabblerID).And("WordID").Eq(node.WordID),
|
bh.Where("BabblerID").Eq(intoBabbler.BabblerID).And("WordID").Eq(node.WordID),
|
||||||
func(record interface{}) error {
|
func(record interface{}) error {
|
||||||
|
r, ok := record.(*BabblerNode)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("expected BabblerNode, got %T", record)
|
||||||
|
}
|
||||||
affected++
|
affected++
|
||||||
r := record.(BabblerNode)
|
|
||||||
r.RootFrequency += node.RootFrequency
|
r.RootFrequency += node.RootFrequency
|
||||||
return p.store.Update(r.BabblerID, r)
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err)
|
||||||
|
@ -666,22 +685,25 @@ func (p *BabblerPlugin) mergeBabblers(intoBabbler, otherBabbler *Babbler, intoNa
|
||||||
|
|
||||||
if err != nil || affected == 0 {
|
if err != nil || affected == 0 {
|
||||||
node.BabblerID = intoBabbler.BabblerID
|
node.BabblerID = intoBabbler.BabblerID
|
||||||
err = p.store.Insert(bh.NextSequence(), &node)
|
err = p.store.Insert(bh.NextSequence(), node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("error inserting node")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
log.Debug().Msgf("Inserted: %+v", node)
|
||||||
|
} else {
|
||||||
|
log.Error().Err(err).Int("affected", affected).Msgf("problem before insert")
|
||||||
}
|
}
|
||||||
|
|
||||||
var updatedNode BabblerNode
|
var updatedNode BabblerNode
|
||||||
err = p.store.FindOne(&updatedNode,
|
err = p.store.FindOne(&updatedNode,
|
||||||
bh.Where("BabblerID").Eq(intoBabbler.BabblerID).And("WordID").Eq(node.WordID))
|
bh.Where("BabblerID").Eq(intoBabbler.BabblerID).And("WordID").Eq(node.WordID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msg("error finding updated node and also why do we need this?")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
mapping[node.NodeId] = &updatedNode
|
mapping[node.NodeID] = &updatedNode
|
||||||
}
|
}
|
||||||
|
|
||||||
for oldNodeId, newNode := range mapping {
|
for oldNodeId, newNode := range mapping {
|
||||||
|
@ -692,7 +714,7 @@ func (p *BabblerPlugin) mergeBabblers(intoBabbler, otherBabbler *Babbler, intoNa
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, arc := range arcs {
|
for _, arc := range arcs {
|
||||||
_, err := p.incrementWordArc(newNode, mapping[arc.ToNodeId])
|
_, err := p.incrementWordArc(newNode, mapping[arc.ToNodeID])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -747,7 +769,7 @@ func (p *BabblerPlugin) babbleSeedSuffix(babblerName string, seed []string) (str
|
||||||
return strings.TrimSpace(strings.Join(words, " ")), nil
|
return strings.TrimSpace(strings.Join(words, " ")), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BabblerPlugin) getNextArcs(babblerNodeId int64) ([]*BabblerArc, error) {
|
func (p *BabblerPlugin) getNextArcs(babblerNodeId uint64) ([]*BabblerArc, error) {
|
||||||
arcs := []*BabblerArc{}
|
arcs := []*BabblerArc{}
|
||||||
err := p.store.Find(&arcs, bh.Where("FromNodeID").Eq(babblerNodeId))
|
err := p.store.Find(&arcs, bh.Where("FromNodeID").Eq(babblerNodeId))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -757,7 +779,7 @@ func (p *BabblerPlugin) getNextArcs(babblerNodeId int64) ([]*BabblerArc, error)
|
||||||
return arcs, nil
|
return arcs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BabblerPlugin) getBabblerNodeById(nodeId int64) (*BabblerNode, error) {
|
func (p *BabblerPlugin) getBabblerNodeById(nodeId uint64) (*BabblerNode, error) {
|
||||||
node, err := getNode(p.store, nodeId)
|
node, err := getNode(p.store, nodeId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err)
|
||||||
|
@ -793,13 +815,13 @@ func (p *BabblerPlugin) babbleSeedBookends(babblerName string, start, end []stri
|
||||||
}
|
}
|
||||||
|
|
||||||
type searchNode struct {
|
type searchNode struct {
|
||||||
babblerNodeId int64
|
babblerNodeId uint64
|
||||||
previous *searchNode
|
previous *searchNode
|
||||||
}
|
}
|
||||||
|
|
||||||
open := []*searchNode{{startWordNode.NodeId, nil}}
|
open := []*searchNode{{startWordNode.NodeID, nil}}
|
||||||
closed := map[int64]*searchNode{startWordNode.NodeId: open[0]}
|
closed := map[uint64]*searchNode{startWordNode.NodeID: open[0]}
|
||||||
goalNodeId := int64(-1)
|
goalNodeId := uint64(math.MaxUint64)
|
||||||
|
|
||||||
for i := 0; i < len(open) && i < 1000; i++ {
|
for i := 0; i < len(open) && i < 1000; i++ {
|
||||||
cur := open[i]
|
cur := open[i]
|
||||||
|
@ -812,12 +834,12 @@ func (p *BabblerPlugin) babbleSeedBookends(babblerName string, start, end []stri
|
||||||
shuffle(arcs)
|
shuffle(arcs)
|
||||||
|
|
||||||
for _, arc := range arcs {
|
for _, arc := range arcs {
|
||||||
if _, ok := closed[arc.ToNodeId]; !ok {
|
if _, ok := closed[arc.ToNodeID]; !ok {
|
||||||
child := &searchNode{arc.ToNodeId, cur}
|
child := &searchNode{arc.ToNodeID, cur}
|
||||||
open = append(open, child)
|
open = append(open, child)
|
||||||
closed[arc.ToNodeId] = child
|
closed[arc.ToNodeID] = child
|
||||||
|
|
||||||
if arc.ToNodeId == endWordNode.NodeId {
|
if arc.ToNodeID == endWordNode.NodeID {
|
||||||
goalNodeId = cur.babblerNodeId
|
goalNodeId = cur.babblerNodeId
|
||||||
//add a little randomization in through maybe searching beyond this solution?
|
//add a little randomization in through maybe searching beyond this solution?
|
||||||
if rand.Intn(4) == 0 {
|
if rand.Intn(4) == 0 {
|
||||||
|
@ -828,7 +850,7 @@ func (p *BabblerPlugin) babbleSeedBookends(babblerName string, start, end []stri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if goalNodeId == -1 {
|
if goalNodeId == math.MaxUint64 {
|
||||||
return "", errors.New("couldn't find path")
|
return "", errors.New("couldn't find path")
|
||||||
} else if closed[goalNodeId].previous == nil {
|
} else if closed[goalNodeId].previous == nil {
|
||||||
seeds := append(start, end...)
|
seeds := append(start, end...)
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
package babbler
|
package babbler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -15,12 +18,18 @@ import (
|
||||||
"github.com/velour/catbase/bot/user"
|
"github.com/velour/catbase/bot/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
output := zerolog.ConsoleWriter{Out: os.Stdout}
|
||||||
|
log.Logger = log.Output(output).With().Caller().Stack().Logger()
|
||||||
|
}
|
||||||
|
|
||||||
func makeMessage(payload string, r *regexp.Regexp) bot.Request {
|
func makeMessage(payload string, r *regexp.Regexp) bot.Request {
|
||||||
c := &cli.CliPlugin{}
|
c := &cli.CliPlugin{}
|
||||||
isCmd := strings.HasPrefix(payload, "!")
|
isCmd := strings.HasPrefix(payload, "!")
|
||||||
if isCmd {
|
if isCmd {
|
||||||
payload = payload[1:]
|
payload = payload[1:]
|
||||||
}
|
}
|
||||||
|
log.Debug().Msgf("isCmd: %v, payload: %v", isCmd, payload)
|
||||||
return bot.Request{
|
return bot.Request{
|
||||||
Conn: c,
|
Conn: c,
|
||||||
Kind: bot.Message,
|
Kind: bot.Message,
|
||||||
|
@ -34,16 +43,12 @@ func makeMessage(payload string, r *regexp.Regexp) bot.Request {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBabblerPlugin(mb *bot.MockBot) *BabblerPlugin {
|
func newBabblerPlugin(mb *bot.MockBot) (*BabblerPlugin, func()) {
|
||||||
bp := New(mb)
|
bp := New(mb)
|
||||||
bp.WithGoRoutines = false
|
bp.WithGoRoutines = false
|
||||||
mb.DB().MustExec(`
|
return bp, func() {
|
||||||
delete from babblers;
|
mb.TearDown()
|
||||||
delete from babblerWords;
|
}
|
||||||
delete from babblerNodes;
|
|
||||||
delete from babblerArcs;
|
|
||||||
`)
|
|
||||||
return bp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testMessage(p *BabblerPlugin, msg string) bool {
|
func testMessage(p *BabblerPlugin, msg string) bool {
|
||||||
|
@ -60,17 +65,19 @@ func testMessage(p *BabblerPlugin, msg string) bool {
|
||||||
|
|
||||||
func TestBabblerNoBabbler(t *testing.T) {
|
func TestBabblerNoBabbler(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, td := newBabblerPlugin(mb)
|
||||||
|
defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
testMessage(bp, "!seabass2 says")
|
testMessage(bp, "!seabass2 says")
|
||||||
res := assert.Len(t, mb.Messages, 0)
|
res := assert.Len(t, mb.Messages, 1)
|
||||||
assert.True(t, res)
|
assert.True(t, res)
|
||||||
// assert.Contains(t, mb.Messages[0], "seabass2 babbler not found")
|
assert.Contains(t, mb.Messages[0], "seabass2 babbler not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBabblerNothingSaid(t *testing.T) {
|
func TestBabblerNothingSaid(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, td := newBabblerPlugin(mb)
|
||||||
|
defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
res := testMessage(bp, "initialize babbler for seabass")
|
res := testMessage(bp, "initialize babbler for seabass")
|
||||||
assert.True(t, res)
|
assert.True(t, res)
|
||||||
|
@ -84,13 +91,15 @@ func TestBabblerNothingSaid(t *testing.T) {
|
||||||
|
|
||||||
func TestBabbler(t *testing.T) {
|
func TestBabbler(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, _ := newBabblerPlugin(mb)
|
||||||
|
//defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
testMessage(bp, "!initialize babbler for tester")
|
testMessage(bp, "!initialize babbler for tester")
|
||||||
testMessage(bp, "This is a message")
|
testMessage(bp, "This is a message")
|
||||||
testMessage(bp, "This is another message")
|
testMessage(bp, "This is another message")
|
||||||
testMessage(bp, "This is a long message")
|
testMessage(bp, "This is a long message")
|
||||||
res := testMessage(bp, "!tester says")
|
res := testMessage(bp, "!tester says")
|
||||||
|
log.Debug().Msgf("messages: %+v", mb.Messages)
|
||||||
assert.True(t, res)
|
assert.True(t, res)
|
||||||
if assert.Len(t, mb.Messages, 1) {
|
if assert.Len(t, mb.Messages, 1) {
|
||||||
assert.Contains(t, mb.Messages[0], "this is")
|
assert.Contains(t, mb.Messages[0], "this is")
|
||||||
|
@ -100,7 +109,8 @@ func TestBabbler(t *testing.T) {
|
||||||
|
|
||||||
func TestBabblerSeed(t *testing.T) {
|
func TestBabblerSeed(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, td := newBabblerPlugin(mb)
|
||||||
|
defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
|
|
||||||
testMessage(bp, "This is a message")
|
testMessage(bp, "This is a message")
|
||||||
|
@ -115,7 +125,8 @@ func TestBabblerSeed(t *testing.T) {
|
||||||
|
|
||||||
func TestBabblerMultiSeed(t *testing.T) {
|
func TestBabblerMultiSeed(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, td := newBabblerPlugin(mb)
|
||||||
|
defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
|
|
||||||
testMessage(bp, "This is a message")
|
testMessage(bp, "This is a message")
|
||||||
|
@ -130,7 +141,8 @@ func TestBabblerMultiSeed(t *testing.T) {
|
||||||
|
|
||||||
func TestBabblerBadSeed(t *testing.T) {
|
func TestBabblerBadSeed(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, td := newBabblerPlugin(mb)
|
||||||
|
defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
|
|
||||||
testMessage(bp, "This is a message")
|
testMessage(bp, "This is a message")
|
||||||
|
@ -145,7 +157,8 @@ func TestBabblerBadSeed(t *testing.T) {
|
||||||
|
|
||||||
func TestBabblerBadSeed2(t *testing.T) {
|
func TestBabblerBadSeed2(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, td := newBabblerPlugin(mb)
|
||||||
|
defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
|
|
||||||
testMessage(bp, "This is a message")
|
testMessage(bp, "This is a message")
|
||||||
|
@ -160,7 +173,8 @@ func TestBabblerBadSeed2(t *testing.T) {
|
||||||
|
|
||||||
func TestBabblerSuffixSeed(t *testing.T) {
|
func TestBabblerSuffixSeed(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, td := newBabblerPlugin(mb)
|
||||||
|
defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
|
|
||||||
testMessage(bp, "This is message one")
|
testMessage(bp, "This is message one")
|
||||||
|
@ -176,7 +190,8 @@ func TestBabblerSuffixSeed(t *testing.T) {
|
||||||
|
|
||||||
func TestBabblerBadSuffixSeed(t *testing.T) {
|
func TestBabblerBadSuffixSeed(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, td := newBabblerPlugin(mb)
|
||||||
|
defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
|
|
||||||
testMessage(bp, "This is message one")
|
testMessage(bp, "This is message one")
|
||||||
|
@ -190,7 +205,8 @@ func TestBabblerBadSuffixSeed(t *testing.T) {
|
||||||
|
|
||||||
func TestBabblerBookendSeed(t *testing.T) {
|
func TestBabblerBookendSeed(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, td := newBabblerPlugin(mb)
|
||||||
|
defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
|
|
||||||
testMessage(bp, "This is message one")
|
testMessage(bp, "This is message one")
|
||||||
|
@ -204,7 +220,8 @@ func TestBabblerBookendSeed(t *testing.T) {
|
||||||
|
|
||||||
func TestBabblerBadBookendSeed(t *testing.T) {
|
func TestBabblerBadBookendSeed(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, td := newBabblerPlugin(mb)
|
||||||
|
defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
|
|
||||||
testMessage(bp, "This is message one")
|
testMessage(bp, "This is message one")
|
||||||
|
@ -218,7 +235,8 @@ func TestBabblerBadBookendSeed(t *testing.T) {
|
||||||
|
|
||||||
func TestBabblerMiddleOutSeed(t *testing.T) {
|
func TestBabblerMiddleOutSeed(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, td := newBabblerPlugin(mb)
|
||||||
|
defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
|
|
||||||
testMessage(bp, "This is message one")
|
testMessage(bp, "This is message one")
|
||||||
|
@ -232,7 +250,8 @@ func TestBabblerMiddleOutSeed(t *testing.T) {
|
||||||
|
|
||||||
func TestBabblerBadMiddleOutSeed(t *testing.T) {
|
func TestBabblerBadMiddleOutSeed(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, td := newBabblerPlugin(mb)
|
||||||
|
defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
|
|
||||||
testMessage(bp, "This is message one")
|
testMessage(bp, "This is message one")
|
||||||
|
@ -246,7 +265,8 @@ func TestBabblerBadMiddleOutSeed(t *testing.T) {
|
||||||
|
|
||||||
func TestBabblerMerge(t *testing.T) {
|
func TestBabblerMerge(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, td := newBabblerPlugin(mb)
|
||||||
|
defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
|
|
||||||
testMessage(bp, "<tester> This is a message")
|
testMessage(bp, "<tester> This is a message")
|
||||||
|
@ -270,7 +290,8 @@ func TestBabblerMerge(t *testing.T) {
|
||||||
|
|
||||||
func TestHelp(t *testing.T) {
|
func TestHelp(t *testing.T) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
bp := newBabblerPlugin(mb)
|
bp, td := newBabblerPlugin(mb)
|
||||||
|
defer td()
|
||||||
assert.NotNil(t, bp)
|
assert.NotNil(t, bp)
|
||||||
c := &cli.CliPlugin{}
|
c := &cli.CliPlugin{}
|
||||||
bp.help(c, bot.Help, msg.Message{Channel: "channel"}, []string{})
|
bp.help(c, bot.Help, msg.Message{Channel: "channel"}, []string{})
|
||||||
|
|
|
@ -2,6 +2,7 @@ package babbler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,10 +18,19 @@ func (p *BabblerPlugin) addToBabbler(babblerName, whatWasSaid string) {
|
||||||
babblerID, err := p.getOrCreateBabbler(babblerName)
|
babblerID, err := p.getOrCreateBabbler(babblerName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if p.WithGoRoutines {
|
if p.WithGoRoutines {
|
||||||
go p.addToMarkovChain(babblerID, whatWasSaid)
|
go func() {
|
||||||
} else {
|
if err := p.addToMarkovChain(babblerID, whatWasSaid); err != nil {
|
||||||
p.addToMarkovChain(babblerID, whatWasSaid)
|
log.Error().Err(err).Msg("addToMarkovChain")
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
|
} else {
|
||||||
|
err = p.addToMarkovChain(babblerID, whatWasSaid)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("error adding to chain")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.Error().Err(err).Msg("error getting or creating babbler")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,9 +39,9 @@ func (p *BabblerPlugin) getBabble(who string, tokens []string) string {
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == NO_BABBLER {
|
if err == NO_BABBLER {
|
||||||
// return fmt.Sprintf("%s babbler not found.", who), true
|
return fmt.Sprintf("%s babbler not found.", who)
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
log.Debug().Err(err).Msg("error getting babbler")
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
var saying string
|
var saying string
|
||||||
|
@ -46,12 +56,17 @@ func (p *BabblerPlugin) getBabble(who string, tokens []string) string {
|
||||||
return fmt.Sprintf("%s hasn't said anything yet.", who)
|
return fmt.Sprintf("%s hasn't said anything yet.", who)
|
||||||
} else if err == NEVER_SAID {
|
} else if err == NEVER_SAID {
|
||||||
return fmt.Sprintf("%s never said '%s'", who, strings.Join(tokens, " "))
|
return fmt.Sprintf("%s never said '%s'", who, strings.Join(tokens, " "))
|
||||||
|
} else {
|
||||||
|
log.Error().Err(err).Msgf("error babbling")
|
||||||
|
return fmt.Sprintf("babbler encountered an error for %s", who)
|
||||||
}
|
}
|
||||||
} else if saying != "" {
|
} else if saying != "" {
|
||||||
return saying
|
return saying
|
||||||
|
} else {
|
||||||
|
return "for some reason the saying was empty"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ""
|
return "IDK how we got here"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BabblerPlugin) getBabbleWithSuffix(who string, tokens []string) string {
|
func (p *BabblerPlugin) getBabbleWithSuffix(who string, tokens []string) string {
|
||||||
|
|
|
@ -45,10 +45,10 @@ type BeersPlugin struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type untappdUser struct {
|
type untappdUser struct {
|
||||||
untappdUser string `boltholdid:"untappdUser"`
|
UntappdUser string `boltholdKey:"UntappdUser"`
|
||||||
channel string
|
Channel string
|
||||||
lastCheckin int
|
LastCheckin int
|
||||||
chanNick string
|
ChanNick string
|
||||||
}
|
}
|
||||||
|
|
||||||
// New BeersPlugin creates a new BeersPlugin with the Plugin interface
|
// New BeersPlugin creates a new BeersPlugin with the Plugin interface
|
||||||
|
@ -160,17 +160,17 @@ func (p *BeersPlugin) register() {
|
||||||
untappdNick := r.Values["who"]
|
untappdNick := r.Values["who"]
|
||||||
|
|
||||||
u := untappdUser{
|
u := untappdUser{
|
||||||
untappdUser: untappdNick,
|
UntappdUser: untappdNick,
|
||||||
chanNick: chanNick,
|
ChanNick: chanNick,
|
||||||
channel: channel,
|
Channel: channel,
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info().
|
log.Info().
|
||||||
Str("untappdUser", u.untappdUser).
|
Str("UntappdUser", u.UntappdUser).
|
||||||
Str("nick", u.chanNick).
|
Str("nick", u.ChanNick).
|
||||||
Msg("Creating Untappd user")
|
Msg("Creating Untappd user")
|
||||||
|
|
||||||
count, err := p.store.Count(untappdUser{}, bh.Where("untappdUser").Eq(u.untappdUser))
|
count, err := p.store.Count(untappdUser{}, bh.Where("UntappdUser").Eq(u.UntappdUser))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msgf("Error registering untappd")
|
log.Error().Err(err).Msgf("Error registering untappd")
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ func (p *BeersPlugin) register() {
|
||||||
p.b.Send(r.Conn, bot.Message, channel, "I'm already watching you.")
|
p.b.Send(r.Conn, bot.Message, channel, "I'm already watching you.")
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
err = p.store.Insert(u.untappdUser, u)
|
err = p.store.Insert(u.UntappdUser, u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msgf("Error registering untappd")
|
log.Error().Err(err).Msgf("Error registering untappd")
|
||||||
p.b.Send(r.Conn, bot.Message, channel, "I can't see.")
|
p.b.Send(r.Conn, bot.Message, channel, "I can't see.")
|
||||||
|
@ -270,7 +270,7 @@ func (p *BeersPlugin) doIKnow(nick, id string) bool {
|
||||||
return count > 0
|
return count > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends random affirmation to the channel. This could be better (with a datastore for sayings)
|
// Sends random affirmation to the Channel. This could be better (with a datastore for sayings)
|
||||||
func (p *BeersPlugin) randomReply(c bot.Connector, channel string) {
|
func (p *BeersPlugin) randomReply(c bot.Connector, channel string) {
|
||||||
replies := []string{"ZIGGY! ZAGGY!", "HIC!", "Stay thirsty, my friend!"}
|
replies := []string{"ZIGGY! ZAGGY!", "HIC!", "Stay thirsty, my friend!"}
|
||||||
p.b.Send(c, bot.Message, channel, replies[rand.Intn(len(replies))])
|
p.b.Send(c, bot.Message, channel, replies[rand.Intn(len(replies))])
|
||||||
|
@ -384,9 +384,9 @@ func (p *BeersPlugin) checkUntappd(c bot.Connector, channel string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, u := range users {
|
for _, u := range users {
|
||||||
userMap[u.untappdUser] = u
|
userMap[u.UntappdUser] = u
|
||||||
if u.chanNick == "" {
|
if u.ChanNick == "" {
|
||||||
log.Fatal().Msg("Empty chanNick for no good reason.")
|
log.Fatal().Msg("Empty ChanNick for no good reason.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,7 +398,7 @@ func (p *BeersPlugin) checkUntappd(c bot.Connector, channel string) {
|
||||||
for i := len(chks); i > 0; i-- {
|
for i := len(chks); i > 0; i-- {
|
||||||
checkin := chks[i-1]
|
checkin := chks[i-1]
|
||||||
|
|
||||||
if checkin.Checkin_id <= userMap[checkin.User.User_name].lastCheckin {
|
if checkin.Checkin_id <= userMap[checkin.User.User_name].LastCheckin {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,8 +421,8 @@ func (p *BeersPlugin) sendCheckin(c bot.Connector, channel string, user untappdU
|
||||||
breweryName := checkin.Brewery["brewery_name"].(string)
|
breweryName := checkin.Brewery["brewery_name"].(string)
|
||||||
|
|
||||||
log.Debug().
|
log.Debug().
|
||||||
Msgf("user.chanNick: %s, user.untappdUser: %s, checkin.User.User_name: %s",
|
Msgf("user.ChanNick: %s, user.UntappdUser: %s, checkin.User.User_name: %s",
|
||||||
user.chanNick, user.untappdUser, checkin.User.User_name)
|
user.ChanNick, user.UntappdUser, checkin.User.User_name)
|
||||||
|
|
||||||
args := []interface{}{}
|
args := []interface{}{}
|
||||||
if checkin.Badges.Count > 0 {
|
if checkin.Badges.Count > 0 {
|
||||||
|
@ -453,11 +453,11 @@ func (p *BeersPlugin) sendCheckin(c bot.Connector, channel string, user untappdU
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't add beers till after a photo has been detected (or failed once)
|
// Don't add beers till after a photo has been detected (or failed once)
|
||||||
p.addBeers(nil, user.chanNick, "", 1)
|
p.addBeers(nil, user.ChanNick, "", 1)
|
||||||
drunken := p.getBeers(user.chanNick, "")
|
drunken := p.getBeers(user.ChanNick, "")
|
||||||
|
|
||||||
msg := fmt.Sprintf("%s just drank %s by %s%s, bringing his drunkeness to %d",
|
msg := fmt.Sprintf("%s just drank %s by %s%s, bringing his drunkeness to %d",
|
||||||
user.chanNick, beerName, breweryName, venue, drunken)
|
user.ChanNick, beerName, breweryName, venue, drunken)
|
||||||
if checkin.Rating_score > 0 {
|
if checkin.Rating_score > 0 {
|
||||||
msg = fmt.Sprintf("%s. Rating: %.2f", msg, checkin.Rating_score)
|
msg = fmt.Sprintf("%s. Rating: %.2f", msg, checkin.Rating_score)
|
||||||
}
|
}
|
||||||
|
@ -468,9 +468,9 @@ func (p *BeersPlugin) sendCheckin(c bot.Connector, channel string, user untappdU
|
||||||
|
|
||||||
args = append([]interface{}{channel, msg}, args...)
|
args = append([]interface{}{channel, msg}, args...)
|
||||||
|
|
||||||
user.lastCheckin = checkin.Checkin_id
|
user.LastCheckin = checkin.Checkin_id
|
||||||
|
|
||||||
err := p.store.Update(user.untappdUser, user)
|
err := p.store.Update(user.UntappdUser, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("UPDATE ERROR!")
|
log.Error().Err(err).Msg("UPDATE ERROR!")
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,19 +48,21 @@ func testMessage(p *BeersPlugin, msg string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeBeersPlugin(t *testing.T) (*BeersPlugin, *bot.MockBot) {
|
func makeBeersPlugin(t *testing.T) (*BeersPlugin, *bot.MockBot, func()) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
counter.New(mb)
|
counter.New(mb)
|
||||||
mb.DB().MustExec(`delete from counter; delete from counter_alias;`)
|
|
||||||
b := New(mb)
|
b := New(mb)
|
||||||
counter.MkAlias(mb.DB(), "beer", DEFAULT_ITEM)
|
counter.MkAlias(mb.Store(), "beer", DEFAULT_ITEM)
|
||||||
counter.MkAlias(mb.DB(), "beers", DEFAULT_ITEM)
|
counter.MkAlias(mb.Store(), "beers", DEFAULT_ITEM)
|
||||||
return b, mb
|
return b, mb, func() {
|
||||||
|
mb.TearDown()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCounter(t *testing.T) {
|
func TestCounter(t *testing.T) {
|
||||||
_, mb := makeBeersPlugin(t)
|
_, mb, td := makeBeersPlugin(t)
|
||||||
i, err := counter.GetUserItem(mb.DB(), "tester", "id", "test")
|
defer td()
|
||||||
|
i, err := counter.GetUserItem(mb.Store(), "tester", "id", "test")
|
||||||
if !assert.Nil(t, err) {
|
if !assert.Nil(t, err) {
|
||||||
t.Log(err)
|
t.Log(err)
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
|
@ -70,62 +72,68 @@ func TestCounter(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestImbibe(t *testing.T) {
|
func TestImbibe(t *testing.T) {
|
||||||
b, mb := makeBeersPlugin(t)
|
b, mb, td := makeBeersPlugin(t)
|
||||||
|
defer td()
|
||||||
testMessage(b, "imbibe")
|
testMessage(b, "imbibe")
|
||||||
assert.Len(t, mb.Messages, 1)
|
assert.Len(t, mb.Messages, 1)
|
||||||
testMessage(b, "imbibe")
|
testMessage(b, "imbibe")
|
||||||
assert.Len(t, mb.Messages, 2)
|
assert.Len(t, mb.Messages, 2)
|
||||||
it, err := counter.GetUserItem(mb.DB(), "tester", "id", DEFAULT_ITEM)
|
it, err := counter.GetUserItem(mb.Store(), "tester", "id", DEFAULT_ITEM)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 2, it.Count)
|
assert.Equal(t, 2, it.Count)
|
||||||
}
|
}
|
||||||
func TestEq(t *testing.T) {
|
func TestEq(t *testing.T) {
|
||||||
b, mb := makeBeersPlugin(t)
|
b, mb, td := makeBeersPlugin(t)
|
||||||
|
defer td()
|
||||||
testMessage(b, "beers = 3")
|
testMessage(b, "beers = 3")
|
||||||
assert.Len(t, mb.Messages, 1)
|
assert.Len(t, mb.Messages, 1)
|
||||||
it, err := counter.GetUserItem(mb.DB(), "tester", "id", DEFAULT_ITEM)
|
it, err := counter.GetUserItem(mb.Store(), "tester", "id", DEFAULT_ITEM)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 3, it.Count)
|
assert.Equal(t, 3, it.Count)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEqZero(t *testing.T) {
|
func TestEqZero(t *testing.T) {
|
||||||
b, mb := makeBeersPlugin(t)
|
b, mb, td := makeBeersPlugin(t)
|
||||||
|
defer td()
|
||||||
testMessage(b, "beers += 5")
|
testMessage(b, "beers += 5")
|
||||||
testMessage(b, "beers = 0")
|
testMessage(b, "beers = 0")
|
||||||
assert.Len(t, mb.Messages, 2)
|
assert.Len(t, mb.Messages, 2)
|
||||||
assert.Contains(t, mb.Messages[1], "reversal of fortune")
|
assert.Contains(t, mb.Messages[1], "reversal of fortune")
|
||||||
it, err := counter.GetUserItem(mb.DB(), "tester", "id", DEFAULT_ITEM)
|
it, err := counter.GetUserItem(mb.Store(), "tester", "id", DEFAULT_ITEM)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 0, it.Count)
|
assert.Equal(t, 0, it.Count)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBeersPlusEq(t *testing.T) {
|
func TestBeersPlusEq(t *testing.T) {
|
||||||
b, mb := makeBeersPlugin(t)
|
b, mb, td := makeBeersPlugin(t)
|
||||||
|
defer td()
|
||||||
testMessage(b, "beers += 5")
|
testMessage(b, "beers += 5")
|
||||||
assert.Len(t, mb.Messages, 1)
|
assert.Len(t, mb.Messages, 1)
|
||||||
testMessage(b, "beers += 5")
|
testMessage(b, "beers += 5")
|
||||||
assert.Len(t, mb.Messages, 2)
|
assert.Len(t, mb.Messages, 2)
|
||||||
it, err := counter.GetUserItem(mb.DB(), "tester", "id", DEFAULT_ITEM)
|
it, err := counter.GetUserItem(mb.Store(), "tester", "id", DEFAULT_ITEM)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 10, it.Count)
|
assert.Equal(t, 10, it.Count)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPuke(t *testing.T) {
|
func TestPuke(t *testing.T) {
|
||||||
b, mb := makeBeersPlugin(t)
|
b, mb, td := makeBeersPlugin(t)
|
||||||
|
defer td()
|
||||||
testMessage(b, "beers += 5")
|
testMessage(b, "beers += 5")
|
||||||
it, err := counter.GetUserItem(mb.DB(), "tester", "id", DEFAULT_ITEM)
|
it, err := counter.GetUserItem(mb.Store(), "tester", "id", DEFAULT_ITEM)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 5, it.Count)
|
assert.Equal(t, 5, it.Count)
|
||||||
testMessage(b, "puke")
|
testMessage(b, "puke")
|
||||||
it, err = counter.GetUserItem(mb.DB(), "tester", "id", DEFAULT_ITEM)
|
it, err = counter.GetUserItem(mb.Store(), "tester", "id", DEFAULT_ITEM)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 0, it.Count)
|
assert.Equal(t, 0, it.Count)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBeersReport(t *testing.T) {
|
func TestBeersReport(t *testing.T) {
|
||||||
b, mb := makeBeersPlugin(t)
|
b, mb, td := makeBeersPlugin(t)
|
||||||
|
defer td()
|
||||||
testMessage(b, "beers += 5")
|
testMessage(b, "beers += 5")
|
||||||
it, err := counter.GetUserItem(mb.DB(), "tester", "id", DEFAULT_ITEM)
|
it, err := counter.GetUserItem(mb.Store(), "tester", "id", DEFAULT_ITEM)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, 5, it.Count)
|
assert.Equal(t, 5, it.Count)
|
||||||
testMessage(b, "beers")
|
testMessage(b, "beers")
|
||||||
|
@ -135,7 +143,8 @@ func TestBeersReport(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHelp(t *testing.T) {
|
func TestHelp(t *testing.T) {
|
||||||
b, mb := makeBeersPlugin(t)
|
b, mb, td := makeBeersPlugin(t)
|
||||||
b.help(&cli.CliPlugin{}, bot.Help, msg.Message{Channel: "channel"}, []string{})
|
defer td()
|
||||||
|
b.help(&cli.CliPlugin{}, bot.Help, msg.Message{Channel: "Channel"}, []string{})
|
||||||
assert.Len(t, mb.Messages, 1)
|
assert.Len(t, mb.Messages, 1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ var embeddedFS embed.FS
|
||||||
|
|
||||||
// Factoid stores info about our factoid for lookup and later interaction
|
// Factoid stores info about our factoid for lookup and later interaction
|
||||||
type Factoid struct {
|
type Factoid struct {
|
||||||
ID int64 `boltholdid:"ID"`
|
ID uint64 `boltholdKey:"ID"`
|
||||||
Fact string
|
Fact string
|
||||||
Tidbit string
|
Tidbit string
|
||||||
Verb string
|
Verb string
|
||||||
|
|
|
@ -63,11 +63,11 @@ func New(b bot.Bot) *FirstPlugin {
|
||||||
|
|
||||||
func getLastFirst(store *bh.Store, channel string) (*FirstEntry, error) {
|
func getLastFirst(store *bh.Store, channel string) (*FirstEntry, error) {
|
||||||
fe := &FirstEntry{}
|
fe := &FirstEntry{}
|
||||||
err := store.FindOne(fe, bh.Where("Channel").Eq(channel))
|
err := store.FindOne(fe, bh.Where("Channel").Eq(channel).SortBy("Day").Reverse())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
log.Debug().Msgf("ID: %v Day %v Time %v Body %v Nick %v", fe)
|
log.Debug().Msgf("getLastFirst: %+v", fe)
|
||||||
return fe, nil
|
return fe, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -237,7 +237,7 @@ func parseCmd(r *regexp.Regexp, body string) cmd {
|
||||||
}
|
}
|
||||||
|
|
||||||
type goal struct {
|
type goal struct {
|
||||||
ID uint64 `boltholdid:"ID"`
|
ID uint64 `boltholdKey:"ID"`
|
||||||
Kind string
|
Kind string
|
||||||
Who string
|
Who string
|
||||||
What string
|
What string
|
||||||
|
|
|
@ -44,7 +44,7 @@ func New(b bot.Bot) *InventoryPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Item struct {
|
type Item struct {
|
||||||
Name string `boltholdid:"Name"`
|
Name string `boltholdKey:"Name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *InventoryPlugin) giveItemFilter(input string) string {
|
func (p *InventoryPlugin) giveItemFilter(input string) string {
|
||||||
|
|
|
@ -56,7 +56,7 @@ func (p *NewsBid) balanceCmd(r bot.Request) bool {
|
||||||
|
|
||||||
bal := p.ws.GetBalance(r.Msg.User.Name)
|
bal := p.ws.GetBalance(r.Msg.User.Name)
|
||||||
p.bot.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("%s, your current balance is %d.",
|
p.bot.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("%s, your current balance is %d.",
|
||||||
r.Msg.User.Name, bal))
|
r.Msg.User.Name, bal.Balance))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ type Webshit struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Bid struct {
|
type Bid struct {
|
||||||
ID int64 `boltholdid:"ID"`
|
ID int64 `boltholdKey:"ID"`
|
||||||
User string
|
User string
|
||||||
Title string
|
Title string
|
||||||
URL string
|
URL string
|
||||||
|
@ -42,7 +42,7 @@ type Bid struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Balance struct {
|
type Balance struct {
|
||||||
User string `boltholdid:"User"`
|
User string `boltholdKey:"User"`
|
||||||
Balance int
|
Balance int
|
||||||
Score int
|
Score int
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,8 @@ func TestCornerCaseBug(t *testing.T) {
|
||||||
p.rememberCmd(rememberMsg)
|
p.rememberCmd(rememberMsg)
|
||||||
assert.Len(t, mb.Messages, 1)
|
assert.Len(t, mb.Messages, 1)
|
||||||
assert.Contains(t, mb.Messages[0], "horse dick")
|
assert.Contains(t, mb.Messages[0], "horse dick")
|
||||||
q, err := fact.GetSingleFact(mb.DB(), "user1 quotes")
|
q, err := fact.GetSingleFact(mb.Store(), "user1 quotes")
|
||||||
assert.Nil(t, err)
|
if assert.Nil(t, err) {
|
||||||
assert.Contains(t, q.Tidbit, "horse dick")
|
assert.Contains(t, q.Tidbit, "horse dick")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,13 +112,21 @@ func (p *ReminderPlugin) message(c bot.Connector, kind bot.Kind, message msg.Mes
|
||||||
when := time.Now().UTC().Add(dur)
|
when := time.Now().UTC().Add(dur)
|
||||||
what := strings.Join(parts[4:], " ")
|
what := strings.Join(parts[4:], " ")
|
||||||
|
|
||||||
p.addReminder(&Reminder{
|
rem := &Reminder{
|
||||||
From: from,
|
From: from,
|
||||||
Who: who,
|
Who: who,
|
||||||
What: what,
|
What: what,
|
||||||
When: when,
|
When: when,
|
||||||
Channel: channel,
|
Channel: channel,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
log.Debug().Msgf("Adding reminder: %v", rem)
|
||||||
|
|
||||||
|
p.addReminder(rem)
|
||||||
|
|
||||||
|
all := []Reminder{}
|
||||||
|
p.store.Find(&all, &bh.Query{})
|
||||||
|
log.Debug().Msgf("All reminders: %v", all)
|
||||||
|
|
||||||
} else if operator == "every" && strings.ToLower(parts[4]) == "for" {
|
} else if operator == "every" && strings.ToLower(parts[4]) == "for" {
|
||||||
//batch add, especially for reminding msherms to buy a kit
|
//batch add, especially for reminding msherms to buy a kit
|
||||||
|
@ -175,7 +183,7 @@ func (p *ReminderPlugin) message(c bot.Connector, kind bot.Kind, message msg.Mes
|
||||||
} else if len(parts) == 4 {
|
} else if len(parts) == 4 {
|
||||||
if strings.ToLower(parts[2]) == "to" {
|
if strings.ToLower(parts[2]) == "to" {
|
||||||
response, err = p.getAllRemindersToMeFormatted(channel, strings.ToLower(parts[3]))
|
response, err = p.getAllRemindersToMeFormatted(channel, strings.ToLower(parts[3]))
|
||||||
} else if strings.ToLower(parts[2]) == "From" {
|
} else if strings.ToLower(parts[2]) == "from" {
|
||||||
response, err = p.getAllRemindersFromMeFormatted(channel, strings.ToLower(parts[3]))
|
response, err = p.getAllRemindersFromMeFormatted(channel, strings.ToLower(parts[3]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,16 +222,14 @@ func (p *ReminderPlugin) getNextReminder() *Reminder {
|
||||||
defer p.mutex.Unlock()
|
defer p.mutex.Unlock()
|
||||||
|
|
||||||
reminder := Reminder{}
|
reminder := Reminder{}
|
||||||
res, err := p.store.FindAggregate(Reminder{}, &bh.Query{}, "")
|
err := p.store.FindOne(&reminder, (&bh.Query{}).SortBy("When"))
|
||||||
if err != nil {
|
if err != nil && err != bh.ErrNotFound {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msgf("aggregate reminders failed")
|
||||||
return nil
|
return nil
|
||||||
}
|
} else if err == bh.ErrNotFound {
|
||||||
if len(res) == 0 {
|
|
||||||
log.Error().Msg("No next reminder in system.")
|
log.Error().Msg("No next reminder in system.")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
res[0].Max("RemindWhen", &reminder)
|
|
||||||
|
|
||||||
return &reminder
|
return &reminder
|
||||||
}
|
}
|
||||||
|
@ -252,13 +258,20 @@ func (p *ReminderPlugin) getRemindersFormatted(filter, who string) (string, erro
|
||||||
p.mutex.Lock()
|
p.mutex.Lock()
|
||||||
defer p.mutex.Unlock()
|
defer p.mutex.Unlock()
|
||||||
|
|
||||||
q := bh.Where(filter).Eq(who)
|
var total int
|
||||||
|
var err error
|
||||||
|
reminders := []Reminder{}
|
||||||
|
|
||||||
if filter == "" || who == "" {
|
if filter == "" || who == "" {
|
||||||
q = &bh.Query{}
|
total, _ = p.store.Count(Reminder{}, &bh.Query{})
|
||||||
|
err = p.store.Find(&reminders, (&bh.Query{}).SortBy("ID").Limit(max))
|
||||||
|
} else {
|
||||||
|
log.Debug().Msgf("Looking for reminders where %s eq %s", filter, who)
|
||||||
|
total, _ = p.store.Count(Reminder{}, bh.Where(filter).Eq(who))
|
||||||
|
err = p.store.Find(&reminders, bh.Where(filter).Eq(who).SortBy("ID").Limit(max))
|
||||||
}
|
}
|
||||||
total, err := p.store.Count(Reminder{}, q)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err)
|
log.Error().Err(err).Msgf("error finding reminders")
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,15 +279,9 @@ func (p *ReminderPlugin) getRemindersFormatted(filter, who string) (string, erro
|
||||||
return "no pending reminders", nil
|
return "no pending reminders", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
reminders := []Reminder{}
|
|
||||||
err = p.store.Find(&reminders, q.SortBy("ID").Limit(max))
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err)
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
txt := ""
|
txt := ""
|
||||||
for counter, reminder := range reminders {
|
for counter, reminder := range reminders {
|
||||||
txt += fmt.Sprintf("%d) %s -> %s :: %s @ %s (%d)\n", counter, reminder.From, reminder.Who, reminder.What, reminder.When, reminder.ID)
|
txt += fmt.Sprintf("%d) %s -> %s :: %s @ %s (%d)\n", reminder.ID, reminder.From, reminder.Who, reminder.What, reminder.When, reminder.ID)
|
||||||
counter++
|
counter++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,11 +298,11 @@ func (p *ReminderPlugin) getAllRemindersFormatted(channel string) (string, error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ReminderPlugin) getAllRemindersFromMeFormatted(channel, me string) (string, error) {
|
func (p *ReminderPlugin) getAllRemindersFromMeFormatted(channel, me string) (string, error) {
|
||||||
return p.getRemindersFormatted("FromWho", me)
|
return p.getRemindersFormatted("From", me)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ReminderPlugin) getAllRemindersToMeFormatted(channel, me string) (string, error) {
|
func (p *ReminderPlugin) getAllRemindersToMeFormatted(channel, me string) (string, error) {
|
||||||
return p.getRemindersFormatted("ToWho", me)
|
return p.getRemindersFormatted("Who", me)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ReminderPlugin) queueUpNextReminder() {
|
func (p *ReminderPlugin) queueUpNextReminder() {
|
||||||
|
@ -327,6 +334,7 @@ func reminderer(c bot.Connector, p *ReminderPlugin) {
|
||||||
log.Error().Err(err).Msgf("could not send reminder")
|
log.Error().Err(err).Msgf("could not send reminder")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug().Msgf("trying to delete: %v", reminder)
|
||||||
if err := p.deleteReminder(reminder.ID); err != nil {
|
if err := p.deleteReminder(reminder.ID); err != nil {
|
||||||
log.Fatal().
|
log.Fatal().
|
||||||
Uint64("ID", reminder.ID).
|
Uint64("ID", reminder.ID).
|
||||||
|
|
|
@ -65,11 +65,13 @@ func TestReminder(t *testing.T) {
|
||||||
func TestReminderReorder(t *testing.T) {
|
func TestReminderReorder(t *testing.T) {
|
||||||
c, mb, td := setup(t)
|
c, mb, td := setup(t)
|
||||||
defer td()
|
defer td()
|
||||||
res := c.message(makeMessage("!remind testuser in 2s don't fail this test 2"))
|
min, max := 1, 2
|
||||||
|
res := c.message(makeMessage(fmt.Sprintf("!remind testuser in %ds don't fail this test 1", min)))
|
||||||
assert.True(t, res)
|
assert.True(t, res)
|
||||||
res = c.message(makeMessage("!remind testuser in 1s don't fail this test 1"))
|
res = c.message(makeMessage(fmt.Sprintf("!remind testuser in %ds don't fail this test 2", max)))
|
||||||
assert.True(t, res)
|
assert.True(t, res)
|
||||||
time.Sleep(5 * time.Second)
|
|
||||||
|
time.Sleep(time.Duration(max+1) * time.Second)
|
||||||
assert.Len(t, mb.Messages, 4)
|
assert.Len(t, mb.Messages, 4)
|
||||||
assert.Contains(t, mb.Messages[0], "Sure tester, I'll remind testuser.")
|
assert.Contains(t, mb.Messages[0], "Sure tester, I'll remind testuser.")
|
||||||
assert.Contains(t, mb.Messages[1], "Sure tester, I'll remind testuser.")
|
assert.Contains(t, mb.Messages[1], "Sure tester, I'll remind testuser.")
|
||||||
|
@ -116,7 +118,7 @@ func TestListBy(t *testing.T) {
|
||||||
assert.True(t, res)
|
assert.True(t, res)
|
||||||
res = c.message(makeMessageBy("!remind testuser in 5m don't fail this test 2", "testuser2"))
|
res = c.message(makeMessageBy("!remind testuser in 5m don't fail this test 2", "testuser2"))
|
||||||
assert.True(t, res)
|
assert.True(t, res)
|
||||||
res = c.message(makeMessage("!list reminders From testuser"))
|
res = c.message(makeMessage("!list reminders from testuser"))
|
||||||
assert.True(t, res)
|
assert.True(t, res)
|
||||||
assert.Len(t, mb.Messages, 3)
|
assert.Len(t, mb.Messages, 3)
|
||||||
assert.Contains(t, mb.Messages[2], "don't fail this test 1 @ ")
|
assert.Contains(t, mb.Messages[2], "don't fail this test 1 @ ")
|
||||||
|
|
|
@ -32,15 +32,17 @@ func makeMessage(payload string) bot.Request {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setup(t *testing.T) (*YourPlugin, *bot.MockBot) {
|
func setup(t *testing.T) (*YourPlugin, *bot.MockBot, func()) {
|
||||||
mb := bot.NewMockBot()
|
mb := bot.NewMockBot()
|
||||||
c := New(mb)
|
c := New(mb)
|
||||||
mb.DB().MustExec(`delete from config;`)
|
return c, mb, func() {
|
||||||
return c, mb
|
mb.TearDown()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReplacement(t *testing.T) {
|
func TestReplacement(t *testing.T) {
|
||||||
c, mb := setup(t)
|
c, mb, td := setup(t)
|
||||||
|
defer td()
|
||||||
c.config.Set("Your.MaxLength", "1000")
|
c.config.Set("Your.MaxLength", "1000")
|
||||||
c.config.SetArray("your.replacements", []string{"0"})
|
c.config.SetArray("your.replacements", []string{"0"})
|
||||||
c.config.Set("your.replacements.0.freq", "1.0")
|
c.config.Set("your.replacements.0.freq", "1.0")
|
||||||
|
@ -53,7 +55,8 @@ func TestReplacement(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNoReplacement(t *testing.T) {
|
func TestNoReplacement(t *testing.T) {
|
||||||
c, mb := setup(t)
|
c, mb, td := setup(t)
|
||||||
|
defer td()
|
||||||
c.config.Set("Your.MaxLength", "1000")
|
c.config.Set("Your.MaxLength", "1000")
|
||||||
c.config.SetArray("your.replacements", []string{"0", "1", "2"})
|
c.config.SetArray("your.replacements", []string{"0", "1", "2"})
|
||||||
c.config.Set("your.replacements.0.freq", "1.0")
|
c.config.Set("your.replacements.0.freq", "1.0")
|
||||||
|
|
Loading…
Reference in New Issue