package store import ( "context" "database/sql" "encoding/json" "time" ) type TaskInput struct { ID int64 TaskID string Actor string Text string Images []string CreatedAt time.Time } func (s *Store) AddTaskInput(ctx context.Context, in TaskInput, projectID, sessionID string) error { images, err := json.Marshal(append([]string{}, in.Images...)) if err != nil { return err } payload := map[string]any{"text": in.Text} if len(in.Images) > 0 { payload["images"] = in.Images } return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { res, err := tx.ExecContext(ctx, `INSERT INTO task_inputs (task_id, actor, text, images, created_at) VALUES (?, ?, ?, ?, ?)`, in.TaskID, in.Actor, in.Text, string(images), now()) if err != nil { return err } payload["id"], err = res.LastInsertId() if err != nil { return err } return emit(sessionEvent("user.queued", projectID, in.TaskID, "", sessionID, in.Actor, payload)) }) } func (s *Store) WithdrawTaskInput(ctx context.Context, taskID string, id int64, projectID, sessionID, actor string) error { return s.write(ctx, func(tx *sql.Tx, emit emitFunc) error { res, err := tx.ExecContext(ctx, `DELETE FROM task_inputs WHERE id = ? AND task_id = ?`, id, taskID) if err != nil { return err } n, err := res.RowsAffected() if err != nil { return err } if n == 0 { return ErrNotFound } return emit(sessionEvent("user.unqueued", projectID, taskID, "", sessionID, actor, map[string]any{"id": id})) }) } func (s *Store) TaskInputs(ctx context.Context, taskID string) ([]TaskInput, error) { rows, err := s.db.QueryContext(ctx, `SELECT id, task_id, actor, text, images, created_at FROM task_inputs WHERE task_id = ? ORDER BY id`, taskID) if err != nil { return nil, err } defer rows.Close() inputs := []TaskInput{} for rows.Next() { in := TaskInput{} images := "" createdAt := "" err = rows.Scan(&in.ID, &in.TaskID, &in.Actor, &in.Text, &images, &createdAt) if err != nil { return nil, err } 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) RestoreTaskInputs(ctx context.Context, inputs []TaskInput) 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 task_inputs (id, task_id, actor, text, images, created_at) VALUES (?, ?, ?, ?, ?, ?)`, in.ID, in.TaskID, in.Actor, in.Text, string(images), formatTime(in.CreatedAt)) if err != nil { return err } } return nil }) } func (s *Store) DeleteTaskInputs(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 task_inputs WHERE id = ?`, id) if err != nil { return err } } return nil }) }