diff --git a/bot/interfaces.go b/bot/interfaces.go index 173107f..47e389a 100644 --- a/bot/interfaces.go +++ b/bot/interfaces.go @@ -35,6 +35,8 @@ const ( SelfMessage // Delete removes a message by ID Delete + // Startup is triggered after the connector has run the Serve function + Startup ) type EphemeralID string diff --git a/connectors/slackapp/slackApp.go b/connectors/slackapp/slackApp.go index bd4077b..b121da7 100644 --- a/connectors/slackapp/slackApp.go +++ b/connectors/slackapp/slackApp.go @@ -676,6 +676,7 @@ func (s *SlackApp) Profile(identifier string) (user.User, error) { } for _, u := range users { + log.Debug().Str("Name", u.Name).Str("ID", u.ID).Msgf("Looking for %s", identifier) if u.Name == identifier || u.ID == identifier { return user.User{ ID: u.ID, diff --git a/main.go b/main.go index d745a91..bcfbec5 100644 --- a/main.go +++ b/main.go @@ -9,6 +9,7 @@ import ( "os" "time" + "github.com/velour/catbase/bot/msg" "github.com/velour/catbase/connectors/discord" "github.com/velour/catbase/plugins/gpt2" @@ -158,6 +159,8 @@ func main() { log.Fatal().Err(err) } + b.Receive(client, bot.Startup, msg.Message{}) + addr := c.Get("HttpAddr", "127.0.0.1:1337") log.Debug().Msgf("starting web service at %s", addr) log.Fatal().Err(http.ListenAndServe(addr, nil)).Msg("bot killed") diff --git a/plugins/beers/beers.go b/plugins/beers/beers.go index 9da3e38..f1ae2d3 100644 --- a/plugins/beers/beers.go +++ b/plugins/beers/beers.go @@ -98,22 +98,23 @@ func (p *BeersPlugin) register() { op := r.Values["operator"] count, _ := strconv.Atoi(r.Values["amount"]) nick := r.Msg.User.Name + id := r.Msg.User.ID switch op { case "=": if count == 0 { - p.puke(r.Conn, nick, r.Msg.Channel) + p.puke(r.Conn, nick, id, r.Msg.Channel) } else { - p.setBeers(nick, count) + p.setBeers(nick, id, count) p.randomReply(r.Conn, r.Msg.Channel) } return true case "+=": - p.addBeers(nick, count) + p.addBeers(nick, id, count) p.randomReply(r.Conn, r.Msg.Channel) return true case "-=": - p.addBeers(nick, -count) + p.addBeers(nick, id, -count) p.randomReply(r.Conn, r.Msg.Channel) return true } @@ -124,10 +125,11 @@ func (p *BeersPlugin) register() { Handler: func(r bot.Request) bool { op := r.Values["operator"] nick := r.Msg.User.Name + id := r.Msg.User.ID if op == "++" { - p.addBeers(nick, 1) + p.addBeers(nick, id, 1) } else { - p.addBeers(nick, -1) + p.addBeers(nick, id, -1) } p.randomReply(r.Conn, r.Msg.Channel) return true @@ -139,8 +141,8 @@ func (p *BeersPlugin) register() { if who == "" { who = r.Msg.User.Name } - if p.doIKnow(who) { - p.reportCount(r.Conn, who, r.Msg.Channel, false) + if p.doIKnow(who, "") { + p.reportCount(r.Conn, who, "", r.Msg.Channel, false) } else { msg := fmt.Sprintf("Sorry, I don't know %s.", who) p.b.Send(r.Conn, bot.Message, r.Msg.Channel, msg) @@ -150,14 +152,14 @@ func (p *BeersPlugin) register() { {Kind: bot.Message, IsCmd: true, Regex: regexp.MustCompile(`(?i)^puke$`), Handler: func(r bot.Request) bool { - p.puke(r.Conn, r.Msg.User.Name, r.Msg.Channel) + p.puke(r.Conn, r.Msg.User.Name, r.Msg.User.ID, r.Msg.Channel) return true }}, {Kind: bot.Message, IsCmd: true, Regex: regexp.MustCompile(`(?i)^` + strings.Join(p.c.GetArray("beers.imbibewords", []string{"imbibe", "quaff"}), "|") + `$`), Handler: func(r bot.Request) bool { - p.addBeers(r.Msg.User.Name, 1) + p.addBeers(r.Msg.User.Name, r.Msg.User.ID, 1) p.randomReply(r.Conn, r.Msg.Channel) return true }}, @@ -237,34 +239,35 @@ func (p *BeersPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, return true } -func getUserBeers(db *sqlx.DB, user string) counter.Item { - booze, _ := counter.GetUserItem(db, user, itemName) +func getUserBeers(db *sqlx.DB, user, id string) counter.Item { + // TODO: really ought to have an ID here + booze, _ := counter.GetUserItem(db, user, id, itemName) return booze } -func (p *BeersPlugin) setBeers(user string, amount int) { - ub := getUserBeers(p.db, user) +func (p *BeersPlugin) setBeers(user, id string, amount int) { + ub := getUserBeers(p.db, user, id) err := ub.Update(amount) if err != nil { log.Error().Err(err).Msgf("Error saving beers") } } -func (p *BeersPlugin) addBeers(user string, delta int) { - ub := getUserBeers(p.db, user) +func (p *BeersPlugin) addBeers(user, id string, delta int) { + ub := getUserBeers(p.db, user, id) err := ub.UpdateDelta(delta) if err != nil { log.Error().Err(err).Msgf("Error saving beers") } } -func (p *BeersPlugin) getBeers(nick string) int { - ub := getUserBeers(p.db, nick) +func (p *BeersPlugin) getBeers(nick, id string) int { + ub := getUserBeers(p.db, nick, id) return ub.Count } -func (p *BeersPlugin) reportCount(c bot.Connector, nick, channel string, himself bool) { - beers := p.getBeers(nick) +func (p *BeersPlugin) reportCount(c bot.Connector, nick, id, channel string, himself bool) { + beers := p.getBeers(nick, id) msg := fmt.Sprintf("%s has had %d beers so far.", nick, beers) if himself { if beers == 0 { @@ -276,14 +279,14 @@ func (p *BeersPlugin) reportCount(c bot.Connector, nick, channel string, himself p.b.Send(c, bot.Message, channel, msg) } -func (p *BeersPlugin) puke(c bot.Connector, user string, channel string) { - p.setBeers(user, 0) +func (p *BeersPlugin) puke(c bot.Connector, user, id string, channel string) { + p.setBeers(user, id, 0) msg := fmt.Sprintf("Ohhhhhh, and a reversal of fortune for %s!", user) p.b.Send(c, bot.Message, channel, msg) } -func (p *BeersPlugin) doIKnow(nick string) bool { - count := p.getBeers(nick) +func (p *BeersPlugin) doIKnow(nick, id string) bool { + count := p.getBeers(nick, id) return count > 0 } @@ -471,8 +474,8 @@ 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) - p.addBeers(user.chanNick, 1) - drunken := p.getBeers(user.chanNick) + p.addBeers(user.chanNick, "", 1) + drunken := p.getBeers(user.chanNick, "") msg := fmt.Sprintf("%s just drank %s by %s%s, bringing his drunkeness to %d", user.chanNick, beerName, breweryName, venue, drunken) diff --git a/plugins/beers/beers_test.go b/plugins/beers/beers_test.go index cbe07e6..cd5f677 100644 --- a/plugins/beers/beers_test.go +++ b/plugins/beers/beers_test.go @@ -28,7 +28,7 @@ func makeMessage(payload string, r *regexp.Regexp) bot.Request { Kind: bot.Message, Values: values, Msg: msg.Message{ - User: &user.User{Name: "tester"}, + User: &user.User{Name: "tester", ID: "id"}, Channel: "test", Body: payload, Command: isCmd, @@ -60,7 +60,7 @@ func makeBeersPlugin(t *testing.T) (*BeersPlugin, *bot.MockBot) { func TestCounter(t *testing.T) { _, mb := makeBeersPlugin(t) - i, err := counter.GetUserItem(mb.DB(), "tester", "test") + i, err := counter.GetUserItem(mb.DB(), "tester", "id", "test") if !assert.Nil(t, err) { t.Log(err) t.Fatal() @@ -75,7 +75,7 @@ func TestImbibe(t *testing.T) { assert.Len(t, mb.Messages, 1) testMessage(b, "imbibe") assert.Len(t, mb.Messages, 2) - it, err := counter.GetUserItem(mb.DB(), "tester", itemName) + it, err := counter.GetUserItem(mb.DB(), "tester", "id", itemName) assert.Nil(t, err) assert.Equal(t, 2, it.Count) } @@ -83,7 +83,7 @@ func TestEq(t *testing.T) { b, mb := makeBeersPlugin(t) testMessage(b, "beers = 3") assert.Len(t, mb.Messages, 1) - it, err := counter.GetUserItem(mb.DB(), "tester", itemName) + it, err := counter.GetUserItem(mb.DB(), "tester", "id", itemName) assert.Nil(t, err) assert.Equal(t, 3, it.Count) } @@ -94,7 +94,7 @@ func TestEqZero(t *testing.T) { testMessage(b, "beers = 0") assert.Len(t, mb.Messages, 2) assert.Contains(t, mb.Messages[1], "reversal of fortune") - it, err := counter.GetUserItem(mb.DB(), "tester", itemName) + it, err := counter.GetUserItem(mb.DB(), "tester", "id", itemName) assert.Nil(t, err) assert.Equal(t, 0, it.Count) } @@ -105,7 +105,7 @@ func TestBeersPlusEq(t *testing.T) { assert.Len(t, mb.Messages, 1) testMessage(b, "beers += 5") assert.Len(t, mb.Messages, 2) - it, err := counter.GetUserItem(mb.DB(), "tester", itemName) + it, err := counter.GetUserItem(mb.DB(), "tester", "id", itemName) assert.Nil(t, err) assert.Equal(t, 10, it.Count) } @@ -113,11 +113,11 @@ func TestBeersPlusEq(t *testing.T) { func TestPuke(t *testing.T) { b, mb := makeBeersPlugin(t) testMessage(b, "beers += 5") - it, err := counter.GetUserItem(mb.DB(), "tester", itemName) + it, err := counter.GetUserItem(mb.DB(), "tester", "id", itemName) assert.Nil(t, err) assert.Equal(t, 5, it.Count) testMessage(b, "puke") - it, err = counter.GetUserItem(mb.DB(), "tester", itemName) + it, err = counter.GetUserItem(mb.DB(), "tester", "id", itemName) assert.Nil(t, err) assert.Equal(t, 0, it.Count) } @@ -125,7 +125,7 @@ func TestPuke(t *testing.T) { func TestBeersReport(t *testing.T) { b, mb := makeBeersPlugin(t) testMessage(b, "beers += 5") - it, err := counter.GetUserItem(mb.DB(), "tester", itemName) + it, err := counter.GetUserItem(mb.DB(), "tester", "id", itemName) assert.Nil(t, err) assert.Equal(t, 5, it.Count) testMessage(b, "beers") diff --git a/plugins/counter/counter.go b/plugins/counter/counter.go index cba426c..c2e2fcc 100644 --- a/plugins/counter/counter.go +++ b/plugins/counter/counter.go @@ -28,10 +28,11 @@ type CounterPlugin struct { type Item struct { *sqlx.DB - ID int64 - Nick string - Item string - Count int + ID int64 + Nick string + Item string + Count int + UserID string } type alias struct { @@ -57,9 +58,14 @@ func GetAllItems(db *sqlx.DB) ([]Item, error) { } // GetItems returns all counters for a subject -func GetItems(db *sqlx.DB, nick string) ([]Item, error) { +func GetItems(db *sqlx.DB, nick, id string) ([]Item, error) { var items []Item - err := db.Select(&items, `select * from counter where nick = ?`, nick) + var err error + if id != "" { + err = db.Select(&items, `select * from counter where userid = ?`, id) + } else { + err = db.Select(&items, `select * from counter where nick = ?`, nick) + } if err != nil { return nil, err } @@ -162,7 +168,7 @@ func GetItem(db *sqlx.DB, itemName string) ([]Item, error) { } // GetUserItem returns a specific counter for a subject -func GetUserItem(db *sqlx.DB, nick, itemName string) (Item, error) { +func GetUserItem(db *sqlx.DB, nick, id, itemName string) (Item, error) { itemName = trimUnicode(itemName) var item Item item.DB = db @@ -173,19 +179,25 @@ func GetUserItem(db *sqlx.DB, nick, itemName string) (Item, error) { log.Error().Err(err).Interface("alias", a) } - err := db.Get(&item, `select * from counter where nick = ? and item= ?`, - nick, itemName) + var err error + if id != "" { + err = db.Get(&item, `select * from counter where userid = ? and item= ?`, id, itemName) + } else { + err = db.Get(&item, `select * from counter where nick = ? and item= ?`, nick, itemName) + } switch err { case sql.ErrNoRows: item.ID = -1 item.Nick = nick item.Item = itemName + item.UserID = id case nil: default: return Item{}, err } log.Debug(). Str("nick", nick). + Str("id", id). Str("itemName", itemName). Interface("item", item). Msg("got item") @@ -195,8 +207,8 @@ func GetUserItem(db *sqlx.DB, nick, itemName string) (Item, error) { // GetUserItem returns a specific counter for a subject // Create saves a counter func (i *Item) Create() error { - res, err := i.Exec(`insert into counter (nick, item, count) values (?, ?, ?);`, - i.Nick, i.Item, i.Count) + res, err := i.Exec(`insert into counter (nick, item, count, userid) values (?, ?, ?, ?);`, + i.Nick, i.Item, i.Count, i.UserID) if err != nil { return err } @@ -241,26 +253,80 @@ func (i *Item) Delete() error { return err } -// NewCounterPlugin creates a new CounterPlugin with the Plugin interface -func New(b bot.Bot) *CounterPlugin { - tx := b.DB().MustBegin() - b.DB().MustExec(`create table if not exists counter ( +func (p *CounterPlugin) migrate(r bot.Request) bool { + db := p.DB + + nicks := []string{} + err := db.Select(&nicks, `select distinct nick from counter where userid is null`) + if err != nil { + log.Error().Err(err).Msg("could not get nick list") + return false + } + + log.Debug().Msgf("Migrating %d nicks to IDs", len(nicks)) + + tx := db.MustBegin() + + for _, nick := range nicks { + user, err := r.Conn.Profile(nick) + if err != nil { + continue + } + if _, err = tx.Exec(`update counter set userid=? where nick=?`, user.ID, nick); err != nil { + log.Error().Err(err).Msg("Could not migrate users") + continue + } + } + + if err := tx.Commit(); err != nil { + log.Error().Err(err).Msg("Could not migrate users") + } + return false +} + +func setupDB(b bot.Bot) error { + db := b.DB() + tx := db.MustBegin() + db.MustExec(`create table if not exists counter ( id integer primary key, nick string, item string, count integer );`) - b.DB().MustExec(`create table if not exists counter_alias ( + db.MustExec(`create table if not exists counter_alias ( id integer PRIMARY KEY AUTOINCREMENT, item string NOT NULL UNIQUE, points_to string NOT NULL );`) tx.Commit() + + tx = db.MustBegin() + count := 0 + err := tx.Get(&count, `SELECT count(*) FROM pragma_table_info('counter') where name='userid'`) + if err != nil { + return err + } + if count == 0 { + tx.MustExec(`alter table counter add column userid string`) + } + tx.Commit() + + return nil +} + +// NewCounterPlugin creates a new CounterPlugin with the Plugin interface +func New(b bot.Bot) *CounterPlugin { + if err := setupDB(b); err != nil { + panic(err) + } + cp := &CounterPlugin{ Bot: b, DB: b.DB(), } + b.RegisterRegex(cp, bot.Startup, regexp.MustCompile(`.*`), cp.migrate) + b.RegisterRegexCmd(cp, bot.Message, mkAliasRegex, cp.mkAliasCmd) b.RegisterRegexCmd(cp, bot.Message, rmAliasRegex, cp.rmAliasCmd) b.RegisterRegexCmd(cp, bot.Message, leaderboardRegex, cp.leaderboardCmd) @@ -363,10 +429,10 @@ func (p *CounterPlugin) leaderboardCmd(r bot.Request) bool { } func (p *CounterPlugin) resetCmd(r bot.Request) bool { - nick := r.Msg.User.Name + nick, id := p.resolveUser(r, "") channel := r.Msg.Channel - items, err := GetItems(p.DB, strings.ToLower(nick)) + items, err := GetItems(p.DB, nick, id) if err != nil { log.Error(). Err(err). @@ -384,32 +450,34 @@ func (p *CounterPlugin) resetCmd(r bot.Request) bool { } func (p *CounterPlugin) inspectCmd(r bot.Request) bool { - var subject string - subject = r.Values["who"] + who := r.Values["who"] + nick, id := "", "" + if who == "me" { + who = r.Msg.User.Name + nick, id = p.resolveUser(r, "") + } else { + nick, id = p.resolveUser(r, who) + } channel := r.Msg.Channel c := r.Conn - if subject == "me" { - subject = strings.ToLower(r.Msg.User.Name) - } else { - subject = strings.ToLower(subject) - } - log.Debug(). - Str("subject", subject). + Str("nick", nick). + Str("id", id). Msg("Getting counter") // pull all of the items associated with "subject" - items, err := GetItems(p.DB, subject) + items, err := GetItems(p.DB, nick, id) if err != nil { log.Error(). Err(err). - Str("subject", subject). + Str("nick", nick). + Str("id", id). Msg("Error retrieving items") p.Bot.Send(c, bot.Message, channel, "Something went wrong finding that counter;") return true } - resp := fmt.Sprintf("%s has the following counters:", subject) + resp := fmt.Sprintf("%s has the following counters:", nick) count := 0 for _, it := range items { count += 1 @@ -425,7 +493,7 @@ func (p *CounterPlugin) inspectCmd(r bot.Request) bool { resp += "." if count == 0 { - p.Bot.Send(c, bot.Message, channel, fmt.Sprintf("%s has no counters.", subject)) + p.Bot.Send(c, bot.Message, channel, fmt.Sprintf("%s has no counters.", nick)) return true } @@ -434,16 +502,17 @@ func (p *CounterPlugin) inspectCmd(r bot.Request) bool { } func (p *CounterPlugin) clearCmd(r bot.Request) bool { - subject := strings.ToLower(r.Msg.User.Name) + nick, id := p.resolveUser(r, "") itemName := strings.ToLower(r.Values["what"]) channel := r.Msg.Channel c := r.Conn - it, err := GetUserItem(p.DB, subject, itemName) + it, err := GetUserItem(p.DB, nick, id, itemName) if err != nil { log.Error(). Err(err). - Str("subject", subject). + Str("nick", nick). + Str("id", id). Str("itemName", itemName). Msg("Error getting item to remove") p.Bot.Send(c, bot.Message, channel, "Something went wrong removing that counter;") @@ -453,7 +522,8 @@ func (p *CounterPlugin) clearCmd(r bot.Request) bool { if err != nil { log.Error(). Err(err). - Str("subject", subject). + Str("nick", nick). + Str("id", id). Str("itemName", itemName). Msg("Error removing item") p.Bot.Send(c, bot.Message, channel, "Something went wrong removing that counter;") @@ -466,54 +536,51 @@ func (p *CounterPlugin) clearCmd(r bot.Request) bool { } func (p *CounterPlugin) countCmd(r bot.Request) bool { - var subject string - var itemName string - - if r.Values["what"] == "" && r.Values["who"] == "" { - return false - } else if r.Values["what"] != "" { - subject = strings.ToLower(r.Values["who"]) - itemName = strings.ToLower(r.Values["what"]) + itemName := strings.ToLower(r.Values["what"]) + nick, id := r.Msg.User.Name, r.Msg.User.ID + if r.Values["what"] == "" { + itemName = r.Values["who"] } else { - subject = strings.ToLower(r.Msg.User.Name) - itemName = strings.ToLower(r.Values["who"]) + nick, id = p.resolveUser(r, r.Values["who"]) } var item Item - item, err := GetUserItem(p.DB, subject, itemName) + item, err := GetUserItem(p.DB, nick, id, itemName) switch { case err == sql.ErrNoRows: p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("I don't think %s has any %s.", - subject, itemName)) + nick, itemName)) return true case err != nil: log.Error(). Err(err). - Str("subject", subject). + Str("nick", nick). + Str("id", id). Str("itemName", itemName). Msg("Error retrieving item count") return true } - p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("%s has %d %s.", subject, item.Count, + p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("%s has %d %s.", nick, item.Count, itemName)) return true } func (p *CounterPlugin) incrementCmd(r bot.Request) bool { - subject := r.Msg.User.Name + nick, id := r.Msg.User.Name, r.Msg.User.ID if r.Values["who"] != "" { - subject = strings.TrimSuffix(r.Values["who"], ".") + nick, id = p.resolveUser(r, r.Values["who"]) } itemName := r.Values["thing"] channel := r.Msg.Channel // ++ those fuckers - item, err := GetUserItem(p.DB, subject, itemName) + item, err := GetUserItem(p.DB, nick, id, itemName) if err != nil { log.Error(). Err(err). - Str("subject", subject). + Str("nick", nick). + Str("id", id). Str("itemName", itemName). Msg("error finding item") // Item ain't there, I guess @@ -521,48 +588,47 @@ func (p *CounterPlugin) incrementCmd(r bot.Request) bool { } log.Debug().Msgf("About to update item: %#v", item) item.UpdateDelta(1) - p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", subject, + p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", nick, item.Count, item.Item)) return true } func (p *CounterPlugin) decrementCmd(r bot.Request) bool { - subject := r.Msg.User.Name + nick, id := r.Msg.User.Name, r.Msg.User.ID if r.Values["who"] != "" { - subject = strings.TrimSuffix(r.Values["who"], ".") + nick, id = p.resolveUser(r, r.Values["who"]) } itemName := r.Values["thing"] channel := r.Msg.Channel // -- those fuckers - item, err := GetUserItem(p.DB, subject, itemName) + item, err := GetUserItem(p.DB, nick, id, itemName) if err != nil { log.Error(). Err(err). - Str("subject", subject). + Str("nick", nick). + Str("id", id). Str("itemName", itemName). Msg("Error finding item") // Item ain't there, I guess return false } item.UpdateDelta(-1) - p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", subject, + p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", nick, item.Count, item.Item)) return true } func (p *CounterPlugin) addToCmd(r bot.Request) bool { - subject := r.Msg.User.Name - if r.Values["who"] != "" { - subject = strings.TrimSuffix(r.Values["who"], ".") - } + nick, id := p.resolveUser(r, r.Values["who"]) itemName := r.Values["thing"] channel := r.Msg.Channel // += those fuckers - item, err := GetUserItem(p.DB, subject, itemName) + item, err := GetUserItem(p.DB, nick, id, itemName) if err != nil { log.Error(). Err(err). - Str("subject", subject). + Str("nick", nick). + Str("id", id). Str("itemName", itemName). Msg("Error finding item") // Item ain't there, I guess @@ -571,24 +637,22 @@ func (p *CounterPlugin) addToCmd(r bot.Request) bool { n, _ := strconv.Atoi(r.Values["amount"]) log.Debug().Msgf("About to update item by %d: %#v", n, item) item.UpdateDelta(n) - p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", subject, + p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", nick, item.Count, item.Item)) return true } func (p *CounterPlugin) removeFromCmd(r bot.Request) bool { - subject := r.Msg.User.Name - if r.Values["who"] != "" { - subject = strings.TrimSuffix(r.Values["who"], ".") - } + nick, id := p.resolveUser(r, r.Values["who"]) itemName := r.Values["thing"] channel := r.Msg.Channel // -= those fuckers - item, err := GetUserItem(p.DB, subject, itemName) + item, err := GetUserItem(p.DB, nick, id, itemName) if err != nil { log.Error(). Err(err). - Str("subject", subject). + Str("nick", nick). + Str("id", id). Str("itemName", itemName). Msg("Error finding item") // Item ain't there, I guess @@ -597,7 +661,7 @@ func (p *CounterPlugin) removeFromCmd(r bot.Request) bool { n, _ := strconv.Atoi(r.Values["amount"]) log.Debug().Msgf("About to update item by -%d: %#v", n, item) item.UpdateDelta(-n) - p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", subject, + p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", nick, item.Count, item.Item)) return true } @@ -614,7 +678,7 @@ func (p *CounterPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message } func (p *CounterPlugin) teaMatchCmd(r bot.Request) bool { - nick := r.Msg.User.Name + nick, id := r.Msg.User.Name, r.Msg.User.ID channel := r.Msg.Channel submatches := teaRegex.FindStringSubmatch(r.Msg.Body) @@ -624,7 +688,7 @@ func (p *CounterPlugin) teaMatchCmd(r bot.Request) bool { itemName := strings.ToLower(submatches[1]) // We will specifically allow :tea: to keep compatability - item, err := GetUserItem(p.DB, nick, itemName) + item, err := GetUserItem(p.DB, nick, id, itemName) if err != nil || (item.Count == 0 && item.Item != ":tea:") { log.Error(). Err(err). @@ -687,7 +751,8 @@ func (p *CounterPlugin) handleCounterAPI(w http.ResponseWriter, r *http.Request) w.Write(j) return } - item, err := GetUserItem(p.DB, info.User, info.Thing) + nick, id := p.resolveUser(bot.Request{Conn: p.Bot.DefaultConnector()}, info.User) + item, err := GetUserItem(p.DB, nick, id, info.Thing) if err != nil { log.Error(). Err(err). @@ -744,3 +809,19 @@ func sendUpdate(who, what string, amount int) { f(Update{who, what, amount}) } } + +func (p *CounterPlugin) resolveUser(r bot.Request, nick string) (string, string) { + id := "" + if nick != "" { + nick = strings.TrimSuffix(nick, ".") + u, err := r.Conn.Profile(nick) + if err == nil && u.ID != "" { + id = u.ID + } + } else if r.Msg.User != nil { + nick, id = r.Msg.User.Name, r.Msg.User.ID + } + nick = strings.ToLower(nick) + log.Debug().Msgf("resolveUser(%s, %s) => (%s, %s)", r.Msg.User.ID, nick, nick, id) + return nick, id +} diff --git a/plugins/counter/counter_test.go b/plugins/counter/counter_test.go index 6b0ad7b..f30998b 100644 --- a/plugins/counter/counter_test.go +++ b/plugins/counter/counter_test.go @@ -33,9 +33,9 @@ func makeMessage(payload string, r *regexp.Regexp) bot.Request { } values := bot.ParseValues(r, payload) return bot.Request{ - Conn: nil, + Conn: &cli.CliPlugin{}, Msg: msg.Message{ - User: &user.User{Name: "tester"}, + User: &user.User{Name: "tester", ID: "id"}, Body: payload, Command: isCmd, }, @@ -48,7 +48,7 @@ func TestMkAlias(t *testing.T) { assert.NotNil(t, c) c.mkAliasCmd(makeMessage("mkalias fuck mornings", mkAliasRegex)) c.incrementCmd(makeMessage("fuck++", incrementRegex)) - item, err := GetUserItem(mb.DB(), "tester", "mornings") + item, err := GetUserItem(mb.DB(), "tester", "id", "mornings") assert.Nil(t, err) assert.Equal(t, 1, item.Count) } @@ -59,7 +59,7 @@ func TestRmAlias(t *testing.T) { c.mkAliasCmd(makeMessage("mkalias fuck mornings", mkAliasRegex)) c.rmAliasCmd(makeMessage("rmalias fuck", rmAliasRegex)) c.incrementCmd(makeMessage("fuck++", incrementRegex)) - item, err := GetUserItem(mb.DB(), "tester", "mornings") + item, err := GetUserItem(mb.DB(), "tester", "id", "mornings") assert.Nil(t, err) assert.Equal(t, 0, item.Count) } @@ -69,7 +69,7 @@ func TestThreeSentencesExists(t *testing.T) { assert.NotNil(t, c) c.incrementCmd(makeMessage(":beer:++", incrementRegex)) c.teaMatchCmd(makeMessage(":beer:. Earl Grey. Hot.", teaRegex)) - item, err := GetUserItem(mb.DB(), "tester", ":beer:") + item, err := GetUserItem(mb.DB(), "tester", "id", ":beer:") assert.Nil(t, err) assert.Equal(t, 2, item.Count) } @@ -77,9 +77,9 @@ func TestThreeSentencesExists(t *testing.T) { func TestThreeSentencesNotExists(t *testing.T) { mb, c := setup(t) assert.NotNil(t, c) - item, err := GetUserItem(mb.DB(), "tester", ":beer:") + item, err := GetUserItem(mb.DB(), "tester", "id", ":beer:") c.teaMatchCmd(makeMessage(":beer:. Earl Grey. Hot.", teaRegex)) - item, err = GetUserItem(mb.DB(), "tester", ":beer:") + item, err = GetUserItem(mb.DB(), "tester", "id", ":beer:") assert.Nil(t, err) assert.Equal(t, 0, item.Count) } @@ -89,7 +89,7 @@ func TestTeaEarlGreyHot(t *testing.T) { assert.NotNil(t, c) c.teaMatchCmd(makeMessage("Tea. Earl Grey. Hot.", teaRegex)) c.teaMatchCmd(makeMessage("Tea. Earl Grey. Hot.", teaRegex)) - item, err := GetUserItem(mb.DB(), "tester", ":tea:") + item, err := GetUserItem(mb.DB(), "tester", "id", ":tea:") assert.Nil(t, err) assert.Equal(t, 2, item.Count) } @@ -99,7 +99,7 @@ func TestTeaTwoPeriods(t *testing.T) { assert.NotNil(t, c) c.teaMatchCmd(makeMessage("Tea. Earl Grey.", teaRegex)) c.teaMatchCmd(makeMessage("Tea. Earl Grey.", teaRegex)) - item, err := GetUserItem(mb.DB(), "tester", ":tea:") + item, err := GetUserItem(mb.DB(), "tester", "id", ":tea:") assert.Nil(t, err) assert.Equal(t, 0, item.Count) } @@ -109,7 +109,7 @@ func TestTeaMultiplePeriods(t *testing.T) { assert.NotNil(t, c) c.teaMatchCmd(makeMessage("Tea. Earl Grey. Spiked. Hot.", teaRegex)) c.teaMatchCmd(makeMessage("Tea. Earl Grey. Spiked. Hot.", teaRegex)) - item, err := GetUserItem(mb.DB(), "tester", ":tea:") + item, err := GetUserItem(mb.DB(), "tester", "id", ":tea:") assert.Nil(t, err) assert.Equal(t, 2, item.Count) } @@ -120,7 +120,7 @@ func TestTeaGreenHot(t *testing.T) { c.teaMatchCmd(makeMessage("Tea. Green. Hot.", teaRegex)) c.teaMatchCmd(makeMessage("Tea. Green. Hot", teaRegex)) c.teaMatchCmd(makeMessage("Tea. Green. Iced.", teaRegex)) - item, err := GetUserItem(mb.DB(), "tester", ":tea:") + item, err := GetUserItem(mb.DB(), "tester", "id", ":tea:") assert.Nil(t, err) assert.Equal(t, 3, item.Count) } @@ -130,7 +130,7 @@ func TestTeaUnrelated(t *testing.T) { assert.NotNil(t, c) c.teaMatchCmd(makeMessage("Tea.", teaRegex)) c.teaMatchCmd(makeMessage("Tea. It's great.", teaRegex)) - item, err := GetUserItem(mb.DB(), "tester", ":tea:") + item, err := GetUserItem(mb.DB(), "tester", "id", ":tea:") assert.Nil(t, err) assert.Equal(t, 0, item.Count) } @@ -139,7 +139,7 @@ func TestTeaSkieselQuote(t *testing.T) { mb, c := setup(t) assert.NotNil(t, c) c.teaMatchCmd(makeMessage("blah, this is a whole page of explanation where \"we did local search and used a tabu list\" would have sufficed", teaRegex)) - item, err := GetUserItem(mb.DB(), "tester", ":tea:") + item, err := GetUserItem(mb.DB(), "tester", "id", ":tea:") assert.Nil(t, err) assert.Equal(t, 0, item.Count) } @@ -147,7 +147,7 @@ func TestTeaUnicodeJapanese(t *testing.T) { mb, c := setup(t) assert.NotNil(t, c) c.teaMatchCmd(makeMessage("Tea. ใŠใกใ‚„. Hot.", teaRegex)) - item, err := GetUserItem(mb.DB(), "tester", ":tea:") + item, err := GetUserItem(mb.DB(), "tester", "id", ":tea:") assert.Nil(t, err) assert.Equal(t, 1, item.Count) } @@ -157,7 +157,7 @@ func TestResetMe(t *testing.T) { assert.NotNil(t, c) c.incrementCmd(makeMessage("test++", incrementRegex)) c.resetCmd(makeMessage("!reset me", resetRegex)) - items, err := GetItems(mb.DB(), "tester") + items, err := GetItems(mb.DB(), "tester", "id") assert.Nil(t, err) assert.Len(t, items, 0) } @@ -251,8 +251,9 @@ func TestCount(t *testing.T) { } res := c.countCmd(makeMessage("!count test", countRegex)) assert.True(t, res) - assert.Len(t, mb.Messages, 5) - assert.Equal(t, mb.Messages[4], "tester has 4 test.") + if assert.Len(t, mb.Messages, 5) { + assert.Equal(t, "tester has 4 test.", mb.Messages[4]) + } } func TestInspectMe(t *testing.T) { diff --git a/plugins/goals/goals.go b/plugins/goals/goals.go index 4506d42..dfdec80 100644 --- a/plugins/goals/goals.go +++ b/plugins/goals/goals.go @@ -188,7 +188,14 @@ func (p *GoalsPlugin) checkGoal(c bot.Connector, ch, what, who string) { p.b.Send(c, bot.Message, ch, fmt.Sprintf("I couldn't find %s", what)) } - item, err := counter.GetUserItem(p.db, who, what) + nick, id := "", "" + user, err := c.Profile(who) + if err == nil && user.ID != "" { + id = user.ID + nick = user.Name + } + + item, err := counter.GetUserItem(p.db, nick, id, what) if err != nil { p.b.Send(c, bot.Message, ch, fmt.Sprintf("I couldn't find any %s", what)) return