package store import ( "context" "database/sql" "encoding/json" "errors" "time" "g.fc.run/misc/byre/internal/api" ) type LeadInputKind string const ( LeadMessage LeadInputKind = "message" LeadSignal LeadInputKind = "signal" ) type LeadInput struct { ID int64 Owner string Kind LeadInputKind Actor string Text string Images []string CreatedAt time.Time } func (s *Store) AddLeadInput(ctx context.Context, in LeadInput) error { images, err := json.Marshal(append([]string{}, in.Images...)) if err != nil { return err } return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { _, err := tx.ExecContext(ctx, `INSERT INTO lead_inputs (owner, kind, actor, text, images, created_at) VALUES (?, ?, ?, ?, ?, ?)`, in.Owner, string(in.Kind), in.Actor, in.Text, string(images), now()) return err }) } func (s *Store) LeadInputs(ctx context.Context, owner string) ([]LeadInput, error) { rows, err := s.db.QueryContext(ctx, `SELECT id, owner, kind, actor, text, images, created_at FROM lead_inputs WHERE owner = ? ORDER BY id`, owner) if err != nil { return nil, err } defer rows.Close() inputs := []LeadInput{} for rows.Next() { in := LeadInput{} kind := "" images := "" createdAt := "" err = rows.Scan(&in.ID, &in.Owner, &kind, &in.Actor, &in.Text, &images, &createdAt) if err != nil { return nil, err } in.Kind = LeadInputKind(kind) err = json.Unmarshal([]byte(images), &in.Images) if err != nil { return nil, err } in.CreatedAt, err = parseTime(createdAt) if err != nil { return nil, err } inputs = append(inputs, in) } return inputs, rows.Err() } func (s *Store) RestoreLeadInputs(ctx context.Context, inputs []LeadInput) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { for _, in := range inputs { images, err := json.Marshal(append([]string{}, in.Images...)) if err != nil { return err } _, err = tx.ExecContext(ctx, `INSERT INTO lead_inputs (id, owner, kind, actor, text, images, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)`, in.ID, in.Owner, string(in.Kind), in.Actor, in.Text, string(images), formatTime(in.CreatedAt)) if err != nil { return err } } return nil }) } func (s *Store) DeleteLeadInputs(ctx context.Context, ids []int64) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { for _, id := range ids { _, err := tx.ExecContext(ctx, `DELETE FROM lead_inputs WHERE id = ?`, id) if err != nil { return err } } return nil }) } func (s *Store) GetFocus(ctx context.Context, login string) (api.Focus, error) { f := api.Focus{} raw := "" err := s.db.QueryRowContext(ctx, `SELECT focus FROM users WHERE login = ?`, login).Scan(&raw) if errors.Is(err, sql.ErrNoRows) { return f, ErrNotFound } if err != nil { return f, err } err = json.Unmarshal([]byte(raw), &f) return f, err } func (s *Store) SetFocus(ctx context.Context, login string, f api.Focus, actor string) error { raw, err := json.Marshal(f) if err != nil { return err } return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { _, err := tx.ExecContext(ctx, `UPDATE users SET focus = ? WHERE login = ?`, string(raw), login) if err != nil { return err } return emit(api.Event{Kind: "focus.updated", Owner: &login, Actor: actor, Payload: ToPayload(f)}) }) }