124 lines
2.4 KiB
Go
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)
|
|
}
|