package dao import ( "context" "database/sql" "git.xeserv.us/xena/gorqlite" "github.com/opentracing/opentracing-go" splog "github.com/opentracing/opentracing-go/log" ) type Users struct { conn gorqlite.Connection } func NewUsers(conn gorqlite.Connection) *Users { return &Users{conn: conn} } func (u *Users) Migrate(ctx context.Context) error { sp, ctx := opentracing.StartSpanFromContext(ctx, "users.migrate") defer sp.Finish() migrationDDL := []string{ `CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY, discord_id TEXT UNIQUE, score INTEGER)`, } res, err := u.conn.Write(migrationDDL) if err != nil { sp.LogFields(splog.Error(err)) } for i, re := range res { if re.Err != nil { sp.LogFields(splog.Error(err)) return err } sp.LogFields(splog.Int("migration.step", i), splog.Float64("timing", re.Timing), splog.Int64("rows.affected", re.RowsAffected)) } return nil } func (u *Users) Insert(ctx context.Context, discordID string) (int64, error) { sp, ctx := opentracing.StartSpanFromContext(ctx, "users.insert") defer sp.Finish() sp.LogFields(splog.String("discord.id", discordID)) re, err := u.conn.WriteOne(gorqlite.NewPreparedStatement("INSERT INTO users (discord_id, score) VALUES (%s, 0)").Bind(discordID)) if err != nil { sp.LogFields(splog.Error(err)) sp.LogFields(splog.Error(re.Err)) return -1, err } if re.Err != nil { sp.LogFields(splog.Error(re.Err)) return -1, err } return re.LastInsertID, nil } func (u *Users) IncScore(ctx context.Context, discordID string) error { sp, ctx := opentracing.StartSpanFromContext(ctx, "users.inc.score") defer sp.Finish() sp.LogFields(splog.String("discord.id", discordID)) re, err := u.conn.WriteOne(gorqlite.NewPreparedStatement("UPDATE users SET score = score + 1 WHERE discord_id=%s").Bind(discordID)) if err != nil { sp.LogFields(splog.Error(err)) } if re.Err != nil { sp.LogFields(splog.Error(re.Err)) return re.Err } return nil } type User struct { ID int64 `json:"id"` DiscordID string `json:"discord_id"` Score int64 `json:"score"` } func (u *Users) Top10(ctx context.Context) ([]User, error) { sp, ctx := opentracing.StartSpanFromContext(ctx, "users.top10") defer sp.Finish() qr, err := u.conn.QueryOne("SELECT id, discord_id, score FROM users WHERE score > 0 ORDER BY score DESC LIMIT 10") if err != nil { sp.LogFields(splog.Error(err)) } if qr.Err != nil { sp.LogFields(splog.Error(qr.Err)) return nil, qr.Err } var result []User if qr.NumRows() == 0 { sp.LogFields(splog.Error(sql.ErrNoRows)) return nil, sql.ErrNoRows } for qr.Next() { var u User err = qr.Scan(&u.ID, &u.DiscordID, &u.Score) if err != nil { sp.LogFields(splog.Error(err)) return nil, err } result = append(result, u) } return result, nil }