From 6fb0990a11912dbcecfe42c82661a084e6edf8a4 Mon Sep 17 00:00:00 2001 From: Chris Sexton Date: Wed, 13 Feb 2019 12:08:16 -0500 Subject: [PATCH 1/3] main: removed zork plugin --- main.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/main.go b/main.go index 490c2c4..e6ba88c 100644 --- a/main.go +++ b/main.go @@ -37,7 +37,6 @@ import ( "github.com/velour/catbase/plugins/tell" "github.com/velour/catbase/plugins/twitch" "github.com/velour/catbase/plugins/your" - "github.com/velour/catbase/plugins/zork" ) var ( @@ -95,7 +94,6 @@ func main() { b.AddPlugin(counter.New(b)) b.AddPlugin(reminder.New(b)) b.AddPlugin(babbler.New(b)) - b.AddPlugin(zork.New(b)) b.AddPlugin(rss.New(b)) b.AddPlugin(reaction.New(b)) b.AddPlugin(twitch.New(b)) From 47a824e8dab0b07f3815ea3fb1ec3e6d08ad17e9 Mon Sep 17 00:00:00 2001 From: Chris Sexton Date: Fri, 15 Feb 2019 13:22:54 -0500 Subject: [PATCH 2/3] remember: fixed something? It works now. --- bot/bot.go | 2 +- bot/handlers.go | 3 +- bot/interfaces.go | 4 +- connectors/slackapp/slackApp.go | 6 +- go.sum | 9 -- main.go | 3 +- .../fact/{remember_test.go => fact_test.go} | 30 +--- plugins/fact/factoid.go | 134 +++++++++--------- plugins/{fact => remember}/remember.go | 72 ++++------ plugins/remember/remember_test.go | 53 +++++++ 10 files changed, 164 insertions(+), 152 deletions(-) rename plugins/fact/{remember_test.go => fact_test.go} (59%) rename plugins/{fact => remember}/remember.go (65%) create mode 100644 plugins/remember/remember_test.go diff --git a/bot/bot.go b/bot/bot.go index b0f0da9..b794fcc 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -246,7 +246,7 @@ func (b *bot) RegisterFilter(name string, f func(string) string) { // Register a callback func (b *bot) Register(p Plugin, kind Kind, cb Callback) { - t := reflect.TypeOf(p) + t := reflect.TypeOf(p).String() if _, ok := b.callbacks[t]; !ok { b.callbacks[t] = make(map[Kind][]Callback) } diff --git a/bot/handlers.go b/bot/handlers.go index 5c52005..75eff1b 100644 --- a/bot/handlers.go +++ b/bot/handlers.go @@ -25,6 +25,7 @@ func (b *bot) Receive(kind Kind, msg msg.Message, args ...interface{}) bool { if kind == Message && strings.HasPrefix(msg.Body, "help") && msg.Command { parts := strings.Fields(strings.ToLower(msg.Body)) b.checkHelp(msg.Channel, parts) + log.Println("Handled a help, returning") goto RET } @@ -40,7 +41,7 @@ RET: } func (b *bot) runCallback(plugin Plugin, evt Kind, message msg.Message, args ...interface{}) bool { - t := reflect.TypeOf(plugin) + t := reflect.TypeOf(plugin).String() for _, cb := range b.callbacks[t][evt] { if cb(evt, message, args...) { return true diff --git a/bot/interfaces.go b/bot/interfaces.go index 53d5aa3..2f430e4 100644 --- a/bot/interfaces.go +++ b/bot/interfaces.go @@ -3,8 +3,6 @@ package bot import ( - "reflect" - "github.com/jmoiron/sqlx" "github.com/velour/catbase/bot/msg" "github.com/velour/catbase/bot/user" @@ -34,7 +32,7 @@ const ( type Kind int type Callback func(Kind, msg.Message, ...interface{}) bool -type CallbackMap map[reflect.Type]map[Kind][]Callback +type CallbackMap map[string]map[Kind][]Callback // Bot interface serves to allow mocking of the actual bot type Bot interface { diff --git a/connectors/slackapp/slackApp.go b/connectors/slackapp/slackApp.go index 3d8e90c..a252037 100644 --- a/connectors/slackapp/slackApp.go +++ b/connectors/slackapp/slackApp.go @@ -48,7 +48,7 @@ func New(c *config.Config) *SlackApp { log.Fatalf("No slack token found. Set SLACKTOKEN env.") } - api := slack.New(token, slack.OptionDebug(true)) + api := slack.New(token, slack.OptionDebug(false)) return &SlackApp{ api: api, @@ -263,7 +263,7 @@ func (s *SlackApp) populateEmojiList() { log.Println("Cannot get emoji list without slack.usertoken") return } - api := slack.New(s.userToken, slack.OptionDebug(true)) + api := slack.New(s.userToken, slack.OptionDebug(false)) em, err := api.GetEmoji() if err != nil { @@ -339,7 +339,7 @@ func (s *SlackApp) Who(id string) []string { log.Println("Cannot get emoji list without slack.usertoken") return []string{s.config.Get("nick", "bot")} } - api := slack.New(s.userToken, slack.OptionDebug(true)) + api := slack.New(s.userToken, slack.OptionDebug(false)) log.Println("Who is queried for ", id) // Not super sure this is the correct call diff --git a/go.sum b/go.sum index cf9d3cc..e4ec4ff 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,6 @@ github.com/PuerkitoBio/goquery v1.5.0 h1:uGvmFXOA73IKluu/F84Xd1tt/z07GYm8X49XKHP github.com/PuerkitoBio/goquery v1.5.0/go.mod h1:qD2PgZ9lccMbQlc7eEOjaeRlFQON7xY8kdmcsrnKqMg= github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o= github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= -github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff h1:+TEqaP0eO1unI7XHHFeMDhsxhLDIb0x8KYuZbqbAmxA= github.com/chrissexton/leftpad v0.0.0-20181207133115-1e93189d2fff/go.mod h1:QCRjR0b4qiJiNjuP7RFM89bh4UExGJalcWmYeSvlnRc= @@ -20,7 +19,6 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mmcdole/gofeed v1.0.0-beta2 h1:CjQ0ADhAwNSb08zknAkGOEYqr8zfZKfrzgk9BxpWP2E= github.com/mmcdole/gofeed v1.0.0-beta2/go.mod h1:/BF9JneEL2/flujm8XHoxUcghdTV6vvb3xx/vKyChFU= @@ -37,23 +35,16 @@ github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d/go.mod h1:xvqspo github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/velour/chat v0.0.0-20180713122344-fd1d1606cb89 h1:3D3M900hEBJJAqyKl70QuRHi5weX9+ptlQI1v+FNcQ8= github.com/velour/chat v0.0.0-20180713122344-fd1d1606cb89/go.mod h1:ejwOYCjnDMyO5LXFXRARQJGBZ6xQJZ3rgAHE5drSuMM= github.com/velour/velour v0.0.0-20160303155839-8e090e68d158 h1:p3rTUXxzuKsBOsHlkly7+rj9wagFBKeIsCDKkDII9sw= github.com/velour/velour v0.0.0-20160303155839-8e090e68d158/go.mod h1:Ojy3BTOiOTwpHpw7/HNi+TVTFppao191PQs+Qc3sqpE= -github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7 h1:noHsffKZsNfU38DwcXWEPldrTjIZ8FPNKx8mYMGnqjs= github.com/yuin/gluamapper v0.0.0-20150323120927-d836955830e7/go.mod h1:bbMEM6aU1WDF1ErA5YJ0p91652pGv140gGw4Ww3RGp8= -github.com/yuin/gopher-lua v0.0.0-20181214045814-db9ae37725ec h1:vpF8Kxql6/3OvGH4y2SKtpN3WsB17mvJ8f8H1o2vucQ= -github.com/yuin/gopher-lua v0.0.0-20181214045814-db9ae37725ec/go.mod h1:fFiAh+CowNFr0NK5VASokuwKwkbacRmHsVA7Yb1Tqac= github.com/yuin/gopher-lua v0.0.0-20190125051437-7b9317363aa9/go.mod h1:fFiAh+CowNFr0NK5VASokuwKwkbacRmHsVA7Yb1Tqac= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181217023233-e147a9138326 h1:iCzOf0xz39Tstp+Tu/WwyGjUXCk34QhQORRxBeXXTA4= -golang.org/x/net v0.0.0-20181217023233-e147a9138326/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 h1:ulvT7fqt0yHWzpJwI57MezWnYDVpCAYBVuYst/L+fAY= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= diff --git a/main.go b/main.go index e6ba88c..0e5e311 100644 --- a/main.go +++ b/main.go @@ -29,6 +29,7 @@ import ( "github.com/velour/catbase/plugins/nerdepedia" "github.com/velour/catbase/plugins/picker" "github.com/velour/catbase/plugins/reaction" + "github.com/velour/catbase/plugins/remember" "github.com/velour/catbase/plugins/reminder" "github.com/velour/catbase/plugins/rpgORdie" "github.com/velour/catbase/plugins/rss" @@ -89,7 +90,7 @@ func main() { b.AddPlugin(dice.New(b)) b.AddPlugin(picker.New(b)) b.AddPlugin(beers.New(b)) - b.AddPlugin(fact.NewRemember(b)) + b.AddPlugin(remember.New(b)) b.AddPlugin(your.New(b)) b.AddPlugin(counter.New(b)) b.AddPlugin(reminder.New(b)) diff --git a/plugins/fact/remember_test.go b/plugins/fact/fact_test.go similarity index 59% rename from plugins/fact/remember_test.go rename to plugins/fact/fact_test.go index a3ded28..c0fa9a9 100644 --- a/plugins/fact/remember_test.go +++ b/plugins/fact/fact_test.go @@ -23,32 +23,10 @@ func makeMessage(nick, payload string) msg.Message { } } -func makePlugin(t *testing.T) (*RememberPlugin, *Factoid, *bot.MockBot) { +func makePlugin(t *testing.T) (*FactoidPlugin, *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 don’t 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(bot.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") + return f, mb } func TestReact(t *testing.T) { @@ -56,7 +34,7 @@ func TestReact(t *testing.T) { makeMessage("user1", "!testing123 jesus"), makeMessage("user2", "testing123"), } - _, p, mb := makePlugin(t) + p, mb := makePlugin(t) for _, m := range msgs { p.message(bot.Message, m) @@ -69,7 +47,7 @@ func TestReactCantLearnSpaces(t *testing.T) { msgs := []msg.Message{ makeMessage("user1", "!test jesus christ"), } - _, p, mb := makePlugin(t) + p, mb := makePlugin(t) for _, m := range msgs { p.message(bot.Message, m) diff --git a/plugins/fact/factoid.go b/plugins/fact/factoid.go index d7479a9..b4cc1d4 100644 --- a/plugins/fact/factoid.go +++ b/plugins/fact/factoid.go @@ -22,14 +22,14 @@ import ( // respond to queries in a way that is unpredictable and fun // factoid stores info about our factoid for lookup and later interaction -type factoid struct { - id sql.NullInt64 +type Factoid struct { + ID sql.NullInt64 Fact string Tidbit string Verb string Owner string - created time.Time - accessed time.Time + Created time.Time + Accessed time.Time Count int } @@ -38,14 +38,14 @@ type alias struct { Next string } -func (a *alias) resolve(db *sqlx.DB) (*factoid, error) { +func (a *alias) resolve(db *sqlx.DB) (*Factoid, error) { // perform DB query to fill the To field q := `select fact, next from factoid_alias where fact=?` var next alias err := db.Get(&next, q, a.Next) if err != nil { // we hit the end of the chain, get a factoid named Next - fact, err := getSingleFact(db, a.Next) + fact, err := GetSingleFact(db, a.Next) if err != nil { err := fmt.Errorf("Error resolvig alias %v: %v", a, err) return nil, err @@ -55,7 +55,7 @@ func (a *alias) resolve(db *sqlx.DB) (*factoid, error) { return next.resolve(db) } -func findAlias(db *sqlx.DB, fact string) (bool, *factoid) { +func findAlias(db *sqlx.DB, fact string) (bool, *Factoid) { q := `select * from factoid_alias where fact=?` var a alias err := db.Get(&a, q, fact) @@ -89,9 +89,9 @@ func aliasFromStrings(from, to string) *alias { return &alias{from, to} } -func (f *factoid) save(db *sqlx.DB) error { +func (f *Factoid) Save(db *sqlx.DB) error { var err error - if f.id.Valid { + if f.ID.Valid { // update _, err = db.Exec(`update factoid set fact=?, @@ -105,12 +105,12 @@ func (f *factoid) save(db *sqlx.DB) error { f.Tidbit, f.Verb, f.Owner, - f.accessed.Unix(), + f.Accessed.Unix(), f.Count, - f.id.Int64) + f.ID.Int64) } else { - f.created = time.Now() - f.accessed = time.Now() + f.Created = time.Now() + f.Accessed = time.Now() // insert res, err := db.Exec(`insert into factoid ( fact, @@ -125,8 +125,8 @@ func (f *factoid) save(db *sqlx.DB) error { f.Tidbit, f.Verb, f.Owner, - f.created.Unix(), - f.accessed.Unix(), + f.Created.Unix(), + f.Accessed.Unix(), f.Count, ) if err != nil { @@ -134,23 +134,23 @@ func (f *factoid) save(db *sqlx.DB) error { } id, err := res.LastInsertId() // hackhackhack? - f.id.Int64 = id - f.id.Valid = true + f.ID.Int64 = id + f.ID.Valid = true } return err } -func (f *factoid) delete(db *sqlx.DB) error { +func (f *Factoid) delete(db *sqlx.DB) error { var err error - if f.id.Valid { - _, err = db.Exec(`delete from factoid where id=?`, f.id) + if f.ID.Valid { + _, err = db.Exec(`delete from factoid where id=?`, f.ID) } - f.id.Valid = false + f.ID.Valid = false return err } -func getFacts(db *sqlx.DB, fact string, tidbit string) ([]*factoid, error) { - var fs []*factoid +func getFacts(db *sqlx.DB, fact string, tidbit string) ([]*Factoid, error) { + var fs []*Factoid query := `select id, fact, @@ -170,11 +170,11 @@ func getFacts(db *sqlx.DB, fact string, tidbit string) ([]*factoid, error) { return nil, err } for rows.Next() { - var f factoid + var f Factoid var tmpCreated int64 var tmpAccessed int64 err := rows.Scan( - &f.id, + &f.ID, &f.Fact, &f.Tidbit, &f.Verb, @@ -186,15 +186,15 @@ func getFacts(db *sqlx.DB, fact string, tidbit string) ([]*factoid, error) { if err != nil { return nil, err } - f.created = time.Unix(tmpCreated, 0) - f.accessed = time.Unix(tmpAccessed, 0) + f.Created = time.Unix(tmpCreated, 0) + f.Accessed = time.Unix(tmpAccessed, 0) fs = append(fs, &f) } return fs, err } -func getSingle(db *sqlx.DB) (*factoid, error) { - var f factoid +func GetSingle(db *sqlx.DB) (*Factoid, error) { + var f Factoid var tmpCreated int64 var tmpAccessed int64 err := db.QueryRow(`select @@ -208,7 +208,7 @@ func getSingle(db *sqlx.DB) (*factoid, error) { count from factoid order by random() limit 1;`).Scan( - &f.id, + &f.ID, &f.Fact, &f.Tidbit, &f.Verb, @@ -217,13 +217,13 @@ func getSingle(db *sqlx.DB) (*factoid, error) { &tmpAccessed, &f.Count, ) - f.created = time.Unix(tmpCreated, 0) - f.accessed = time.Unix(tmpAccessed, 0) + f.Created = time.Unix(tmpCreated, 0) + f.Accessed = time.Unix(tmpAccessed, 0) return &f, err } -func getSingleFact(db *sqlx.DB, fact string) (*factoid, error) { - var f factoid +func GetSingleFact(db *sqlx.DB, fact string) (*Factoid, error) { + var f Factoid var tmpCreated int64 var tmpAccessed int64 err := db.QueryRow(`select @@ -239,7 +239,7 @@ func getSingleFact(db *sqlx.DB, fact string) (*factoid, error) { where fact like ? order by random() limit 1;`, fact).Scan( - &f.id, + &f.ID, &f.Fact, &f.Tidbit, &f.Verb, @@ -248,22 +248,22 @@ func getSingleFact(db *sqlx.DB, fact string) (*factoid, error) { &tmpAccessed, &f.Count, ) - f.created = time.Unix(tmpCreated, 0) - f.accessed = time.Unix(tmpAccessed, 0) + f.Created = time.Unix(tmpCreated, 0) + f.Accessed = time.Unix(tmpAccessed, 0) return &f, err } // Factoid provides the necessary plugin-wide needs -type Factoid struct { +type FactoidPlugin struct { Bot bot.Bot NotFound []string - LastFact *factoid + LastFact *Factoid db *sqlx.DB } // NewFactoid creates a new Factoid with the Plugin interface -func New(botInst bot.Bot) *Factoid { - p := &Factoid{ +func New(botInst bot.Bot) *FactoidPlugin { + p := &FactoidPlugin{ Bot: botInst, NotFound: []string{ "I don't know.", @@ -343,7 +343,7 @@ func findAction(message string) string { // learnFact assumes we have a learning situation and inserts a new fact // into the database -func (p *Factoid) learnFact(message msg.Message, fact, verb, tidbit string) error { +func (p *FactoidPlugin) learnFact(message msg.Message, fact, verb, tidbit string) error { verb = strings.ToLower(verb) if verb == "react" { // This would be a great place to check against the API for valid emojy @@ -366,17 +366,17 @@ func (p *Factoid) learnFact(message msg.Message, fact, verb, tidbit string) erro return fmt.Errorf("Look, I already know that.") } - n := factoid{ + n := Factoid{ Fact: fact, Tidbit: tidbit, Verb: verb, Owner: message.User.Name, - created: time.Now(), - accessed: time.Now(), + Created: time.Now(), + Accessed: time.Now(), Count: 0, } p.LastFact = &n - err = n.save(p.db) + err = n.Save(p.db) if err != nil { log.Println("Error inserting fact: ", err) return fmt.Errorf("My brain is overheating.") @@ -386,10 +386,10 @@ func (p *Factoid) learnFact(message msg.Message, fact, verb, tidbit string) erro } // findTrigger checks to see if a given string is a trigger or not -func (p *Factoid) findTrigger(fact string) (bool, *factoid) { +func (p *FactoidPlugin) findTrigger(fact string) (bool, *Factoid) { 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) if err != nil { return findAlias(p.db, fact) } @@ -398,7 +398,7 @@ func (p *Factoid) findTrigger(fact string) (bool, *factoid) { // sayFact spits out a fact to the channel and updates the fact in the database // with new time and count information -func (p *Factoid) sayFact(message msg.Message, fact factoid) { +func (p *FactoidPlugin) sayFact(message msg.Message, fact Factoid) { msg := p.Bot.Filter(message, fact.Tidbit) full := p.Bot.Filter(message, fmt.Sprintf("%s %s %s", fact.Fact, fact.Verb, fact.Tidbit, @@ -421,9 +421,9 @@ func (p *Factoid) sayFact(message msg.Message, fact factoid) { } // update fact tracking - fact.accessed = time.Now() + fact.Accessed = time.Now() fact.Count += 1 - err := fact.save(p.db) + err := fact.Save(p.db) if err != nil { log.Printf("Could not update fact.\n") log.Printf("%#v\n", fact) @@ -434,7 +434,7 @@ func (p *Factoid) sayFact(message msg.Message, fact factoid) { // 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 -func (p *Factoid) trigger(message msg.Message) bool { +func (p *FactoidPlugin) trigger(message msg.Message) bool { minLen := p.Bot.Config().GetInt("Factoid.MinLen", 4) if len(message.Body) > minLen || message.Command || message.Body == "..." { if ok, fact := p.findTrigger(message.Body); ok { @@ -453,20 +453,20 @@ func (p *Factoid) trigger(message msg.Message) bool { } // tellThemWhatThatWas is a hilarious name for a function. -func (p *Factoid) tellThemWhatThatWas(message msg.Message) bool { +func (p *FactoidPlugin) tellThemWhatThatWas(message msg.Message) bool { fact := p.LastFact var msg string if fact == nil { msg = "Nope." } else { msg = fmt.Sprintf("That was (#%d) '%s <%s> %s'", - fact.id.Int64, fact.Fact, fact.Verb, fact.Tidbit) + fact.ID.Int64, fact.Fact, fact.Verb, fact.Tidbit) } p.Bot.Send(bot.Message, message.Channel, msg) return true } -func (p *Factoid) learnAction(message msg.Message, action string) bool { +func (p *FactoidPlugin) learnAction(message msg.Message, action string) bool { body := message.Body parts := strings.SplitN(body, action, 2) @@ -512,7 +512,7 @@ func changeOperator(body string) string { // If the user requesting forget is either the owner of the last learned fact or // an admin, it may be deleted -func (p *Factoid) forgetLastFact(message msg.Message) bool { +func (p *FactoidPlugin) forgetLastFact(message msg.Message) bool { if p.LastFact == nil { p.Bot.Send(bot.Message, message.Channel, "I refuse.") return true @@ -522,7 +522,7 @@ func (p *Factoid) forgetLastFact(message msg.Message) bool { if err != nil { log.Println("Error removing fact: ", p.LastFact, err) } - fmt.Printf("Forgot #%d: %s %s %s\n", p.LastFact.id.Int64, p.LastFact.Fact, + fmt.Printf("Forgot #%d: %s %s %s\n", p.LastFact.ID.Int64, p.LastFact.Fact, p.LastFact.Verb, p.LastFact.Tidbit) p.Bot.Send(bot.Action, message.Channel, "hits himself over the head with a skillet") p.LastFact = nil @@ -531,7 +531,7 @@ func (p *Factoid) forgetLastFact(message msg.Message) bool { } // Allow users to change facts with a simple regexp -func (p *Factoid) changeFact(message msg.Message) bool { +func (p *FactoidPlugin) changeFact(message msg.Message) bool { oper := changeOperator(message.Body) parts := strings.SplitN(message.Body, oper, 2) userexp := strings.TrimSpace(parts[1]) @@ -571,8 +571,8 @@ func (p *Factoid) changeFact(message msg.Message) bool { fact.Verb = reg.ReplaceAllString(fact.Verb, replace) fact.Tidbit = reg.ReplaceAllString(fact.Tidbit, replace) fact.Count += 1 - fact.accessed = time.Now() - fact.save(p.db) + fact.Accessed = time.Now() + fact.Save(p.db) } } else if len(parts) == 3 { // search for a factoid and print it @@ -614,7 +614,7 @@ func (p *Factoid) changeFact(message msg.Message) bool { // Message responds to the bot hook on recieving messages. // This function returns true if the plugin responds in a meaningful way to the users message. // Otherwise, the function returns false and the bot continues execution of other plugins. -func (p *Factoid) message(kind bot.Kind, message msg.Message, args ...interface{}) bool { +func (p *FactoidPlugin) message(kind bot.Kind, message msg.Message, args ...interface{}) bool { if strings.ToLower(message.Body) == "what was that?" { return p.tellThemWhatThatWas(message) } @@ -674,15 +674,15 @@ func (p *Factoid) message(kind bot.Kind, message msg.Message, args ...interface{ } // Help responds to help requests. Every plugin must implement a help function. -func (p *Factoid) help(kind bot.Kind, message msg.Message, args ...interface{}) bool { +func (p *FactoidPlugin) help(kind bot.Kind, message msg.Message, args ...interface{}) bool { p.Bot.Send(bot.Message, message.Channel, "I can learn facts and spit them back out. You can say \"this is that\" or \"he $5\". Later, trigger the factoid by just saying the trigger word, \"this\" or \"he\" in these examples.") p.Bot.Send(bot.Message, message.Channel, "I can also figure out some variables including: $nonzero, $digit, $nick, and $someone.") return true } // Pull a fact at random from the database -func (p *Factoid) randomFact() *factoid { - f, err := getSingle(p.db) +func (p *FactoidPlugin) randomFact() *Factoid { + f, err := GetSingle(p.db) if err != nil { fmt.Println("Error getting a fact: ", err) return nil @@ -691,7 +691,7 @@ func (p *Factoid) randomFact() *factoid { } // factTimer spits out a fact at a given interval and with given probability -func (p *Factoid) factTimer(channel string) { +func (p *FactoidPlugin) factTimer(channel string) { quoteTime := p.Bot.Config().GetInt("Factoid.QuoteTime", 30) if quoteTime == 0 { quoteTime = 30 @@ -739,7 +739,7 @@ func (p *Factoid) factTimer(channel string) { } // Register any web URLs desired -func (p *Factoid) registerWeb() { +func (p *FactoidPlugin) registerWeb() { http.HandleFunc("/factoid/req", p.serveQuery) http.HandleFunc("/factoid", p.serveQuery) p.Bot.RegisterWeb("/factoid", "Factoid") @@ -755,7 +755,7 @@ func linkify(text string) template.HTML { return template.HTML(strings.Join(parts, " ")) } -func (p *Factoid) serveQuery(w http.ResponseWriter, r *http.Request) { +func (p *FactoidPlugin) serveQuery(w http.ResponseWriter, r *http.Request) { context := make(map[string]interface{}) funcMap := template.FuncMap{ // The name "title" is what the function will be called in the template text. diff --git a/plugins/fact/remember.go b/plugins/remember/remember.go similarity index 65% rename from plugins/fact/remember.go rename to plugins/remember/remember.go index 8aa32da..820b5fa 100644 --- a/plugins/fact/remember.go +++ b/plugins/remember/remember.go @@ -1,6 +1,4 @@ -// © 2013 the CatBase Authors under the WTFPL. See AUTHORS for the list of authors. - -package fact +package remember import ( "fmt" @@ -11,38 +9,32 @@ import ( "github.com/jmoiron/sqlx" "github.com/velour/catbase/bot" "github.com/velour/catbase/bot/msg" + "github.com/velour/catbase/plugins/fact" ) -// This is a skeleton plugin to serve as an example and quick copy/paste for new -// plugins. - type RememberPlugin struct { - Bot bot.Bot - Log map[string][]msg.Message + bot bot.Bot + log map[string][]msg.Message db *sqlx.DB } -// NewRememberPlugin creates a new RememberPlugin with the Plugin interface -func NewRemember(b bot.Bot) *RememberPlugin { - p := RememberPlugin{ - Bot: b, - Log: make(map[string][]msg.Message), +func New(b bot.Bot) *RememberPlugin { + p := &RememberPlugin{ + bot: b, + log: make(map[string][]msg.Message), db: b.DB(), } + b.Register(p, bot.Message, p.message) - b.Register(p, bot.Message, p.help) - return &p + b.Register(p, bot.Help, p.help) + + return p } -// Message responds to the bot hook on recieving messages. -// This function returns true if the plugin responds in a meaningful way to the -// users message. Otherwise, the function returns false and the bot continues -// execution of other plugins. func (p *RememberPlugin) message(kind bot.Kind, message msg.Message, args ...interface{}) bool { - if strings.ToLower(message.Body) == "quote" && message.Command { q := p.randQuote() - p.Bot.Send(bot.Message, message.Channel, q) + p.bot.Send(bot.Message, message.Channel, q) // is it evil not to remember that the user said quote? return true @@ -50,16 +42,16 @@ func (p *RememberPlugin) message(kind bot.Kind, message msg.Message, args ...int user := message.User parts := strings.Fields(message.Body) + if message.Command && len(parts) >= 3 && strings.ToLower(parts[0]) == "remember" { - // we have a remember! // look through the logs and find parts[1] as a user, if not, // fuck this hoser nick := parts[1] snip := strings.Join(parts[2:], " ") - for i := len(p.Log[message.Channel]) - 1; i >= 0; i-- { - entry := p.Log[message.Channel][i] + for i := len(p.log[message.Channel]) - 1; i >= 0; i-- { + entry := p.log[message.Channel][i] log.Printf("Comparing %s:%s with %s:%s", entry.User.Name, entry.Body, nick, snip) if strings.ToLower(entry.User.Name) == strings.ToLower(nick) && @@ -78,18 +70,18 @@ func (p *RememberPlugin) message(kind bot.Kind, message msg.Message, args ...int trigger := fmt.Sprintf("%s quotes", entry.User.Name) - fact := factoid{ + fact := fact.Factoid{ Fact: strings.ToLower(trigger), Verb: "reply", Tidbit: msg, Owner: user.Name, - created: time.Now(), - accessed: time.Now(), + Created: time.Now(), + Accessed: time.Now(), Count: 0, } - if err := fact.save(p.db); err != nil { + if err := fact.Save(p.db); err != nil { log.Println("ERROR!!!!:", err) - p.Bot.Send(bot.Message, message.Channel, "Tell somebody I'm broke.") + p.bot.Send(bot.Message, message.Channel, "Tell somebody I'm broke.") } log.Println("Remembering factoid:", msg) @@ -97,30 +89,28 @@ func (p *RememberPlugin) message(kind bot.Kind, message msg.Message, args ...int // sorry, not creative with names so we're reusing msg msg = fmt.Sprintf("Okay, %s, remembering '%s'.", message.User.Name, msg) - p.Bot.Send(bot.Message, message.Channel, msg) + p.bot.Send(bot.Message, message.Channel, msg) p.recordMsg(message) return true } } - - p.Bot.Send(bot.Message, message.Channel, "Sorry, I don't know that phrase.") + p.bot.Send(bot.Message, message.Channel, "Sorry, I don't know that phrase.") p.recordMsg(message) return true } + p.recordMsg(message) return false } -// Help responds to help requests. Every plugin must implement a help function. func (p *RememberPlugin) help(kind bot.Kind, message msg.Message, args ...interface{}) bool { - - msg := "!remember will let you quote your idiot friends. Just type " + + msg := "remember will let you quote your idiot friends. Just type " + "!remember to remember what they said. Snippet can " + "be any part of their message. Later on, you can ask for a random " + "!quote." - p.Bot.Send(bot.Message, message.Channel, msg) + p.bot.Send(bot.Message, message.Channel, msg) return true } @@ -129,12 +119,12 @@ func (p *RememberPlugin) help(kind bot.Kind, message msg.Message, args ...interf // expanded to have this function execute a quote for a particular channel func (p *RememberPlugin) randQuote() string { - var f factoid + var f fact.Factoid var tmpCreated int64 var tmpAccessed int64 err := p.db.QueryRow(`select * from factoid where fact like '%quotes' order by random() limit 1;`).Scan( - &f.id, + &f.ID, &f.Fact, &f.Tidbit, &f.Verb, @@ -147,13 +137,13 @@ func (p *RememberPlugin) randQuote() string { log.Println("Error getting quotes: ", err) return "I had a problem getting your quote." } - f.created = time.Unix(tmpCreated, 0) - f.accessed = time.Unix(tmpAccessed, 0) + f.Created = time.Unix(tmpCreated, 0) + f.Accessed = time.Unix(tmpAccessed, 0) return f.Tidbit } func (p *RememberPlugin) recordMsg(message msg.Message) { log.Printf("Logging message: %s: %s", message.User.Name, message.Body) - p.Log[message.Channel] = append(p.Log[message.Channel], message) + p.log[message.Channel] = append(p.log[message.Channel], message) } diff --git a/plugins/remember/remember_test.go b/plugins/remember/remember_test.go new file mode 100644 index 0000000..8a1512a --- /dev/null +++ b/plugins/remember/remember_test.go @@ -0,0 +1,53 @@ +package remember + +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" + "github.com/velour/catbase/plugins/fact" +) + +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, *fact.FactoidPlugin, *bot.MockBot) { + mb := bot.NewMockBot() + f := fact.New(mb) // for DB table + p := New(mb) + assert.NotNil(t, p) + return p, f, mb +} + +// Test case +func TestCornerCaseBug(t *testing.T) { + msgs := []msg.Message{ + makeMessage("user1", "I don’t 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(bot.Message, m) + } + assert.Len(t, mb.Messages, 1) + assert.Contains(t, mb.Messages[0], "horse dick") + q, err := fact.GetSingleFact(mb.DB(), "user1 quotes") + assert.Nil(t, err) + assert.Contains(t, q.Tidbit, "horse dick") +} From 30944bf620118f5a395b835efc645c7fccc64f43 Mon Sep 17 00:00:00 2001 From: Chris Sexton Date: Fri, 15 Feb 2019 15:00:01 -0500 Subject: [PATCH 3/3] Revert "main: removed zork plugin" This reverts commit 6fb0990a11912dbcecfe42c82661a084e6edf8a4. --- main.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/main.go b/main.go index 0e5e311..aa5c352 100644 --- a/main.go +++ b/main.go @@ -38,6 +38,7 @@ import ( "github.com/velour/catbase/plugins/tell" "github.com/velour/catbase/plugins/twitch" "github.com/velour/catbase/plugins/your" + "github.com/velour/catbase/plugins/zork" ) var ( @@ -95,6 +96,7 @@ func main() { b.AddPlugin(counter.New(b)) b.AddPlugin(reminder.New(b)) b.AddPlugin(babbler.New(b)) + b.AddPlugin(zork.New(b)) b.AddPlugin(rss.New(b)) b.AddPlugin(reaction.New(b)) b.AddPlugin(twitch.New(b))