Compare commits

..

No commits in common. "00dae33e8a5bc35002b14004475d49f96991a459" and "9b5d39fdc7995c25adc13dcadce5b1c95d0f1a2d" have entirely different histories.

5 changed files with 405 additions and 444 deletions

View File

@ -41,7 +41,7 @@ RET:
return true return true
} }
func ParseValues(r *regexp.Regexp, body string) RegexValues { func parseValues(r *regexp.Regexp, body string) RegexValues {
out := RegexValues{} out := RegexValues{}
subs := r.FindStringSubmatch(body) subs := r.FindStringSubmatch(body)
if len(subs) == 0 { if len(subs) == 0 {
@ -62,7 +62,7 @@ func (b *bot) runCallback(conn Connector, plugin Plugin, evt Kind, message msg.M
Conn: conn, Conn: conn,
Kind: evt, Kind: evt,
Msg: message, Msg: message,
Values: ParseValues(r, message.Body), Values: parseValues(r, message.Body),
Args: args, Args: args,
} }
if cb(resp) { if cb(resp) {

View File

@ -31,11 +31,7 @@ func New(b bot.Bot) *AchievementsPlugin {
if err != nil { if err != nil {
log.Fatal().Err(err).Msg("unable to create achievements tables") log.Fatal().Err(err).Msg("unable to create achievements tables")
} }
b.Register(ap, bot.Message, ap.message)
b.RegisterRegexCmd(ap, bot.Message, grantRegex, ap.grantCmd)
b.RegisterRegexCmd(ap, bot.Message, createRegex, ap.createCmd)
b.RegisterRegexCmd(ap, bot.Message, greatRegex, ap.greatCmd)
b.Register(ap, bot.Help, ap.help) b.Register(ap, bot.Help, ap.help)
return ap return ap
} }
@ -84,55 +80,12 @@ var grantRegex = regexp.MustCompile(`(?i)grant (?P<emojy>(?::[[:word:][:punct:]]
var createRegex = regexp.MustCompile(`(?i)create trophy (?P<emojy>(?::[[:word:][:punct:]]+:\s?)+) (?P<description>.+)`) var createRegex = regexp.MustCompile(`(?i)create trophy (?P<emojy>(?::[[:word:][:punct:]]+:\s?)+) (?P<description>.+)`)
var greatRegex = regexp.MustCompile(`(?i)how great (?:am i|is :?(?P<who>[[:word:]]+))[[:punct:]]*`) var greatRegex = regexp.MustCompile(`(?i)how great (?:am i|is :?(?P<who>[[:word:]]+))[[:punct:]]*`)
func (p *AchievementsPlugin) grantCmd(r bot.Request) bool { func (p *AchievementsPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
nick := r.Msg.User.Name nick := message.User.Name
emojy := r.Values["emojy"]
receiver := r.Values["nick"]
trophy, err := p.FindTrophy(emojy)
if err != nil {
log.Error().Err(err).Msg("could not find trophy")
msg := fmt.Sprintf("The %s award doesn't exist.", emojy)
p.bot.Send(r.Conn, bot.Message, r.Msg.Channel, msg)
return true
}
if nick == trophy.Creator {
a, err := p.Grant(receiver, emojy)
if err != nil {
log.Error().Err(err).Msg("could not award trophy")
}
msg := fmt.Sprintf("Congrats %s. You just got the %s award for %s.",
receiver, emojy, a.Description)
p.bot.Send(r.Conn, bot.Message, r.Msg.Channel, msg)
} else {
msg := fmt.Sprintf("Sorry, %s. %s owns that trophy.", nick, trophy.Creator)
p.bot.Send(r.Conn, bot.Message, r.Msg.Channel, msg)
}
return true
}
func (p *AchievementsPlugin) createCmd(r bot.Request) bool { if greatRegex.MatchString(message.Body) {
nick := r.Msg.User.Name submatches := greatRegex.FindAllStringSubmatch(message.Body, -1)
emojy := r.Values["emojy"] who := submatches[0][1]
description := r.Values["description"]
t, err := p.Create(emojy, description, nick)
if err != nil {
log.Error().Err(err).Msg("could not create trophy")
if strings.Contains(err.Error(), "exists") {
p.bot.Send(r.Conn, bot.Message, r.Msg.Channel, err.Error())
return true
}
p.bot.Send(r.Conn, bot.Message, r.Msg.Channel, "I'm too humble to ever award that trophy")
return true
}
resp := fmt.Sprintf("Okay %s. I have crafted a one-of-a-kind %s trophy to give for %s",
nick, t.Emojy, t.Description)
p.bot.Send(r.Conn, bot.Message, r.Msg.Channel, resp)
return true
}
func (p *AchievementsPlugin) greatCmd(r bot.Request) bool {
nick := r.Msg.User.Name
who := r.Values["who"]
if who == "" { if who == "" {
who = nick who = nick
} }
@ -143,16 +96,62 @@ func (p *AchievementsPlugin) greatCmd(r bot.Request) bool {
m = fmt.Sprintf("You have no achievements to your name. "+ m = fmt.Sprintf("You have no achievements to your name. "+
"You are a sad and terrible specimen of the human condition, %s.", who) "You are a sad and terrible specimen of the human condition, %s.", who)
} }
p.bot.Send(r.Conn, bot.Message, r.Msg.Channel, m) p.bot.Send(c, bot.Message, message.Channel, m)
} else { } else {
m := fmt.Sprintf("Wow, let's all clap for %s. Look at these awards:", who) m := fmt.Sprintf("Wow, let's all clap for %s. Look at these awards:", who)
for _, a := range awards { for _, a := range awards {
m += fmt.Sprintf("\n%s - %s", a.Emojy, a.Description) m += fmt.Sprintf("\n%s - %s", a.Emojy, a.Description)
} }
p.bot.Send(r.Conn, bot.Message, r.Msg.Channel, m) p.bot.Send(c, bot.Message, message.Channel, m)
} }
return true return true
} }
if message.Command && grantRegex.MatchString(message.Body) {
submatches := grantRegex.FindAllStringSubmatch(message.Body, -1)
emojy := submatches[0][1]
receiver := submatches[0][2]
trophy, err := p.FindTrophy(emojy)
if err != nil {
log.Error().Err(err).Msg("could not find trophy")
msg := fmt.Sprintf("The %s award doesn't exist.", emojy)
p.bot.Send(c, bot.Message, message.Channel, msg)
return true
}
if nick == trophy.Creator {
a, err := p.Grant(receiver, emojy)
if err != nil {
log.Error().Err(err).Msg("could not award trophy")
}
msg := fmt.Sprintf("Congrats %s. You just got the %s award for %s.",
receiver, emojy, a.Description)
p.bot.Send(c, bot.Message, message.Channel, msg)
} else {
msg := fmt.Sprintf("Sorry, %s. %s owns that trophy.", nick, trophy.Creator)
p.bot.Send(c, bot.Message, message.Channel, msg)
}
return true
}
if message.Command && createRegex.MatchString(message.Body) {
submatches := createRegex.FindAllStringSubmatch(message.Body, -1)
emojy := submatches[0][1]
description := submatches[0][2]
t, err := p.Create(emojy, description, nick)
if err != nil {
log.Error().Err(err).Msg("could not create trophy")
if strings.Contains(err.Error(), "exists") {
p.bot.Send(c, bot.Message, message.Channel, err.Error())
return true
}
p.bot.Send(c, bot.Message, message.Channel, "I'm too humble to ever award that trophy")
return true
}
resp := fmt.Sprintf("Okay %s. I have crafted a one-of-a-kind %s trophy to give for %s",
nick, t.Emojy, t.Description)
p.bot.Send(c, bot.Message, message.Channel, resp)
return true
}
return false
}
func (p *AchievementsPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool { func (p *AchievementsPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
ch := message.Channel ch := message.Channel

View File

@ -0,0 +1 @@
package achievements

View File

@ -20,6 +20,8 @@ import (
// This is a counter plugin to count arbitrary things. // This is a counter plugin to count arbitrary things.
var teaMatcher = regexp.MustCompile("(?i)^([^.]+)\\. [^.]*\\. ([^.]*\\.?)+$")
type CounterPlugin struct { type CounterPlugin struct {
Bot bot.Bot Bot bot.Bot
DB *sqlx.DB DB *sqlx.DB
@ -260,20 +262,7 @@ func New(b bot.Bot) *CounterPlugin {
Bot: b, Bot: b,
DB: b.DB(), DB: b.DB(),
} }
b.Register(cp, bot.Message, cp.message)
b.RegisterRegexCmd(cp, bot.Message, mkAliasRegex, cp.mkAliasCmd)
b.RegisterRegexCmd(cp, bot.Message, rmAliasRegex, cp.rmAliasCmd)
b.RegisterRegexCmd(cp, bot.Message, leaderboardRegex, cp.leaderboardCmd)
b.RegisterRegex(cp, bot.Message, teaRegex, cp.teaMatchCmd)
b.RegisterRegexCmd(cp, bot.Message, resetRegex, cp.resetCmd)
b.RegisterRegexCmd(cp, bot.Message, inspectRegex, cp.inspectCmd)
b.RegisterRegexCmd(cp, bot.Message, clearRegex, cp.clearCmd)
b.RegisterRegexCmd(cp, bot.Message, countRegex, cp.countCmd)
b.RegisterRegex(cp, bot.Message, incrementRegex, cp.incrementCmd)
b.RegisterRegex(cp, bot.Message, decrementRegex, cp.decrementCmd)
b.RegisterRegex(cp, bot.Message, addToRegex, cp.addToCmd)
b.RegisterRegex(cp, bot.Message, removeFromRegex, cp.removeFromCmd)
b.Register(cp, bot.Help, cp.help) b.Register(cp, bot.Help, cp.help)
cp.registerWeb() cp.registerWeb()
@ -284,61 +273,46 @@ func trimUnicode(s string) string {
return strings.Trim(s, string(rune(0xFE0F))) return strings.Trim(s, string(rune(0xFE0F)))
} }
var mkAliasRegex = regexp.MustCompile(`(?i)^mkalias (?P<what>\S+) (?P<to>\S+)$`) // Message responds to the bot hook on recieving messages.
var rmAliasRegex = regexp.MustCompile(`(?i)^rmalias (?P<what>\S+)$`) // This function returns true if the plugin responds in a meaningful way to the
var leaderboardRegex = regexp.MustCompile(`(?i)^leaderboard\s?(?P<what>\S+)?$`) // users message. Otherwise, the function returns false and the bot continues
var teaRegex = regexp.MustCompile("(?i)^([^.]+)\\. [^.]*\\. ([^.]*\\.?)+$") // execution of other plugins.
var resetRegex = regexp.MustCompile(`(?i)^reset me$`) func (p *CounterPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
var inspectRegex = regexp.MustCompile(`(?i)^inspect (?P<who>\S+)$`) // This bot does not reply to anything
var clearRegex = regexp.MustCompile(`(?i)^clear (?P<what>\S+)$`) nick := message.User.Name
var countRegex = regexp.MustCompile(`(?i)^count (?P<who>\S+)\s?(?P<what>\S+)?$`) channel := message.Channel
var incrementRegex = regexp.MustCompile(`(?i)^(?P<who>[^.\t\n\f\r ]+\s?\.)?(?P<thing>\S+)\s?\+\+$`) parts := strings.Fields(message.Body)
var decrementRegex = regexp.MustCompile(`(?i)^(?P<who>[^.\t\n\f\r ]+\s?\.)?(?P<thing>\S+)\s?--$`)
var addToRegex = regexp.MustCompile(`(?i)^(?P<who>[^.\t\n\f\r ]+\s?\.)?(?P<thing>\S+)\s+\+=\s+(?P<amount>\d+)$`)
var removeFromRegex = regexp.MustCompile(`(?i)^(?P<who>[^.\t\n\f\r ]+\s?\.)?(?P<thing>\S+)\s+-=\s+(?P<amount>\d+)$`)
func (p *CounterPlugin) mkAliasCmd(r bot.Request) bool { if len(parts) == 0 {
what := r.Values["what"] return false
to := r.Values["to"]
if what == "" || to == "" {
p.Bot.Send(r.Conn, bot.Message, fmt.Sprintf("You must provide all fields for an alias: %s", mkAliasRegex))
return true
} }
if _, err := MkAlias(p.DB, what, to); err != nil {
if len(parts) == 3 && strings.ToLower(parts[0]) == "mkalias" {
if _, err := MkAlias(p.DB, parts[1], parts[2]); err != nil {
log.Error().Err(err).Msg("Could not mkalias") log.Error().Err(err).Msg("Could not mkalias")
p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, "We're gonna need too much DB space to make an alias for your mom.") p.Bot.Send(c, bot.Message, channel, "We're gonna need too much DB space to make an alias for your mom.")
return true return true
} }
p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("Created alias %s -> %s", p.Bot.Send(c, bot.Message, channel, fmt.Sprintf("Created alias %s -> %s",
what, to)) parts[1], parts[2]))
return true return true
} } else if len(parts) == 2 && strings.ToLower(parts[0]) == "rmalias" {
if err := RmAlias(p.DB, parts[1]); err != nil {
func (p *CounterPlugin) rmAliasCmd(r bot.Request) bool {
what := r.Values["what"]
if what == "" {
p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, "You must specify an alias to remove.")
return true
}
if err := RmAlias(p.DB, what); err != nil {
log.Error().Err(err).Msg("could not RmAlias") log.Error().Err(err).Msg("could not RmAlias")
p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, "`sudo rm your mom` => Nope, she's staying with me.") p.Bot.Send(c, bot.Message, channel, "`sudo rm your mom` => Nope, she's staying with me.")
return true return true
} }
p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, "`sudo rm your mom`") p.Bot.Send(c, bot.Message, channel, "`sudo rm your mom`")
return true return true
} } else if strings.ToLower(parts[0]) == "leaderboard" {
func (p *CounterPlugin) leaderboardCmd(r bot.Request) bool {
var cmd func() ([]Item, error) var cmd func() ([]Item, error)
itNameTxt := "" itNameTxt := ""
what := r.Values["what"]
if what == "" { if len(parts) == 1 {
cmd = func() ([]Item, error) { return LeaderAll(p.DB) } cmd = func() ([]Item, error) { return LeaderAll(p.DB) }
} else { } else {
itNameTxt = fmt.Sprintf(" for %s", what) itNameTxt = fmt.Sprintf(" for %s", parts[1])
cmd = func() ([]Item, error) { return Leader(p.DB, what) } cmd = func() ([]Item, error) { return Leader(p.DB, parts[1]) }
} }
its, err := cmd() its, err := cmd()
@ -346,8 +320,7 @@ func (p *CounterPlugin) leaderboardCmd(r bot.Request) bool {
log.Error().Err(err).Msg("Error with leaderboard") log.Error().Err(err).Msg("Error with leaderboard")
return false return false
} else if len(its) == 0 { } else if len(its) == 0 {
p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, "There are not enough entries for a leaderboard.") return false
return true
} }
out := fmt.Sprintf("Leaderboard%s:\n", itNameTxt) out := fmt.Sprintf("Leaderboard%s:\n", itNameTxt)
@ -358,41 +331,34 @@ func (p *CounterPlugin) leaderboardCmd(r bot.Request) bool {
it.Item, it.Item,
) )
} }
p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, out) p.Bot.Send(c, bot.Message, channel, out)
return true return true
} } else if match := teaMatcher.MatchString(message.Body); match {
// check for tea match TTT
func (p *CounterPlugin) resetCmd(r bot.Request) bool { return p.checkMatch(c, message)
nick := r.Msg.User.Name } else if message.Command && message.Body == "reset me" {
channel := r.Msg.Channel
items, err := GetItems(p.DB, strings.ToLower(nick)) items, err := GetItems(p.DB, strings.ToLower(nick))
if err != nil { if err != nil {
log.Error(). log.Error().
Err(err). Err(err).
Str("nick", nick). Str("nick", nick).
Msg("Error getting items to reset") Msg("Error getting items to reset")
p.Bot.Send(r.Conn, bot.Message, channel, "Something is technically wrong with your counters.") p.Bot.Send(c, bot.Message, channel, "Something is technically wrong with your counters.")
return true return true
} }
log.Debug().Msgf("Items: %+v", items) log.Debug().Msgf("Items: %+v", items)
for _, item := range items { for _, item := range items {
item.Delete() item.Delete()
} }
p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s, you are as new, my son.", nick)) p.Bot.Send(c, bot.Message, channel, fmt.Sprintf("%s, you are as new, my son.", nick))
return true return true
} } else if message.Command && parts[0] == "inspect" && len(parts) == 2 {
func (p *CounterPlugin) inspectCmd(r bot.Request) bool {
var subject string var subject string
subject = r.Values["who"]
channel := r.Msg.Channel
c := r.Conn
if subject == "me" { if parts[1] == "me" {
subject = strings.ToLower(r.Msg.User.Name) subject = strings.ToLower(nick)
} else { } else {
subject = strings.ToLower(subject) subject = strings.ToLower(parts[1])
} }
log.Debug(). log.Debug().
@ -431,13 +397,9 @@ func (p *CounterPlugin) inspectCmd(r bot.Request) bool {
p.Bot.Send(c, bot.Message, channel, resp) p.Bot.Send(c, bot.Message, channel, resp)
return true return true
} } else if message.Command && len(parts) == 2 && parts[0] == "clear" {
subject := strings.ToLower(nick)
func (p *CounterPlugin) clearCmd(r bot.Request) bool { itemName := strings.ToLower(parts[1])
subject := strings.ToLower(r.Msg.User.Name)
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, subject, itemName)
if err != nil { if err != nil {
@ -463,27 +425,27 @@ func (p *CounterPlugin) clearCmd(r bot.Request) bool {
p.Bot.Send(c, bot.Action, channel, fmt.Sprintf("chops a few %s out of his brain", p.Bot.Send(c, bot.Action, channel, fmt.Sprintf("chops a few %s out of his brain",
itemName)) itemName))
return true return true
}
func (p *CounterPlugin) countCmd(r bot.Request) bool { } else if message.Command && parts[0] == "count" {
var subject string var subject string
var itemName string var itemName string
if r.Values["what"] == "" && r.Values["who"] == "" { if len(parts) == 3 {
return false // report count for parts[1]
} else if r.Values["what"] != "" { subject = strings.ToLower(parts[1])
subject = strings.ToLower(r.Values["who"]) itemName = strings.ToLower(parts[2])
itemName = strings.ToLower(r.Values["what"]) } else if len(parts) == 2 {
subject = strings.ToLower(nick)
itemName = strings.ToLower(parts[1])
} else { } else {
subject = strings.ToLower(r.Msg.User.Name) return false
itemName = strings.ToLower(r.Values["who"])
} }
var item Item var item Item
item, err := GetUserItem(p.DB, subject, itemName) item, err := GetUserItem(p.DB, subject, itemName)
switch { switch {
case err == sql.ErrNoRows: case err == sql.ErrNoRows:
p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("I don't think %s has any %s.", p.Bot.Send(c, bot.Message, channel, fmt.Sprintf("I don't think %s has any %s.",
subject, itemName)) subject, itemName))
return true return true
case err != nil: case err != nil:
@ -495,19 +457,28 @@ func (p *CounterPlugin) countCmd(r bot.Request) bool {
return true return true
} }
p.Bot.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("%s has %d %s.", subject, item.Count, p.Bot.Send(c, bot.Message, channel, fmt.Sprintf("%s has %d %s.", subject, item.Count,
itemName)) itemName))
return true return true
} else if len(parts) <= 2 {
if (len(parts) == 2) && (parts[1] == "++" || parts[1] == "--") {
parts = []string{parts[0] + parts[1]}
}
// Need to have at least 3 characters to ++ or --
if len(parts[0]) < 3 {
return false
} }
func (p *CounterPlugin) incrementCmd(r bot.Request) bool { subject := strings.ToLower(nick)
subject := r.Msg.User.Name itemName := strings.ToLower(parts[0])[:len(parts[0])-2]
if r.Values["who"] != "" {
subject = strings.TrimSuffix(r.Values["who"], ".") if nameParts := strings.SplitN(itemName, ".", 2); len(nameParts) == 2 {
subject = nameParts[0]
itemName = nameParts[1]
} }
itemName := r.Values["thing"]
channel := r.Msg.Channel if strings.HasSuffix(parts[0], "++") {
// ++ those fuckers // ++ those fuckers
item, err := GetUserItem(p.DB, subject, itemName) item, err := GetUserItem(p.DB, subject, itemName)
if err != nil { if err != nil {
@ -521,18 +492,10 @@ func (p *CounterPlugin) incrementCmd(r bot.Request) bool {
} }
log.Debug().Msgf("About to update item: %#v", item) log.Debug().Msgf("About to update item: %#v", item)
item.UpdateDelta(1) item.UpdateDelta(1)
p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", subject, p.Bot.Send(c, bot.Message, channel, fmt.Sprintf("%s has %d %s.", subject,
item.Count, item.Item)) item.Count, item.Item))
return true return true
} } else if strings.HasSuffix(parts[0], "--") {
func (p *CounterPlugin) decrementCmd(r bot.Request) bool {
subject := r.Msg.User.Name
if r.Values["who"] != "" {
subject = strings.TrimSuffix(r.Values["who"], ".")
}
itemName := r.Values["thing"]
channel := r.Msg.Channel
// -- those fuckers // -- those fuckers
item, err := GetUserItem(p.DB, subject, itemName) item, err := GetUserItem(p.DB, subject, itemName)
if err != nil { if err != nil {
@ -545,18 +508,25 @@ func (p *CounterPlugin) decrementCmd(r bot.Request) bool {
return false return false
} }
item.UpdateDelta(-1) item.UpdateDelta(-1)
p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", subject, p.Bot.Send(c, bot.Message, channel, fmt.Sprintf("%s has %d %s.", subject,
item.Count, item.Item)) item.Count, item.Item))
return true return true
} }
} else if len(parts) == 3 {
func (p *CounterPlugin) addToCmd(r bot.Request) bool { // Need to have at least 3 characters to ++ or --
subject := r.Msg.User.Name if len(parts[0]) < 3 {
if r.Values["who"] != "" { return false
subject = strings.TrimSuffix(r.Values["who"], ".")
} }
itemName := r.Values["thing"]
channel := r.Msg.Channel subject := strings.ToLower(nick)
itemName := strings.ToLower(parts[0])
if nameParts := strings.SplitN(itemName, ".", 2); len(nameParts) == 2 {
subject = nameParts[0]
itemName = nameParts[1]
}
if parts[1] == "+=" {
// += those fuckers // += those fuckers
item, err := GetUserItem(p.DB, subject, itemName) item, err := GetUserItem(p.DB, subject, itemName)
if err != nil { if err != nil {
@ -568,21 +538,13 @@ func (p *CounterPlugin) addToCmd(r bot.Request) bool {
// Item ain't there, I guess // Item ain't there, I guess
return false return false
} }
n, _ := strconv.Atoi(r.Values["amount"]) n, _ := strconv.Atoi(parts[2])
log.Debug().Msgf("About to update item by %d: %#v", n, item) log.Debug().Msgf("About to update item by %d: %#v", n, item)
item.UpdateDelta(n) item.UpdateDelta(n)
p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", subject, p.Bot.Send(c, bot.Message, channel, fmt.Sprintf("%s has %d %s.", subject,
item.Count, item.Item)) item.Count, item.Item))
return true return true
} } else if parts[1] == "-=" {
func (p *CounterPlugin) removeFromCmd(r bot.Request) bool {
subject := r.Msg.User.Name
if r.Values["who"] != "" {
subject = strings.TrimSuffix(r.Values["who"], ".")
}
itemName := r.Values["thing"]
channel := r.Msg.Channel
// -= those fuckers // -= those fuckers
item, err := GetUserItem(p.DB, subject, itemName) item, err := GetUserItem(p.DB, subject, itemName)
if err != nil { if err != nil {
@ -594,13 +556,17 @@ func (p *CounterPlugin) removeFromCmd(r bot.Request) bool {
// Item ain't there, I guess // Item ain't there, I guess
return false return false
} }
n, _ := strconv.Atoi(r.Values["amount"]) n, _ := strconv.Atoi(parts[2])
log.Debug().Msgf("About to update item by -%d: %#v", n, item) log.Debug().Msgf("About to update item by -%d: %#v", n, item)
item.UpdateDelta(-n) item.UpdateDelta(-n)
p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s has %d %s.", subject, p.Bot.Send(c, bot.Message, channel, fmt.Sprintf("%s has %d %s.", subject,
item.Count, item.Item)) item.Count, item.Item))
return true return true
} }
}
return false
}
// 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 *CounterPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool { func (p *CounterPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
@ -613,11 +579,11 @@ func (p *CounterPlugin) help(c bot.Connector, kind bot.Kind, message msg.Message
return true return true
} }
func (p *CounterPlugin) teaMatchCmd(r bot.Request) bool { func (p *CounterPlugin) checkMatch(c bot.Connector, message msg.Message) bool {
nick := r.Msg.User.Name nick := message.User.Name
channel := r.Msg.Channel channel := message.Channel
submatches := teaRegex.FindStringSubmatch(r.Msg.Body) submatches := teaMatcher.FindStringSubmatch(message.Body)
if len(submatches) <= 1 { if len(submatches) <= 1 {
return false return false
} }
@ -639,7 +605,7 @@ func (p *CounterPlugin) teaMatchCmd(r bot.Request) bool {
delta = -1 delta = -1
} }
item.UpdateDelta(delta) item.UpdateDelta(delta)
p.Bot.Send(r.Conn, bot.Message, channel, fmt.Sprintf("%s... %s has %d %s", p.Bot.Send(c, bot.Message, channel, fmt.Sprintf("%s... %s has %d %s",
strings.Join(everyDayImShuffling([]string{"bleep", "bloop", "blop"}), "-"), nick, item.Count, itemName)) strings.Join(everyDayImShuffling([]string{"bleep", "bloop", "blop"}), "-"), nick, item.Count, itemName))
return true return true
} }

View File

@ -4,7 +4,6 @@ package counter
import ( import (
"fmt" "fmt"
"regexp"
"strings" "strings"
"testing" "testing"
@ -26,28 +25,24 @@ func setup(t *testing.T) (*bot.MockBot, *CounterPlugin) {
return mb, c return mb, c
} }
func makeMessage(payload string, r *regexp.Regexp) bot.Request { func makeMessage(payload string) (bot.Connector, bot.Kind, msg.Message) {
isCmd := strings.HasPrefix(payload, "!") isCmd := strings.HasPrefix(payload, "!")
if isCmd { if isCmd {
payload = payload[1:] payload = payload[1:]
} }
values := bot.ParseValues(r, payload) return &cli.CliPlugin{}, bot.Message, msg.Message{
return bot.Request{
Conn: nil,
Msg: msg.Message{
User: &user.User{Name: "tester"}, User: &user.User{Name: "tester"},
Channel: "test",
Body: payload, Body: payload,
Command: isCmd, Command: isCmd,
},
Values: values,
} }
} }
func TestMkAlias(t *testing.T) { func TestMkAlias(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
c.mkAliasCmd(makeMessage("mkalias fuck mornings", mkAliasRegex)) c.message(makeMessage("mkalias fuck mornings"))
c.incrementCmd(makeMessage("fuck++", incrementRegex)) c.message(makeMessage("fuck++"))
item, err := GetUserItem(mb.DB(), "tester", "mornings") item, err := GetUserItem(mb.DB(), "tester", "mornings")
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 1, item.Count) assert.Equal(t, 1, item.Count)
@ -56,9 +51,9 @@ func TestMkAlias(t *testing.T) {
func TestRmAlias(t *testing.T) { func TestRmAlias(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
c.mkAliasCmd(makeMessage("mkalias fuck mornings", mkAliasRegex)) c.message(makeMessage("mkalias fuck mornings"))
c.rmAliasCmd(makeMessage("rmalias fuck", rmAliasRegex)) c.message(makeMessage("rmalias fuck"))
c.incrementCmd(makeMessage("fuck++", incrementRegex)) c.message(makeMessage("fuck++"))
item, err := GetUserItem(mb.DB(), "tester", "mornings") item, err := GetUserItem(mb.DB(), "tester", "mornings")
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 0, item.Count) assert.Equal(t, 0, item.Count)
@ -67,8 +62,8 @@ func TestRmAlias(t *testing.T) {
func TestThreeSentencesExists(t *testing.T) { func TestThreeSentencesExists(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
c.incrementCmd(makeMessage(":beer:++", incrementRegex)) c.message(makeMessage(":beer:++"))
c.teaMatchCmd(makeMessage(":beer:. Earl Grey. Hot.", teaRegex)) c.message(makeMessage(":beer:. Earl Grey. Hot."))
item, err := GetUserItem(mb.DB(), "tester", ":beer:") item, err := GetUserItem(mb.DB(), "tester", ":beer:")
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 2, item.Count) assert.Equal(t, 2, item.Count)
@ -78,7 +73,7 @@ func TestThreeSentencesNotExists(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
item, err := GetUserItem(mb.DB(), "tester", ":beer:") item, err := GetUserItem(mb.DB(), "tester", ":beer:")
c.teaMatchCmd(makeMessage(":beer:. Earl Grey. Hot.", teaRegex)) c.message(makeMessage(":beer:. Earl Grey. Hot."))
item, err = GetUserItem(mb.DB(), "tester", ":beer:") item, err = GetUserItem(mb.DB(), "tester", ":beer:")
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 0, item.Count) assert.Equal(t, 0, item.Count)
@ -87,8 +82,8 @@ func TestThreeSentencesNotExists(t *testing.T) {
func TestTeaEarlGreyHot(t *testing.T) { func TestTeaEarlGreyHot(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
c.teaMatchCmd(makeMessage("Tea. Earl Grey. Hot.", teaRegex)) c.message(makeMessage("Tea. Earl Grey. Hot."))
c.teaMatchCmd(makeMessage("Tea. Earl Grey. Hot.", teaRegex)) c.message(makeMessage("Tea. Earl Grey. Hot."))
item, err := GetUserItem(mb.DB(), "tester", ":tea:") item, err := GetUserItem(mb.DB(), "tester", ":tea:")
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 2, item.Count) assert.Equal(t, 2, item.Count)
@ -97,8 +92,8 @@ func TestTeaEarlGreyHot(t *testing.T) {
func TestTeaTwoPeriods(t *testing.T) { func TestTeaTwoPeriods(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
c.teaMatchCmd(makeMessage("Tea. Earl Grey.", teaRegex)) c.message(makeMessage("Tea. Earl Grey."))
c.teaMatchCmd(makeMessage("Tea. Earl Grey.", teaRegex)) c.message(makeMessage("Tea. Earl Grey."))
item, err := GetUserItem(mb.DB(), "tester", ":tea:") item, err := GetUserItem(mb.DB(), "tester", ":tea:")
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 0, item.Count) assert.Equal(t, 0, item.Count)
@ -107,8 +102,8 @@ func TestTeaTwoPeriods(t *testing.T) {
func TestTeaMultiplePeriods(t *testing.T) { func TestTeaMultiplePeriods(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
c.teaMatchCmd(makeMessage("Tea. Earl Grey. Spiked. Hot.", teaRegex)) c.message(makeMessage("Tea. Earl Grey. Spiked. Hot."))
c.teaMatchCmd(makeMessage("Tea. Earl Grey. Spiked. Hot.", teaRegex)) c.message(makeMessage("Tea. Earl Grey. Spiked. Hot."))
item, err := GetUserItem(mb.DB(), "tester", ":tea:") item, err := GetUserItem(mb.DB(), "tester", ":tea:")
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 2, item.Count) assert.Equal(t, 2, item.Count)
@ -117,9 +112,9 @@ func TestTeaMultiplePeriods(t *testing.T) {
func TestTeaGreenHot(t *testing.T) { func TestTeaGreenHot(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
c.teaMatchCmd(makeMessage("Tea. Green. Hot.", teaRegex)) c.message(makeMessage("Tea. Green. Hot."))
c.teaMatchCmd(makeMessage("Tea. Green. Hot", teaRegex)) c.message(makeMessage("Tea. Green. Hot"))
c.teaMatchCmd(makeMessage("Tea. Green. Iced.", teaRegex)) c.message(makeMessage("Tea. Green. Iced."))
item, err := GetUserItem(mb.DB(), "tester", ":tea:") item, err := GetUserItem(mb.DB(), "tester", ":tea:")
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 3, item.Count) assert.Equal(t, 3, item.Count)
@ -128,8 +123,8 @@ func TestTeaGreenHot(t *testing.T) {
func TestTeaUnrelated(t *testing.T) { func TestTeaUnrelated(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
c.teaMatchCmd(makeMessage("Tea.", teaRegex)) c.message(makeMessage("Tea."))
c.teaMatchCmd(makeMessage("Tea. It's great.", teaRegex)) c.message(makeMessage("Tea. It's great."))
item, err := GetUserItem(mb.DB(), "tester", ":tea:") item, err := GetUserItem(mb.DB(), "tester", ":tea:")
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 0, item.Count) assert.Equal(t, 0, item.Count)
@ -138,7 +133,7 @@ func TestTeaUnrelated(t *testing.T) {
func TestTeaSkieselQuote(t *testing.T) { func TestTeaSkieselQuote(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) 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)) c.message(makeMessage("blah, this is a whole page of explanation where \"we did local search and used a tabu list\" would have sufficed"))
item, err := GetUserItem(mb.DB(), "tester", ":tea:") item, err := GetUserItem(mb.DB(), "tester", ":tea:")
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 0, item.Count) assert.Equal(t, 0, item.Count)
@ -146,7 +141,7 @@ func TestTeaSkieselQuote(t *testing.T) {
func TestTeaUnicodeJapanese(t *testing.T) { func TestTeaUnicodeJapanese(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
c.teaMatchCmd(makeMessage("Tea. おちや. Hot.", teaRegex)) c.message(makeMessage("Tea. おちや. Hot."))
item, err := GetUserItem(mb.DB(), "tester", ":tea:") item, err := GetUserItem(mb.DB(), "tester", ":tea:")
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 1, item.Count) assert.Equal(t, 1, item.Count)
@ -155,8 +150,8 @@ func TestTeaUnicodeJapanese(t *testing.T) {
func TestResetMe(t *testing.T) { func TestResetMe(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
c.incrementCmd(makeMessage("test++", incrementRegex)) c.message(makeMessage("test++"))
c.resetCmd(makeMessage("!reset me", resetRegex)) c.message(makeMessage("!reset me"))
items, err := GetItems(mb.DB(), "tester") items, err := GetItems(mb.DB(), "tester")
assert.Nil(t, err) assert.Nil(t, err)
assert.Len(t, items, 0) assert.Len(t, items, 0)
@ -165,7 +160,7 @@ func TestResetMe(t *testing.T) {
func TestCounterOne(t *testing.T) { func TestCounterOne(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
c.incrementCmd(makeMessage("test++", incrementRegex)) c.message(makeMessage("test++"))
assert.Len(t, mb.Messages, 1) assert.Len(t, mb.Messages, 1)
assert.Equal(t, mb.Messages[0], "tester has 1 test.") assert.Equal(t, mb.Messages[0], "tester has 1 test.")
} }
@ -173,7 +168,7 @@ func TestCounterOne(t *testing.T) {
func TestCounterOneWithSpace(t *testing.T) { func TestCounterOneWithSpace(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
c.incrementCmd(makeMessage(":test: ++", incrementRegex)) c.message(makeMessage(":test: ++"))
assert.Len(t, mb.Messages, 1) assert.Len(t, mb.Messages, 1)
assert.Equal(t, mb.Messages[0], "tester has 1 :test:.") assert.Equal(t, mb.Messages[0], "tester has 1 :test:.")
} }
@ -182,7 +177,7 @@ func TestCounterFour(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
c.incrementCmd(makeMessage("test++", incrementRegex)) c.message(makeMessage("test++"))
} }
assert.Len(t, mb.Messages, 4) assert.Len(t, mb.Messages, 4)
assert.Equal(t, mb.Messages[3], "tester has 4 test.") assert.Equal(t, mb.Messages[3], "tester has 4 test.")
@ -192,10 +187,10 @@ func TestCounterDecrement(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
c.incrementCmd(makeMessage("test++", incrementRegex)) c.message(makeMessage("test++"))
assert.Equal(t, mb.Messages[i], fmt.Sprintf("tester has %d test.", i+1)) assert.Equal(t, mb.Messages[i], fmt.Sprintf("tester has %d test.", i+1))
} }
c.decrementCmd(makeMessage("test--", decrementRegex)) c.message(makeMessage("test--"))
assert.Len(t, mb.Messages, 5) assert.Len(t, mb.Messages, 5)
assert.Equal(t, mb.Messages[4], "tester has 3 test.") assert.Equal(t, mb.Messages[4], "tester has 3 test.")
} }
@ -204,10 +199,10 @@ func TestFriendCounterDecrement(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
c.incrementCmd(makeMessage("other.test++", incrementRegex)) c.message(makeMessage("other.test++"))
assert.Equal(t, mb.Messages[i], fmt.Sprintf("other has %d test.", i+1)) assert.Equal(t, mb.Messages[i], fmt.Sprintf("other has %d test.", i+1))
} }
c.decrementCmd(makeMessage("other.test--", decrementRegex)) c.message(makeMessage("other.test--"))
assert.Len(t, mb.Messages, 5) assert.Len(t, mb.Messages, 5)
assert.Equal(t, mb.Messages[4], "other has 3 test.") assert.Equal(t, mb.Messages[4], "other has 3 test.")
} }
@ -216,12 +211,12 @@ func TestDecrementZero(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
c.incrementCmd(makeMessage("test++", incrementRegex)) c.message(makeMessage("test++"))
assert.Equal(t, mb.Messages[i], fmt.Sprintf("tester has %d test.", i+1)) assert.Equal(t, mb.Messages[i], fmt.Sprintf("tester has %d test.", i+1))
} }
j := 4 j := 4
for i := 4; i > 0; i-- { for i := 4; i > 0; i-- {
c.decrementCmd(makeMessage("test--", decrementRegex)) c.message(makeMessage("test--"))
assert.Equal(t, mb.Messages[j], fmt.Sprintf("tester has %d test.", i-1)) assert.Equal(t, mb.Messages[j], fmt.Sprintf("tester has %d test.", i-1))
j++ j++
} }
@ -233,10 +228,10 @@ func TestClear(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
c.incrementCmd(makeMessage("test++", incrementRegex)) c.message(makeMessage("test++"))
assert.Equal(t, mb.Messages[i], fmt.Sprintf("tester has %d test.", i+1)) assert.Equal(t, mb.Messages[i], fmt.Sprintf("tester has %d test.", i+1))
} }
res := c.clearCmd(makeMessage("!clear test", clearRegex)) res := c.message(makeMessage("!clear test"))
assert.True(t, res) assert.True(t, res)
assert.Len(t, mb.Actions, 1) assert.Len(t, mb.Actions, 1)
assert.Equal(t, mb.Actions[0], "chops a few test out of his brain") assert.Equal(t, mb.Actions[0], "chops a few test out of his brain")
@ -246,10 +241,10 @@ func TestCount(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
c.incrementCmd(makeMessage("test++", incrementRegex)) c.message(makeMessage("test++"))
assert.Equal(t, mb.Messages[i], fmt.Sprintf("tester has %d test.", i+1)) assert.Equal(t, mb.Messages[i], fmt.Sprintf("tester has %d test.", i+1))
} }
res := c.countCmd(makeMessage("!count test", countRegex)) res := c.message(makeMessage("!count test"))
assert.True(t, res) assert.True(t, res)
assert.Len(t, mb.Messages, 5) assert.Len(t, mb.Messages, 5)
assert.Equal(t, mb.Messages[4], "tester has 4 test.") assert.Equal(t, mb.Messages[4], "tester has 4 test.")
@ -259,18 +254,18 @@ func TestInspectMe(t *testing.T) {
mb, c := setup(t) mb, c := setup(t)
assert.NotNil(t, c) assert.NotNil(t, c)
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {
c.incrementCmd(makeMessage("test++", incrementRegex)) c.message(makeMessage("test++"))
assert.Equal(t, mb.Messages[i], fmt.Sprintf("tester has %d test.", i+1)) assert.Equal(t, mb.Messages[i], fmt.Sprintf("tester has %d test.", i+1))
} }
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
c.incrementCmd(makeMessage("fucks++", incrementRegex)) c.message(makeMessage("fucks++"))
assert.Equal(t, mb.Messages[i+4], fmt.Sprintf("tester has %d fucks.", i+1)) assert.Equal(t, mb.Messages[i+4], fmt.Sprintf("tester has %d fucks.", i+1))
} }
for i := 0; i < 20; i++ { for i := 0; i < 20; i++ {
c.incrementCmd(makeMessage("cheese++", incrementRegex)) c.message(makeMessage("cheese++"))
assert.Equal(t, mb.Messages[i+6], fmt.Sprintf("tester has %d cheese.", i+1)) assert.Equal(t, mb.Messages[i+6], fmt.Sprintf("tester has %d cheese.", i+1))
} }
res := c.inspectCmd(makeMessage("!inspect me", inspectRegex)) res := c.message(makeMessage("!inspect me"))
assert.True(t, res) assert.True(t, res)
assert.Len(t, mb.Messages, 27) assert.Len(t, mb.Messages, 27)
assert.Equal(t, mb.Messages[26], "tester has the following counters: test: 4, fucks: 2, cheese: 20.") assert.Equal(t, mb.Messages[26], "tester has the following counters: test: 4, fucks: 2, cheese: 20.")