Files

124 lines
2.4 KiB
Go

package db
import (
"context"
"encoding/json"
"errors"
"time"
"github.com/jackc/pgx/v5"
)
type WizardData map[string]any
type AdminWizard struct {
AdminID int64
Step string
Data WizardData
}
func (d *DB) GetWizard(ctx context.Context, adminID int64) (*AdminWizard, error) {
row := d.pool.QueryRow(ctx, `
SELECT admin_telegram_id, step, data
FROM admin_wizard WHERE admin_telegram_id = $1`, adminID)
var w AdminWizard
var raw []byte
if err := row.Scan(&w.AdminID, &w.Step, &raw); err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return nil, nil
}
return nil, err
}
if len(raw) > 0 {
_ = json.Unmarshal(raw, &w.Data)
}
if w.Data == nil {
w.Data = WizardData{}
}
return &w, nil
}
func (d *DB) SetWizard(ctx context.Context, adminID int64, step string, data WizardData) error {
raw, _ := json.Marshal(data)
_, err := d.pool.Exec(ctx, `
INSERT INTO admin_wizard (admin_telegram_id, step, data, updated_at)
VALUES ($1, $2, $3, NOW())
ON CONFLICT (admin_telegram_id) DO UPDATE SET
step = EXCLUDED.step,
data = EXCLUDED.data,
updated_at = NOW()`,
adminID, step, raw)
return err
}
func (d *DB) ClearWizard(ctx context.Context, adminID int64) error {
_, err := d.pool.Exec(ctx, `DELETE FROM admin_wizard WHERE admin_telegram_id = $1`, adminID)
return err
}
func (w WizardData) String(key string) string {
v, _ := w[key].(string)
return v
}
func (w WizardData) Int(key string) int {
switch v := w[key].(type) {
case float64:
return int(v)
case int:
return v
default:
return 0
}
}
func (w WizardData) StringSlice(key string) []string {
raw, ok := w[key].([]any)
if !ok {
if ss, ok := w[key].([]string); ok {
return ss
}
return nil
}
out := make([]string, 0, len(raw))
for _, x := range raw {
if s, ok := x.(string); ok {
out = append(out, s)
}
}
return out
}
func (w WizardData) Set(key string, val any) {
w[key] = val
}
func (w WizardData) ToggleUUID(key, uuid string) {
cur := w.StringSlice(key)
for i, id := range cur {
if id == uuid {
cur = append(cur[:i], cur[i+1:]...)
w[key] = cur
return
}
}
w[key] = append(cur, uuid)
}
const (
StepIdle = ""
StepAwaitUsername = "await_username"
StepAwaitDays = "await_days"
StepPickExternalSquad = "pick_external"
StepPickInternalSquads = "pick_internal"
StepConfirm = "confirm"
)
func DefaultExpireAt(days int) time.Time {
if days <= 0 {
days = 30
}
return time.Now().UTC().AddDate(0, 0, days)
}