Add corner case test, change factoid plugin name

This commit is contained in:
Chris Sexton 2016-04-08 12:18:34 -04:00
parent 2180daced9
commit d24f48862c
2 changed files with 74 additions and 22 deletions

View File

@ -179,7 +179,7 @@ func getSingleFact(db *sqlx.DB, fact string) (*factoid, error) {
accessed, accessed,
count count
from factoid from factoid
where fact regexp ? where fact like ?
order by random() limit 1;`, order by random() limit 1;`,
fact).Scan( fact).Scan(
&f.id, &f.id,
@ -196,17 +196,17 @@ func getSingleFact(db *sqlx.DB, fact string) (*factoid, error) {
return &f, err return &f, err
} }
// FactoidPlugin provides the necessary plugin-wide needs // Factoid provides the necessary plugin-wide needs
type FactoidPlugin struct { type Factoid struct {
Bot bot.Bot Bot bot.Bot
NotFound []string NotFound []string
LastFact *factoid LastFact *factoid
db *sqlx.DB db *sqlx.DB
} }
// NewFactoidPlugin creates a new FactoidPlugin with the Plugin interface // NewFactoid creates a new Factoid with the Plugin interface
func New(botInst bot.Bot) *FactoidPlugin { func New(botInst bot.Bot) *Factoid {
p := &FactoidPlugin{ p := &Factoid{
Bot: botInst, Bot: botInst,
NotFound: []string{ NotFound: []string{
"I don't know.", "I don't know.",
@ -274,7 +274,7 @@ func findAction(message string) string {
// learnFact assumes we have a learning situation and inserts a new fact // learnFact assumes we have a learning situation and inserts a new fact
// into the database // into the database
func (p *FactoidPlugin) learnFact(message msg.Message, fact, verb, tidbit string) bool { func (p *Factoid) learnFact(message msg.Message, fact, verb, tidbit string) bool {
verb = strings.ToLower(verb) verb = strings.ToLower(verb)
var count sql.NullInt64 var count sql.NullInt64
@ -309,7 +309,7 @@ func (p *FactoidPlugin) learnFact(message msg.Message, fact, verb, tidbit string
} }
// findTrigger checks to see if a given string is a trigger or not // findTrigger checks to see if a given string is a trigger or not
func (p *FactoidPlugin) findTrigger(fact string) (bool, *factoid) { func (p *Factoid) findTrigger(fact string) (bool, *factoid) {
fact = strings.ToLower(fact) // TODO: make sure this needs to be lowered here fact = strings.ToLower(fact) // TODO: make sure this needs to be lowered here
f, err := getSingleFact(p.db, fact) f, err := getSingleFact(p.db, fact)
@ -321,7 +321,7 @@ func (p *FactoidPlugin) findTrigger(fact string) (bool, *factoid) {
// sayFact spits out a fact to the channel and updates the fact in the database // sayFact spits out a fact to the channel and updates the fact in the database
// with new time and count information // with new time and count information
func (p *FactoidPlugin) sayFact(message msg.Message, fact factoid) { func (p *Factoid) sayFact(message msg.Message, fact factoid) {
msg := p.Bot.Filter(message, fact.Tidbit) msg := p.Bot.Filter(message, fact.Tidbit)
full := p.Bot.Filter(message, fmt.Sprintf("%s %s %s", full := p.Bot.Filter(message, fmt.Sprintf("%s %s %s",
fact.Fact, fact.Verb, fact.Tidbit, fact.Fact, fact.Verb, fact.Tidbit,
@ -355,7 +355,7 @@ func (p *FactoidPlugin) sayFact(message msg.Message, fact factoid) {
// trigger checks the message for its fitness to be a factoid and then hauls // trigger checks the message for its fitness to be a factoid and then hauls
// the message off to sayFact for processing if it is in fact a trigger // the message off to sayFact for processing if it is in fact a trigger
func (p *FactoidPlugin) trigger(message msg.Message) bool { func (p *Factoid) trigger(message msg.Message) bool {
minLen := p.Bot.Config().Factoid.MinLen minLen := p.Bot.Config().Factoid.MinLen
if len(message.Body) > minLen || message.Command || message.Body == "..." { if len(message.Body) > minLen || message.Command || message.Body == "..." {
if ok, fact := p.findTrigger(message.Body); ok { if ok, fact := p.findTrigger(message.Body); ok {
@ -374,7 +374,7 @@ func (p *FactoidPlugin) trigger(message msg.Message) bool {
} }
// tellThemWhatThatWas is a hilarious name for a function. // tellThemWhatThatWas is a hilarious name for a function.
func (p *FactoidPlugin) tellThemWhatThatWas(message msg.Message) bool { func (p *Factoid) tellThemWhatThatWas(message msg.Message) bool {
fact := p.LastFact fact := p.LastFact
var msg string var msg string
if fact == nil { if fact == nil {
@ -387,7 +387,7 @@ func (p *FactoidPlugin) tellThemWhatThatWas(message msg.Message) bool {
return true return true
} }
func (p *FactoidPlugin) learnAction(message msg.Message, action string) bool { func (p *Factoid) learnAction(message msg.Message, action string) bool {
body := message.Body body := message.Body
parts := strings.SplitN(body, action, 2) parts := strings.SplitN(body, action, 2)
@ -433,7 +433,7 @@ func changeOperator(body string) string {
// If the user requesting forget is either the owner of the last learned fact or // If the user requesting forget is either the owner of the last learned fact or
// an admin, it may be deleted // an admin, it may be deleted
func (p *FactoidPlugin) forgetLastFact(message msg.Message) bool { func (p *Factoid) forgetLastFact(message msg.Message) bool {
if p.LastFact == nil { if p.LastFact == nil {
p.Bot.SendMessage(message.Channel, "I refuse.") p.Bot.SendMessage(message.Channel, "I refuse.")
return true return true
@ -455,7 +455,7 @@ func (p *FactoidPlugin) forgetLastFact(message msg.Message) bool {
} }
// Allow users to change facts with a simple regexp // Allow users to change facts with a simple regexp
func (p *FactoidPlugin) changeFact(message msg.Message) bool { func (p *Factoid) changeFact(message msg.Message) bool {
oper := changeOperator(message.Body) oper := changeOperator(message.Body)
parts := strings.SplitN(message.Body, oper, 2) parts := strings.SplitN(message.Body, oper, 2)
userexp := strings.TrimSpace(parts[1]) userexp := strings.TrimSpace(parts[1])
@ -542,7 +542,7 @@ func (p *FactoidPlugin) changeFact(message msg.Message) bool {
// 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.
func (p *FactoidPlugin) Message(message msg.Message) bool { func (p *Factoid) Message(message msg.Message) bool {
if strings.ToLower(message.Body) == "what was that?" { if strings.ToLower(message.Body) == "what was that?" {
return p.tellThemWhatThatWas(message) return p.tellThemWhatThatWas(message)
} }
@ -586,18 +586,18 @@ func (p *FactoidPlugin) Message(message msg.Message) bool {
} }
// 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 *FactoidPlugin) Help(channel string, parts []string) { func (p *Factoid) Help(channel string, parts []string) {
p.Bot.SendMessage(channel, "I can learn facts and spit them back out. You can say \"this is that\" or \"he <has> $5\". Later, trigger the factoid by just saying the trigger word, \"this\" or \"he\" in these examples.") p.Bot.SendMessage(channel, "I can learn facts and spit them back out. You can say \"this is that\" or \"he <has> $5\". Later, trigger the factoid by just saying the trigger word, \"this\" or \"he\" in these examples.")
p.Bot.SendMessage(channel, "I can also figure out some variables including: $nonzero, $digit, $nick, and $someone.") p.Bot.SendMessage(channel, "I can also figure out some variables including: $nonzero, $digit, $nick, and $someone.")
} }
// Empty event handler because this plugin does not do anything on event recv // Empty event handler because this plugin does not do anything on event recv
func (p *FactoidPlugin) Event(kind string, message msg.Message) bool { func (p *Factoid) Event(kind string, message msg.Message) bool {
return false return false
} }
// Pull a fact at random from the database // Pull a fact at random from the database
func (p *FactoidPlugin) randomFact() *factoid { func (p *Factoid) randomFact() *factoid {
f, err := getSingle(p.db) f, err := getSingle(p.db)
if err != nil { if err != nil {
fmt.Println("Error getting a fact: ", err) fmt.Println("Error getting a fact: ", err)
@ -607,7 +607,7 @@ func (p *FactoidPlugin) randomFact() *factoid {
} }
// factTimer spits out a fact at a given interval and with given probability // factTimer spits out a fact at a given interval and with given probability
func (p *FactoidPlugin) factTimer(channel string) { func (p *Factoid) factTimer(channel string) {
duration := time.Duration(p.Bot.Config().Factoid.QuoteTime) * time.Minute duration := time.Duration(p.Bot.Config().Factoid.QuoteTime) * time.Minute
myLastMsg := time.Now() myLastMsg := time.Now()
for { for {
@ -643,12 +643,12 @@ func (p *FactoidPlugin) factTimer(channel string) {
} }
// Handler for bot's own messages // Handler for bot's own messages
func (p *FactoidPlugin) BotMessage(message msg.Message) bool { func (p *Factoid) BotMessage(message msg.Message) bool {
return false return false
} }
// Register any web URLs desired // Register any web URLs desired
func (p *FactoidPlugin) RegisterWeb() *string { func (p *Factoid) RegisterWeb() *string {
http.HandleFunc("/factoid/req", p.serveQuery) http.HandleFunc("/factoid/req", p.serveQuery)
http.HandleFunc("/factoid", p.serveQuery) http.HandleFunc("/factoid", p.serveQuery)
tmp := "/factoid" tmp := "/factoid"
@ -665,7 +665,7 @@ func linkify(text string) template.HTML {
return template.HTML(strings.Join(parts, " ")) return template.HTML(strings.Join(parts, " "))
} }
func (p *FactoidPlugin) serveQuery(w http.ResponseWriter, r *http.Request) { func (p *Factoid) serveQuery(w http.ResponseWriter, r *http.Request) {
context := make(map[string]interface{}) context := make(map[string]interface{})
funcMap := template.FuncMap{ funcMap := template.FuncMap{
// The name "title" is what the function will be called in the template text. // The name "title" is what the function will be called in the template text.

View File

@ -0,0 +1,52 @@
package fact
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"
)
func makeMessage(nick, payload string) msg.Message {
isCmd := strings.HasPrefix(payload, "!")
if isCmd {
payload = payload[1:]
}
return msg.Message{
User: &user.User{Name: nick},
Channel: "test",
Body: payload,
Command: isCmd,
}
}
func makePlugin(t *testing.T) (*RememberPlugin, *Factoid, *bot.MockBot) {
mb := bot.NewMockBot()
f := New(mb) // for DB table
p := NewRemember(mb)
assert.NotNil(t, p)
return p, f, mb
}
// Test case
func TestCornerCaseBug(t *testing.T) {
msgs := []msg.Message{
makeMessage("user1", "I dont want to personally touch a horse dick."),
makeMessage("user3", "idk my bff rose?"),
makeMessage("user2", "!remember user1 touch"),
}
p, _, mb := makePlugin(t)
for _, m := range msgs {
p.Message(m)
}
assert.Len(t, mb.Messages, 1)
assert.Contains(t, mb.Messages[0], "horse dick")
q, err := getSingleFact(mb.DB(), "user1 quotes")
assert.Nil(t, err)
assert.Contains(t, q.Tidbit, "horse dick")
}