package user import ( "context" "database/sql" "errors" "time" "git.anhgelus.world/anhgelus/les-copaings-bot/common" ) type Copaing struct { ID uint64 CopaingXPs []CopaingXP `gorm:"constraint:OnDelete:SET NULL;"` GuildID uint64 `gorm:"not null"` lastSaved int } type CopaingXP struct { XP uint `gorm:"default:0"` CopaingID uint64 GuildID uint64 `gorm:"not null;"` CreatedAt time.Time } type CopaingAccess interface { Copaing() *Copaing GetXP() uint } func GetCopaing(ctx context.Context, discordID, guildID uint64) *CopaingCached { state := GetState(ctx) cc, err := state.Copaing(guildID, discordID) if err != nil { c := Copaing{ID: discordID, GuildID: guildID} if err := c.load(ctx); err != nil { panic(err) } cc = FromCopaing(&c) } return cc } func (c *Copaing) load(ctx context.Context) error { db := common.GetDB(ctx) row := db.QueryRowContext( ctx, `SELECT id, guild_id FROM copaings WHERE id = ? AND guild_id = ?`, c.ID, c.GuildID, ) c.CopaingXPs = make([]CopaingXP, 0) c.lastSaved = 0 err := row.Err() if err != nil { if !errors.Is(err, sql.ErrNoRows) { return err } _, err = db.ExecContext( ctx, `INSERT INTO copaings (id, guild_id) VALUES (?, ?)`, c.ID, c.GuildID, ) return err } rows, err := db.QueryContext( ctx, `SELECT xp, created_at FROM copaing_xps WHERE copaing_id = ? AND guild_id = ?`, c.ID, c.GuildID, ) if err != nil { if !errors.Is(err, sql.ErrNoRows) { return err } return nil } for rows.Next() { var xp CopaingXP err = rows.Scan(&xp.XP, &xp.CreatedAt) if err != nil { return err } xp.CopaingID = c.ID xp.GuildID = c.GuildID c.CopaingXPs = append(c.CopaingXPs, xp) } c.lastSaved = len(c.CopaingXPs) return nil } func (c *Copaing) Save(ctx context.Context) error { if c.lastSaved == len(c.CopaingXPs) { return nil } db := common.GetDB(ctx) for _, xp := range c.CopaingXPs[c.lastSaved:] { _, err := db.ExecContext( ctx, `INSERT INTO copaing_xps (copaing_id, guild_id, xp) VALUES (?, ?, ?)`, c.ID, c.GuildID, xp.XP, ) if err != nil { return err } c.lastSaved++ } return nil } func (c *Copaing) Delete(ctx context.Context) error { _, err := common.GetDB(ctx).ExecContext( ctx, `DELETE FROM copaings WHERE copaing_id = ? AND guild_id = ?`, c.ID, c.GuildID, ) c.lastSaved = 0 c.CopaingXPs = nil return err }