package sqlite import ( "context" "database/sql" "git.gobha.me/xcaliber/chat-switchboard/models" "git.gobha.me/xcaliber/chat-switchboard/store" ) // ── SessionStore ─────────────────────────── type SessionStore struct{} func NewSessionStore() *SessionStore { return &SessionStore{} } func (s *SessionStore) Create(ctx context.Context, sp *models.SessionParticipant) error { if sp.ID == "" { sp.ID = store.NewID() } _, err := DB.ExecContext(ctx, ` INSERT INTO session_participants (id, session_token, channel_id, display_name, fingerprint) VALUES (?, ?, ?, ?, ?)`, sp.ID, sp.SessionToken, sp.ChannelID, sp.DisplayName, nullText(sp.Fingerprint), ) if err != nil { return err } return DB.QueryRowContext(ctx, `SELECT created_at FROM session_participants WHERE id = ?`, sp.ID). Scan(&sp.CreatedAt) } func (s *SessionStore) GetByToken(ctx context.Context, token string) (*models.SessionParticipant, error) { sp := &models.SessionParticipant{} err := DB.QueryRowContext(ctx, ` SELECT id, session_token, channel_id, display_name, COALESCE(fingerprint, ''), created_at FROM session_participants WHERE session_token = ?`, token, ).Scan(&sp.ID, &sp.SessionToken, &sp.ChannelID, &sp.DisplayName, &sp.Fingerprint, &sp.CreatedAt) if err != nil { return nil, err } return sp, nil } func (s *SessionStore) GetByID(ctx context.Context, id string) (*models.SessionParticipant, error) { sp := &models.SessionParticipant{} err := DB.QueryRowContext(ctx, ` SELECT id, session_token, channel_id, display_name, COALESCE(fingerprint, ''), created_at FROM session_participants WHERE id = ?`, id, ).Scan(&sp.ID, &sp.SessionToken, &sp.ChannelID, &sp.DisplayName, &sp.Fingerprint, &sp.CreatedAt) if err != nil { return nil, err } return sp, nil } func (s *SessionStore) ListForChannel(ctx context.Context, channelID string) ([]models.SessionParticipant, error) { rows, err := DB.QueryContext(ctx, ` SELECT id, session_token, channel_id, display_name, COALESCE(fingerprint, ''), created_at FROM session_participants WHERE channel_id = ? ORDER BY created_at ASC`, channelID) if err != nil { return nil, err } defer rows.Close() var result []models.SessionParticipant for rows.Next() { var sp models.SessionParticipant if err := rows.Scan(&sp.ID, &sp.SessionToken, &sp.ChannelID, &sp.DisplayName, &sp.Fingerprint, &sp.CreatedAt); err != nil { return nil, err } result = append(result, sp) } return result, rows.Err() } func (s *SessionStore) CountForChannel(ctx context.Context, channelID string) (int, error) { var count int err := DB.QueryRowContext(ctx, ` SELECT COUNT(*) FROM session_participants WHERE channel_id = ?`, channelID, ).Scan(&count) return count, err } func (s *SessionStore) Delete(ctx context.Context, id string) error { res, err := DB.ExecContext(ctx, `DELETE FROM session_participants WHERE id = ?`, id) if err != nil { return err } n, _ := res.RowsAffected() if n == 0 { return sql.ErrNoRows } return nil } func nullText(s string) interface{} { if s == "" { return nil } return s }