mirror of https://github.com/velour/catbase.git
Compare commits
No commits in common. "c7a3200a23c1649bff4b79bf020199d508a2971f" and "21d4b11df9a7272caf2940e50341c8a70513343c" have entirely different histories.
c7a3200a23
...
21d4b11df9
2
main.go
2
main.go
|
@ -9,7 +9,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/velour/catbase/plugins/achievements"
|
|
||||||
"github.com/velour/catbase/plugins/aoc"
|
"github.com/velour/catbase/plugins/aoc"
|
||||||
"github.com/velour/catbase/plugins/twitter"
|
"github.com/velour/catbase/plugins/twitter"
|
||||||
|
|
||||||
|
@ -139,7 +138,6 @@ func main() {
|
||||||
b.AddPlugin(impossible.New(b))
|
b.AddPlugin(impossible.New(b))
|
||||||
b.AddPlugin(cli.New(b))
|
b.AddPlugin(cli.New(b))
|
||||||
b.AddPlugin(aoc.New(b))
|
b.AddPlugin(aoc.New(b))
|
||||||
b.AddPlugin(achievements.New(b))
|
|
||||||
// catches anything left, will always return true
|
// catches anything left, will always return true
|
||||||
b.AddPlugin(fact.New(b))
|
b.AddPlugin(fact.New(b))
|
||||||
|
|
||||||
|
|
|
@ -1,240 +0,0 @@
|
||||||
package achievements
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/jmoiron/sqlx"
|
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
|
|
||||||
"github.com/velour/catbase/bot"
|
|
||||||
"github.com/velour/catbase/bot/msg"
|
|
||||||
"github.com/velour/catbase/config"
|
|
||||||
)
|
|
||||||
|
|
||||||
// A plugin to track our misdeeds
|
|
||||||
type AchievementsPlugin struct {
|
|
||||||
bot bot.Bot
|
|
||||||
cfg *config.Config
|
|
||||||
db *sqlx.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
func New(b bot.Bot) *AchievementsPlugin {
|
|
||||||
ap := &AchievementsPlugin{
|
|
||||||
bot: b,
|
|
||||||
cfg: b.Config(),
|
|
||||||
db: b.DB(),
|
|
||||||
}
|
|
||||||
err := ap.mkDB()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal().Err(err).Msg("unable to create achievements tables")
|
|
||||||
}
|
|
||||||
b.Register(ap, bot.Message, ap.message)
|
|
||||||
b.Register(ap, bot.Help, ap.help)
|
|
||||||
return ap
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *AchievementsPlugin) mkDB() error {
|
|
||||||
trophiesTable := `create table if not exists trophies (
|
|
||||||
emojy string primary key,
|
|
||||||
description string,
|
|
||||||
creator string
|
|
||||||
);`
|
|
||||||
|
|
||||||
awardsTable := `create table if not exists awards (
|
|
||||||
id integer primary key,
|
|
||||||
emojy string references trophies(emojy) on delete restrict on update cascade,
|
|
||||||
holder string,
|
|
||||||
amount integer default 0,
|
|
||||||
granted timestamp CURRENT_TIMESTAMP
|
|
||||||
);`
|
|
||||||
tx, err := p.db.Beginx()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err = tx.Exec(trophiesTable); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err = tx.Exec(awardsTable); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = tx.Commit()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *AchievementsPlugin) GetAwards(nick string) []Award {
|
|
||||||
var awards []Award
|
|
||||||
q := `select * from awards inner join trophies on awards.emojy=trophies.emojy where holder=?`
|
|
||||||
if err := p.db.Select(&awards, q, nick); err != nil {
|
|
||||||
log.Error().Err(err).Msg("could not select awards")
|
|
||||||
}
|
|
||||||
return awards
|
|
||||||
}
|
|
||||||
|
|
||||||
var grantRegex = regexp.MustCompile(`(?i)grant (?P<emojy>(?::[[:word:][:punct:]]+:\s?)+) to :?(?P<nick>[[:word:]]+):?`)
|
|
||||||
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:]]*`)
|
|
||||||
|
|
||||||
func (p *AchievementsPlugin) message(c bot.Connector, kind bot.Kind, message msg.Message, args ...interface{}) bool {
|
|
||||||
nick := message.User.Name
|
|
||||||
|
|
||||||
if greatRegex.MatchString(message.Body) {
|
|
||||||
submatches := greatRegex.FindAllStringSubmatch(message.Body, -1)
|
|
||||||
who := submatches[0][1]
|
|
||||||
if who == "" {
|
|
||||||
who = nick
|
|
||||||
}
|
|
||||||
awards := p.GetAwards(who)
|
|
||||||
if len(awards) == 0 {
|
|
||||||
m := fmt.Sprintf("%s has no achievements to their name. They really suck.", who)
|
|
||||||
if who == nick {
|
|
||||||
m = fmt.Sprintf("You have no achievements to your name. "+
|
|
||||||
"You are a sad and terrible specimen of the human condition, %s.", who)
|
|
||||||
}
|
|
||||||
p.bot.Send(c, bot.Message, message.Channel, m)
|
|
||||||
} else {
|
|
||||||
m := fmt.Sprintf("Wow, let's all clap for %s. Look at these awards:", who)
|
|
||||||
for _, a := range awards {
|
|
||||||
m += fmt.Sprintf("\n%s - %s", a.Emojy, a.Description)
|
|
||||||
}
|
|
||||||
p.bot.Send(c, bot.Message, message.Channel, m)
|
|
||||||
}
|
|
||||||
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 {
|
|
||||||
ch := message.Channel
|
|
||||||
me := p.bot.WhoAmI()
|
|
||||||
msg := "The achievements plugins awards trophies."
|
|
||||||
msg += fmt.Sprintf("\nYou can create a trophy with `%s, create trophy <emojy> <description>`", me)
|
|
||||||
msg += fmt.Sprintf("\nYou can award a trophy with `%s, grant <emojy> to <nick>`", me)
|
|
||||||
msg += "\nYou can see others awards with `How great is <nick>`"
|
|
||||||
msg += "\nYou can see your awards with `How great am I?`"
|
|
||||||
p.bot.Send(c, bot.Message, ch, msg)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Award is used by other plugins to register a particular award for a user
|
|
||||||
func (p *AchievementsPlugin) Grant(nick, emojy string) (Award, error) {
|
|
||||||
empty := Award{}
|
|
||||||
q := `insert into awards (emojy,holder) values (?, ?)`
|
|
||||||
tx, err := p.db.Beginx()
|
|
||||||
if err != nil {
|
|
||||||
return empty, err
|
|
||||||
}
|
|
||||||
if _, err := tx.Exec(q, emojy, nick); err != nil {
|
|
||||||
tx.Rollback()
|
|
||||||
return empty, err
|
|
||||||
}
|
|
||||||
if err := tx.Commit(); err != nil {
|
|
||||||
return empty, err
|
|
||||||
}
|
|
||||||
return p.FindAward(emojy)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *AchievementsPlugin) Create(emojy, description, creator string) (Trophy, error) {
|
|
||||||
t, err := p.FindTrophy(emojy)
|
|
||||||
if err == nil {
|
|
||||||
return t, fmt.Errorf("the trophy %s already exists", emojy)
|
|
||||||
}
|
|
||||||
|
|
||||||
q := `insert into trophies (emojy,description,creator) values (?,?,?)`
|
|
||||||
tx, err := p.db.Beginx()
|
|
||||||
if err != nil {
|
|
||||||
return Trophy{}, err
|
|
||||||
}
|
|
||||||
_, err = tx.Exec(q, emojy, description, creator)
|
|
||||||
if err != nil {
|
|
||||||
tx.Rollback()
|
|
||||||
return Trophy{}, err
|
|
||||||
}
|
|
||||||
err = tx.Commit()
|
|
||||||
return Trophy{
|
|
||||||
Emojy: emojy,
|
|
||||||
Description: description,
|
|
||||||
Creator: creator,
|
|
||||||
}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
type Trophy struct {
|
|
||||||
Emojy string
|
|
||||||
Description string
|
|
||||||
Creator string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Award struct {
|
|
||||||
Trophy
|
|
||||||
ID int64
|
|
||||||
Holder string
|
|
||||||
Amount int
|
|
||||||
Granted *time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *Award) Save() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *AchievementsPlugin) FindTrophy(emojy string) (Trophy, error) {
|
|
||||||
q := `select * from trophies where emojy=?`
|
|
||||||
var t Trophy
|
|
||||||
err := p.db.Get(&t, q, emojy)
|
|
||||||
return t, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *AchievementsPlugin) FindAward(emojy string) (Award, error) {
|
|
||||||
q := `select * from awards inner join trophies on awards.emojy=trophies.emojy where trophies.emojy=?`
|
|
||||||
var a Award
|
|
||||||
err := p.db.Get(&a, q, emojy)
|
|
||||||
return a, err
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
package achievements
|
|
Loading…
Reference in New Issue