You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
2.8 KiB
Go
123 lines
2.8 KiB
Go
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
|
|
}
|