package store import ( "database/sql" "time" _ "modernc.org/sqlite" ) type User struct { ID int64 Email string PasswordHash string PodcastTitle string PodcastImage string PodcastAuthor string CreatedAt time.Time } type Episode struct { ID int64 UserID int64 Title string Description string AudioPath string ImagePath string PublishedAt time.Time CreatedAt time.Time } type Store struct { db *sql.DB } func New(path string) (*Store, error) { db, err := sql.Open("sqlite", path) if err != nil { return nil, err } db.SetMaxOpenConns(1) if err := migrate(db); err != nil { return nil, err } return &Store{db: db}, nil } func migrate(db *sql.DB) error { schema := ` CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL, podcast_title TEXT NOT NULL DEFAULT '', podcast_image TEXT NOT NULL DEFAULT '', podcast_author TEXT NOT NULL DEFAULT '', created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS episodes ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL REFERENCES users(id), title TEXT NOT NULL, description TEXT NOT NULL DEFAULT '', audio_path TEXT NOT NULL DEFAULT '', image_path TEXT NOT NULL DEFAULT '', published_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ); ` _, err := db.Exec(schema) return err } func (s *Store) Close() error { return s.db.Close() } // --- Users --- func (s *Store) UserCount() (int, error) { var n int err := s.db.QueryRow("SELECT COUNT(*) FROM users").Scan(&n) return n, err } func (s *Store) CreateUser(email, passwordHash string) (int64, error) { res, err := s.db.Exec("INSERT INTO users (email, password_hash) VALUES (?, ?)", email, passwordHash) if err != nil { return 0, err } return res.LastInsertId() } func (s *Store) UserByEmail(email string) (*User, error) { u := &User{} err := s.db.QueryRow("SELECT id, email, password_hash, podcast_title, podcast_image, podcast_author, created_at FROM users WHERE email = ?", email). Scan(&u.ID, &u.Email, &u.PasswordHash, &u.PodcastTitle, &u.PodcastImage, &u.PodcastAuthor, &u.CreatedAt) if err != nil { return nil, err } return u, nil } func (s *Store) GetUser(id int64) (*User, error) { u := &User{} err := s.db.QueryRow("SELECT id, email, password_hash, podcast_title, podcast_image, podcast_author, created_at FROM users WHERE id = ?", id). Scan(&u.ID, &u.Email, &u.PasswordHash, &u.PodcastTitle, &u.PodcastImage, &u.PodcastAuthor, &u.CreatedAt) if err != nil { return nil, err } return u, nil } func (s *Store) UpdateUserPodcast(id int64, title, image, author string) error { _, err := s.db.Exec("UPDATE users SET podcast_title=?, podcast_image=?, podcast_author=? WHERE id=?", title, image, author, id) return err } // --- Episodes --- func (s *Store) ListEpisodes(userID int64) ([]Episode, error) { rows, err := s.db.Query("SELECT id, user_id, title, description, audio_path, image_path, published_at, created_at FROM episodes WHERE user_id = ? ORDER BY published_at DESC", userID) if err != nil { return nil, err } defer rows.Close() var eps []Episode for rows.Next() { var e Episode if err := rows.Scan(&e.ID, &e.UserID, &e.Title, &e.Description, &e.AudioPath, &e.ImagePath, &e.PublishedAt, &e.CreatedAt); err != nil { return nil, err } eps = append(eps, e) } return eps, rows.Err() } func (s *Store) GetEpisode(id int64) (*Episode, error) { e := &Episode{} err := s.db.QueryRow("SELECT id, user_id, title, description, audio_path, image_path, published_at, created_at FROM episodes WHERE id = ?", id). Scan(&e.ID, &e.UserID, &e.Title, &e.Description, &e.AudioPath, &e.ImagePath, &e.PublishedAt, &e.CreatedAt) if err != nil { return nil, err } return e, nil } func (s *Store) CreateEpisode(userID int64, title, description, audioPath, imagePath string, publishedAt time.Time) (int64, error) { res, err := s.db.Exec("INSERT INTO episodes (user_id, title, description, audio_path, image_path, published_at) VALUES (?, ?, ?, ?, ?, ?)", userID, title, description, audioPath, imagePath, publishedAt) if err != nil { return 0, err } return res.LastInsertId() } func (s *Store) UpdateEpisode(id int64, title, description, audioPath, imagePath string, publishedAt time.Time) error { _, err := s.db.Exec("UPDATE episodes SET title=?, description=?, audio_path=?, image_path=?, published_at=? WHERE id=?", title, description, audioPath, imagePath, publishedAt, id) return err } func (s *Store) DeleteEpisode(id int64) error { _, err := s.db.Exec("DELETE FROM episodes WHERE id = ?", id) return err }