catbase/plugins/inventory/inventory.go

193 lines
4.8 KiB
Go
Raw Normal View History

2017-09-29 04:58:21 +00:00
// © 2016 the CatBase Authors under the WTFPL license. See AUTHORS for the list of authors.
// Package inventory contains the plugin that allows the bot to pad messages
// See the bucket RFC inventory: http://wiki.xkcd.com/irc/Bucket_inventory
package inventory
import (
"fmt"
2021-12-20 17:40:10 +00:00
bh "github.com/timshannon/bolthold"
"math/rand"
2017-09-29 04:58:21 +00:00
"regexp"
"strings"
2019-03-07 16:35:42 +00:00
"github.com/rs/zerolog/log"
2017-09-29 04:58:21 +00:00
"github.com/velour/catbase/bot"
"github.com/velour/catbase/bot/msg"
"github.com/velour/catbase/config"
)
type InventoryPlugin struct {
2021-12-20 17:40:10 +00:00
*bh.Store
2021-02-05 16:19:39 +00:00
bot bot.Bot
config *config.Config
handlers bot.HandlerTable
2017-09-29 04:58:21 +00:00
}
// New creates a new InventoryPlugin with the Plugin interface
func New(b bot.Bot) *InventoryPlugin {
config := b.Config()
2017-09-29 04:58:21 +00:00
p := &InventoryPlugin{
2021-12-20 17:40:10 +00:00
Store: b.Store(),
bot: b,
2017-09-29 04:58:21 +00:00
config: config,
}
b.RegisterFilter("$item", p.itemFilter)
b.RegisterFilter("$giveitem", p.giveItemFilter)
2017-09-29 04:58:21 +00:00
2021-02-05 16:19:39 +00:00
p.register()
return p
2017-09-29 04:58:21 +00:00
}
2021-12-20 17:40:10 +00:00
type Item struct {
2021-12-22 03:36:08 +00:00
Name string `db:"item" boltholdKey:"Name"`
2021-12-20 17:40:10 +00:00
}
2017-09-29 04:58:21 +00:00
func (p *InventoryPlugin) giveItemFilter(input string) string {
for strings.Contains(input, "$giveitem") {
item := p.random()
input = strings.Replace(input, "$giveitem", item, 1)
p.remove(item)
}
return input
}
func (p *InventoryPlugin) itemFilter(input string) string {
for strings.Contains(input, "$item") {
input = strings.Replace(input, "$item", p.random(), 1)
}
return input
}
2021-02-05 16:19:39 +00:00
func (p *InventoryPlugin) register() {
nick := p.config.Get("nick", "bot")
p.handlers = append(p.handlers, bot.HandlerSpec{Kind: bot.Message, IsCmd: true,
Regex: regexp.MustCompile(`inventory`),
Handler: func(r bot.Request) bool {
2017-09-29 04:58:21 +00:00
items := p.getAll()
say := "I'm not holding anything"
if len(items) > 0 {
2019-03-07 16:35:42 +00:00
log.Debug().Msgf("I think I have more than 0 items: %+v, len(items)=%d", items, len(items))
2017-09-29 04:58:21 +00:00
say = fmt.Sprintf("I'm currently holding %s", strings.Join(items, ", "))
}
2021-02-05 16:19:39 +00:00
p.bot.Send(r.Conn, bot.Message, r.Msg.Channel, say)
2017-09-29 04:58:21 +00:00
return true
2021-02-05 16:19:39 +00:00
},
})
h := func(r bot.Request) bool {
log.Debug().Msgf("Adding item: %s", r.Values["item"])
return p.addItem(r.Conn, r.Msg, r.Values["item"])
}
for _, r := range []*regexp.Regexp{
regexp.MustCompile(`(?i)^take this (?P<item>.+)$`),
regexp.MustCompile(`(?i)^have a (?P<item>.+)$`),
} {
p.handlers = append(p.handlers, bot.HandlerSpec{Kind: bot.Message, IsCmd: false,
Regex: r,
Handler: h})
}
for _, r := range []*regexp.Regexp{
regexp.MustCompile(fmt.Sprintf(`(?i)^puts (?P<item>\S+) in %s$`, nick)),
regexp.MustCompile(fmt.Sprintf("(?i)^gives %s (?P<item>.+)$", nick)),
regexp.MustCompile(fmt.Sprintf(`(?i)^gives (?P<item>\S+) to %s$`, nick)),
} {
p.handlers = append(p.handlers, bot.HandlerSpec{Kind: bot.Action, IsCmd: false,
Regex: r,
Handler: h})
}
p.bot.RegisterTable(p, p.handlers)
2017-09-29 04:58:21 +00:00
}
func (p *InventoryPlugin) removeRandom() string {
2021-12-20 17:40:10 +00:00
items := []Item{}
err := p.Find(&items, &bh.Query{})
2017-09-29 04:58:21 +00:00
if err != nil {
2019-03-07 16:35:42 +00:00
log.Error().Err(err).Msgf("Error finding random entry")
2017-09-29 04:58:21 +00:00
return "IAMERROR"
}
2021-12-20 17:40:10 +00:00
item := items[rand.Intn(len(items))]
err = p.Delete(item.Name, Item{})
return item.Name
2017-09-29 04:58:21 +00:00
}
func (p *InventoryPlugin) count() int {
2021-12-20 17:40:10 +00:00
count, err := p.Store.Count(Item{}, &bh.Query{})
2017-09-29 04:58:21 +00:00
if err != nil {
2019-03-07 16:35:42 +00:00
log.Error().Err(err).Msg("Error checking for item")
2017-09-29 04:58:21 +00:00
return -1
}
2021-12-20 17:40:10 +00:00
return count
2017-09-29 04:58:21 +00:00
}
func (p *InventoryPlugin) random() string {
2021-12-20 17:40:10 +00:00
items := []Item{}
err := p.Find(&items, &bh.Query{})
2017-09-29 04:58:21 +00:00
if err != nil {
2021-12-20 17:40:10 +00:00
log.Error().Err(err).Msgf("Error finding random entry")
2017-09-29 04:58:21 +00:00
return "IAMERROR"
}
2021-12-20 17:40:10 +00:00
item := items[rand.Intn(len(items))]
return item.Name
2017-09-29 04:58:21 +00:00
}
func (p *InventoryPlugin) getAll() []string {
2021-12-20 17:40:10 +00:00
items := []Item{}
err := p.Find(&items, &bh.Query{})
2017-09-29 04:58:21 +00:00
if err != nil {
2019-03-07 16:35:42 +00:00
log.Error().Err(err).Msg("Error getting all items")
2017-09-29 04:58:21 +00:00
return []string{}
}
output := []string{}
2021-12-20 17:40:10 +00:00
for _, item := range items {
output = append(output, item.Name)
2017-09-29 04:58:21 +00:00
}
return output
}
func (p *InventoryPlugin) exists(i string) bool {
2021-12-21 04:31:19 +00:00
count, err := p.Store.Count(Item{}, bh.Where("Item").Eq(i))
2017-09-29 04:58:21 +00:00
if err != nil {
2019-03-07 16:35:42 +00:00
log.Error().Err(err).Msg("Error checking for item")
2017-09-29 04:58:21 +00:00
return false
}
2021-12-20 17:40:10 +00:00
return count > 0
2017-09-29 04:58:21 +00:00
}
func (p *InventoryPlugin) remove(i string) {
2021-12-20 17:40:10 +00:00
err := p.Store.Delete(i, Item{})
2017-09-29 04:58:21 +00:00
if err != nil {
2019-03-07 16:35:42 +00:00
log.Error().Msg("Error inserting new inventory item")
2017-09-29 04:58:21 +00:00
}
}
2019-05-27 23:21:53 +00:00
func (p *InventoryPlugin) addItem(c bot.Connector, m msg.Message, i string) bool {
2017-09-29 04:58:21 +00:00
if p.exists(i) {
2019-05-27 23:21:53 +00:00
p.bot.Send(c, bot.Message, m.Channel, fmt.Sprintf("I already have %s.", i))
2017-09-29 04:58:21 +00:00
return true
}
var removed string
2019-01-22 00:16:57 +00:00
max := p.config.GetInt("inventory.max", 10)
if p.count() > max {
2017-09-29 04:58:21 +00:00
removed = p.removeRandom()
}
2021-12-20 17:40:10 +00:00
err := p.Store.Insert(i, Item{Name: i})
2017-09-29 04:58:21 +00:00
if err != nil {
2019-03-07 16:35:42 +00:00
log.Error().Err(err).Msg("Error inserting new inventory item")
2017-09-29 04:58:21 +00:00
}
if removed != "" {
2019-05-27 23:21:53 +00:00
p.bot.Send(c, bot.Action, m.Channel, fmt.Sprintf("dropped %s and took %s from %s", removed, i, m.User.Name))
2017-09-29 04:58:21 +00:00
} else {
2019-05-27 23:21:53 +00:00
p.bot.Send(c, bot.Action, m.Channel, fmt.Sprintf("takes %s from %s", i, m.User.Name))
2017-09-29 04:58:21 +00:00
}
return true
}