package quotegame import ( "fmt" "math/rand" "regexp" "strings" "time" "github.com/jmoiron/sqlx" "github.com/rs/zerolog/log" "github.com/velour/catbase/bot" "github.com/velour/catbase/config" ) type QuoteGame struct { b bot.Bot c *config.Config db *sqlx.DB handlers []bot.HandlerSpec currentGame *time.Timer currentName string } func New(b bot.Bot) *QuoteGame { p := &QuoteGame{ b: b, c: b.Config(), db: b.DB(), currentGame: nil, } p.register() return p } func (p *QuoteGame) register() { log.Debug().Msg("registering quote handlers") p.handlers = []bot.HandlerSpec{ { Kind: bot.Message, IsCmd: false, Regex: regexp.MustCompile(`(?i)^quote game$`), HelpText: "Start a quote game", Handler: p.startGame, }, { Kind: bot.Message, IsCmd: false, Regex: regexp.MustCompile(`(?i)^guess:\s?(?P.+)$`), Handler: p.guess, }, } p.b.RegisterTable(p, p.handlers) } type quote struct { Fact string Tidbit string } func (p *QuoteGame) getAllQuotes() ([]quote, error) { threshold := p.c.GetInt("quotegame.threshold", 10) q := `select fact, tidbit from factoid where fact like '%quotes' group by fact having count(fact) > ?` quotes := []quote{} err := p.db.Select("es, q, threshold) if err != nil { return nil, err } return quotes, nil } func (p *QuoteGame) getRandomquote() (string, string, error) { quotes, err := p.getAllQuotes() if err != nil { return "", "", err } quote := quotes[rand.Intn(len(quotes))] who := strings.ReplaceAll(quote.Fact, " quotes", "") what := strings.ReplaceAll(quote.Tidbit, who, "") what = strings.Trim(what, " <>") return who, what, nil } func (p *QuoteGame) startGame(r bot.Request) bool { log.Debug().Msg("startGame called") if p.currentGame != nil { p.b.Send(r.Conn, bot.Message, r.Msg.Channel, "There is already a quote game running.") return true } who, quote, err := p.getRandomquote() if err != nil { log.Error().Err(err).Msg("problem getting quote") p.b.Send(r.Conn, bot.Message, r.Msg.Channel, "Error: "+err.Error()) return true } length := time.Duration(p.c.GetInt("quotegame.length", 120)) p.currentGame = time.AfterFunc(length*time.Second, func() { p.currentGame = nil p.currentName = "" p.b.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("The quote game ended and nobody won. The answer was %s", who)) }) p.currentName = who msg := fmt.Sprintf("Quote game: Who said \"%s\"?\nYou have %d seconds to guess.\nUse `guess: name` to guess who.", quote, length) p.b.Send(r.Conn, bot.Message, r.Msg.Channel, msg) return true } func (p *QuoteGame) guess(r bot.Request) bool { log.Debug().Msg("quote game message check") if p.currentGame == nil { return false } if r.Values["name"] == p.currentName { msg := fmt.Sprintf("%s won the quote game!", r.Msg.User.Name) p.b.Send(r.Conn, bot.Message, r.Msg.Channel, msg) p.currentName = "" p.currentGame.Stop() p.currentGame = nil return true } p.b.Send(r.Conn, bot.Message, r.Msg.Channel, fmt.Sprintf("Sorry %s, that's not correct.", r.Msg.User.Name)) return true }