diff --git a/client/imdb.go b/client/imdb.go index 7692a80..cf71f7d 100644 --- a/client/imdb.go +++ b/client/imdb.go @@ -7,7 +7,7 @@ import ( "strconv" "strings" - "code.ewintr.nl/emdb/cmd/api-service/moviestore" + "code.ewintr.nl/emdb/storage" "github.com/PuerkitoBio/goquery" "github.com/google/uuid" ) @@ -19,7 +19,7 @@ func NewIMDB() *IMDB { return &IMDB{} } -func (i *IMDB) GetReviews(m moviestore.Movie) ([]moviestore.Review, error) { +func (i *IMDB) GetReviews(m storage.Movie) ([]storage.Review, error) { url := fmt.Sprintf("https://www.imdb.com/title/%s/reviews", m.IMDBID) req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { @@ -40,7 +40,7 @@ func (i *IMDB) GetReviews(m moviestore.Movie) ([]moviestore.Review, error) { } defer res.Body.Close() - reviews := make([]moviestore.Review, 0) + reviews := make([]storage.Review, 0) doc.Find(".lister-item-content").Each(func(i int, reviewNode *goquery.Selection) { var permaLink string @@ -58,10 +58,10 @@ func (i *IMDB) GetReviews(m moviestore.Movie) ([]moviestore.Review, error) { } rat, rev := ScrubIMDBReview(reviewNode.Text()) - reviews = append(reviews, moviestore.Review{ + reviews = append(reviews, storage.Review{ ID: uuid.New().String(), MovieID: m.ID, - Source: moviestore.ReviewSourceIMDB, + Source: storage.ReviewSourceIMDB, URL: fmt.Sprintf("https://www.imdb.com%s", permaLink), Review: rev, MovieRating: rat, diff --git a/client/tmdb.go b/client/tmdb.go index d4c2876..e64b058 100644 --- a/client/tmdb.go +++ b/client/tmdb.go @@ -3,7 +3,7 @@ package client import ( "time" - "code.ewintr.nl/emdb/cmd/api-service/moviestore" + "code.ewintr.nl/emdb/storage" tmdb "github.com/cyruzin/golang-tmdb" ) @@ -24,13 +24,13 @@ func NewTMDB(apikey string) (*TMDB, error) { }, nil } -func (t TMDB) Search(query string) ([]moviestore.Movie, error) { +func (t TMDB) Search(query string) ([]storage.Movie, error) { results, err := t.c.GetSearchMovies(query, nil) if err != nil { return nil, err } - movies := make([]moviestore.Movie, len(results.Results)) + movies := make([]storage.Movie, len(results.Results)) for i, result := range results.Results { movies[i], err = t.GetMovie(result.ID) if err != nil { @@ -41,12 +41,12 @@ func (t TMDB) Search(query string) ([]moviestore.Movie, error) { return movies, nil } -func (t TMDB) GetMovie(id int64) (moviestore.Movie, error) { +func (t TMDB) GetMovie(id int64) (storage.Movie, error) { result, err := t.c.GetMovieDetails(int(id), map[string]string{ "append_to_response": "credits", }) if err != nil { - return moviestore.Movie{}, err + return storage.Movie{}, err } var year int @@ -61,7 +61,7 @@ func (t TMDB) GetMovie(id int64) (moviestore.Movie, error) { } } - return moviestore.Movie{ + return storage.Movie{ Title: result.OriginalTitle, EnglishTitle: result.Title, TMDBID: result.ID, diff --git a/cmd/api-service/handler/movie.go b/cmd/api-service/handler/movie.go index 75aa4b0..547e3bd 100644 --- a/cmd/api-service/handler/movie.go +++ b/cmd/api-service/handler/movie.go @@ -10,19 +10,19 @@ import ( "log/slog" "net/http" - "code.ewintr.nl/emdb/cmd/api-service/moviestore" "code.ewintr.nl/emdb/job" + "code.ewintr.nl/emdb/storage" "github.com/google/uuid" ) type MovieAPI struct { apis APIIndex - repo *moviestore.MovieRepository + repo *storage.MovieRepository jq *job.JobQueue logger *slog.Logger } -func NewMovieAPI(apis APIIndex, repo *moviestore.MovieRepository, jq *job.JobQueue, logger *slog.Logger) *MovieAPI { +func NewMovieAPI(apis APIIndex, repo *storage.MovieRepository, jq *job.JobQueue, logger *slog.Logger) *MovieAPI { return &MovieAPI{ apis: apis, repo: repo, @@ -93,7 +93,7 @@ func (movieAPI *MovieAPI) Store(w http.ResponseWriter, r *http.Request, urlID st } defer r.Body.Close() - var m moviestore.Movie + var m storage.Movie if err := json.Unmarshal(body, &m); err != nil { Error(w, http.StatusBadRequest, "could not unmarshal request body", err, logger) return diff --git a/cmd/api-service/handler/moviereview.go b/cmd/api-service/handler/moviereview.go index 6c8fa2f..ca5c2fd 100644 --- a/cmd/api-service/handler/moviereview.go +++ b/cmd/api-service/handler/moviereview.go @@ -6,15 +6,15 @@ import ( "log/slog" "net/http" - "code.ewintr.nl/emdb/cmd/api-service/moviestore" + "code.ewintr.nl/emdb/storage" ) type MovieReviewAPI struct { - repo *moviestore.ReviewRepository + repo *storage.ReviewRepository logger *slog.Logger } -func NewMovieReviewAPI(repo *moviestore.ReviewRepository, logger *slog.Logger) *MovieReviewAPI { +func NewMovieReviewAPI(repo *storage.ReviewRepository, logger *slog.Logger) *MovieReviewAPI { return &MovieReviewAPI{ repo: repo, logger: logger.With("api", "moviereview"), diff --git a/cmd/api-service/handler/review.go b/cmd/api-service/handler/review.go index af7ec83..bd5000b 100644 --- a/cmd/api-service/handler/review.go +++ b/cmd/api-service/handler/review.go @@ -6,15 +6,15 @@ import ( "log/slog" "net/http" - "code.ewintr.nl/emdb/cmd/api-service/moviestore" + "code.ewintr.nl/emdb/storage" ) type ReviewAPI struct { - repo *moviestore.ReviewRepository + repo *storage.ReviewRepository logger *slog.Logger } -func NewReviewAPI(repo *moviestore.ReviewRepository, logger *slog.Logger) *ReviewAPI { +func NewReviewAPI(repo *storage.ReviewRepository, logger *slog.Logger) *ReviewAPI { return &ReviewAPI{ repo: repo, logger: logger.With("api", "review"), @@ -139,7 +139,7 @@ func (reviewAPI *ReviewAPI) NextNoTitles(w http.ResponseWriter, r *http.Request) func (reviewAPI *ReviewAPI) Store(w http.ResponseWriter, r *http.Request, id string) { logger := reviewAPI.logger.With("method", "store") - var review moviestore.Review + var review storage.Review if err := json.NewDecoder(r.Body).Decode(&review); err != nil { Error(w, http.StatusBadRequest, "could not decode review", err, logger) return diff --git a/cmd/api-service/moviestore/movie.go b/cmd/api-service/moviestore/movie.go deleted file mode 100644 index e60f317..0000000 --- a/cmd/api-service/moviestore/movie.go +++ /dev/null @@ -1,99 +0,0 @@ -package moviestore - -import ( - "fmt" - "strings" - - "github.com/google/uuid" -) - -type Movie struct { - ID string `json:"id"` - TMDBID int64 `json:"tmdbID"` - IMDBID string `json:"imdbID"` - Title string `json:"title"` - EnglishTitle string `json:"englishTitle"` - Year int `json:"year"` - Directors []string `json:"directors"` - WatchedOn string `json:"watchedOn"` - Rating int `json:"rating"` - Summary string `json:"summary"` - Comment string `json:"comment"` -} - -type MovieRepository struct { - db *SQLite -} - -func NewMovieRepository(db *SQLite) *MovieRepository { - return &MovieRepository{ - db: db, - } -} - -func (mr *MovieRepository) Store(m Movie) error { - if m.ID == "" { - m.ID = uuid.New().String() - } - - directors := strings.Join(m.Directors, ",") - if _, err := mr.db.Exec(`REPLACE INTO movie (id, tmdb_id, imdb_id, title, english_title, year, directors, summary, watched_on, rating, comment) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, - m.ID, m.TMDBID, m.IMDBID, m.Title, m.EnglishTitle, m.Year, directors, m.Summary, m.WatchedOn, m.Rating, m.Comment); err != nil { - return fmt.Errorf("%w: %v", ErrSqliteFailure, err) - } - - return nil -} - -func (mr *MovieRepository) Delete(id string) error { - if _, err := mr.db.Exec(`DELETE FROM movie WHERE id=?`, id); err != nil { - return fmt.Errorf("%w: %v", ErrSqliteFailure, err) - } - - return nil -} - -func (mr *MovieRepository) FindOne(id string) (Movie, error) { - row := mr.db.QueryRow(` -SELECT id, tmdb_id, imdb_id, title, english_title, year, directors, summary, watched_on, rating, comment -FROM movie -WHERE id=?`, id) - if row.Err() != nil { - return Movie{}, row.Err() - } - - m := Movie{ - ID: id, - } - var directors string - if err := row.Scan(&m.ID, &m.TMDBID, &m.IMDBID, &m.Title, &m.EnglishTitle, &m.Year, &directors, &m.Summary, &m.WatchedOn, &m.Rating, &m.Comment); err != nil { - return Movie{}, fmt.Errorf("%w: %w", ErrSqliteFailure, err) - } - m.Directors = strings.Split(directors, ",") - - return m, nil -} - -func (mr *MovieRepository) FindAll() ([]Movie, error) { - rows, err := mr.db.Query(` -SELECT id, tmdb_id, imdb_id, title, english_title, year, directors, summary, watched_on, rating, comment -FROM movie`) - if err != nil { - return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err) - } - - movies := make([]Movie, 0) - defer rows.Close() - for rows.Next() { - m := Movie{} - var directors string - if err := rows.Scan(&m.ID, &m.TMDBID, &m.IMDBID, &m.Title, &m.EnglishTitle, &m.Year, &directors, &m.Summary, &m.WatchedOn, &m.Rating, &m.Comment); err != nil { - return nil, fmt.Errorf("%w: %v", ErrSqliteFailure, err) - } - m.Directors = strings.Split(directors, ",") - movies = append(movies, m) - } - - return movies, nil -} diff --git a/cmd/api-service/moviestore/review.go b/cmd/api-service/moviestore/review.go deleted file mode 100644 index e678993..0000000 --- a/cmd/api-service/moviestore/review.go +++ /dev/null @@ -1,208 +0,0 @@ -package moviestore - -import ( - "encoding/json" -) - -const ( - ReviewSourceIMDB = "imdb" - - MentionsSeparator = "|" -) - -type ReviewSource string - -type Titles struct { - Movies []string `json:"movies"` - TVShows []string `json:"tvShows"` - Games []string `json:"games"` - Books []string `json:"books"` -} - -type Review struct { - ID string - MovieID string - Source ReviewSource - URL string - Review string - MovieRating int - Quality int - Titles Titles -} - -type ReviewRepository struct { - db *SQLite -} - -func NewReviewRepository(db *SQLite) *ReviewRepository { - return &ReviewRepository{ - db: db, - } -} - -func (rr *ReviewRepository) Store(r Review) error { - titles, err := json.Marshal(r.Titles) - if err != nil { - return err - } - if _, err := rr.db.Exec(`REPLACE INTO review (id, movie_id, source, url, review, movie_rating, quality, mentioned_titles) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, - r.ID, r.MovieID, r.Source, r.URL, r.Review, r.MovieRating, r.Quality, titles); err != nil { - return err - } - - return nil -} - -func (rr *ReviewRepository) FindOne(id string) (Review, error) { - row := rr.db.QueryRow(`SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles FROM review WHERE id=?`, id) - if row.Err() != nil { - return Review{}, row.Err() - } - - r := Review{} - var titles string - if err := row.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil { - return Review{}, err - } - if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil { - return Review{}, err - } - - return r, nil -} - -func (rr *ReviewRepository) FindByMovieID(movieID string) ([]Review, error) { - rows, err := rr.db.Query(`SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles FROM review WHERE movie_id=?`, movieID) - if err != nil { - return nil, err - } - - reviews := make([]Review, 0) - var titles string - for rows.Next() { - r := Review{} - if err := rows.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil { - return nil, err - } - if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil { - return []Review{}, err - } - reviews = append(reviews, r) - } - rows.Close() - - return reviews, nil -} - -func (rr *ReviewRepository) FindNextUnrated() (Review, error) { - row := rr.db.QueryRow(`SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles FROM review WHERE quality=0 LIMIT 1`) - if row.Err() != nil { - return Review{}, row.Err() - } - - r := Review{} - var titles string - if err := row.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil { - return Review{}, err - } - if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil { - return Review{}, err - } - - return r, nil -} - -func (rr *ReviewRepository) FindUnrated() ([]Review, error) { - rows, err := rr.db.Query(`SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles FROM review WHERE quality=0`) - if err != nil { - return nil, err - } - - reviews := make([]Review, 0) - var titles string - for rows.Next() { - r := Review{} - if err := rows.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil { - return nil, err - } - if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil { - return []Review{}, err - } - reviews = append(reviews, r) - } - rows.Close() - - return reviews, nil -} - -func (rr *ReviewRepository) FindNextNoTitles() (Review, error) { - row := rr.db.QueryRow(`SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles FROM review WHERE mentioned_titles='{}' LIMIT 1`) - if row.Err() != nil { - return Review{}, row.Err() - } - - r := Review{} - var titles string - if err := row.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil { - return Review{}, err - } - if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil { - return Review{}, err - } - - return r, nil -} - -func (rr *ReviewRepository) FindNoTitles() ([]Review, error) { - rows, err := rr.db.Query(`SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles FROM review WHERE mentioned_titles='{}'`) - if err != nil { - return nil, err - } - - reviews := make([]Review, 0) - var titles string - for rows.Next() { - r := Review{} - if err := rows.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil { - return nil, err - } - if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil { - return []Review{}, err - } - reviews = append(reviews, r) - } - rows.Close() - - return reviews, nil -} - -func (rr *ReviewRepository) FindAll() ([]Review, error) { - rows, err := rr.db.Query(`SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles FROM review`) - if err != nil { - return nil, err - } - - reviews := make([]Review, 0) - var titles string - for rows.Next() { - r := Review{} - if err := rows.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil { - return nil, err - } - if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil { - return []Review{}, err - } - reviews = append(reviews, r) - } - rows.Close() - - return reviews, nil -} - -func (rr *ReviewRepository) DeleteByMovieID(id string) error { - if _, err := rr.db.Exec(`DELETE FROM review WHERE movie_id=?`, id); err != nil { - return err - } - - return nil -} diff --git a/cmd/api-service/service.go b/cmd/api-service/service.go index ff1af33..2a76968 100644 --- a/cmd/api-service/service.go +++ b/cmd/api-service/service.go @@ -13,6 +13,7 @@ import ( "code.ewintr.nl/emdb/cmd/api-service/handler" "code.ewintr.nl/emdb/cmd/api-service/moviestore" job2 "code.ewintr.nl/emdb/job" + "code.ewintr.nl/emdb/storage" ) var ( @@ -33,15 +34,15 @@ func main() { } jobQueue := job2.NewJobQueue(db, logger) - worker := job2.NewWorker(jobQueue, moviestore.NewMovieRepository(db), moviestore.NewReviewRepository(db), client.NewIMDB(), logger) + worker := job2.NewWorker(jobQueue, storage.NewMovieRepository(db), storage.NewReviewRepository(db), client.NewIMDB(), logger) go worker.Run() apis := handler.APIIndex{ "job": handler.NewJobAPI(jobQueue, logger), "movie": handler.NewMovieAPI(handler.APIIndex{ - "review": handler.NewMovieReviewAPI(moviestore.NewReviewRepository(db), logger), - }, moviestore.NewMovieRepository(db), jobQueue, logger), - "review": handler.NewReviewAPI(moviestore.NewReviewRepository(db), logger), + "review": handler.NewMovieReviewAPI(storage.NewReviewRepository(db), logger), + }, storage.NewMovieRepository(db), jobQueue, logger), + "review": handler.NewReviewAPI(storage.NewReviewRepository(db), logger), } go http.ListenAndServe(fmt.Sprintf(":%d", *port), handler.NewServer(*apiKey, apis, logger)) diff --git a/cmd/import/main.go b/cmd/import/main.go index f11aa94..61900f2 100644 --- a/cmd/import/main.go +++ b/cmd/import/main.go @@ -38,8 +38,8 @@ func main() { // } //} fmt.Println("reviews") - reviewRepoSqlite := moviestore.NewReviewRepository(dbSQLite) - reviewRepoPG := storage.NewReviewRepositoryPG(dbPostgres) + reviewRepoSqlite := storage.NewReviewRepository(dbSQLite) + reviewRepoPG := storage.NewReviewRepository(dbPostgres) reviews, err := reviewRepoSqlite.FindAll() if err != nil { diff --git a/job/worker.go b/job/worker.go index 862823d..377202e 100644 --- a/job/worker.go +++ b/job/worker.go @@ -7,18 +7,18 @@ import ( "time" "code.ewintr.nl/emdb/client" - "code.ewintr.nl/emdb/cmd/api-service/moviestore" + "code.ewintr.nl/emdb/storage" ) type Worker struct { jq *JobQueue - movieRepo *moviestore.MovieRepository - reviewRepo *moviestore.ReviewRepository + movieRepo *storage.MovieRepository + reviewRepo *storage.ReviewRepository imdb *client.IMDB logger *slog.Logger } -func NewWorker(jq *JobQueue, movieRepo *moviestore.MovieRepository, reviewRepo *moviestore.ReviewRepository, imdb *client.IMDB, logger *slog.Logger) *Worker { +func NewWorker(jq *JobQueue, movieRepo *storage.MovieRepository, reviewRepo *storage.ReviewRepository, imdb *client.IMDB, logger *slog.Logger) *Worker { return &Worker{ jq: jq, movieRepo: movieRepo, diff --git a/storage/moviepg.go b/storage/movie.go similarity index 70% rename from storage/moviepg.go rename to storage/movie.go index 7d4fd69..87c0408 100644 --- a/storage/moviepg.go +++ b/storage/movie.go @@ -8,17 +8,31 @@ import ( "github.com/google/uuid" ) -type MovieRepositoryPG struct { +type Movie struct { + ID string `json:"id"` + TMDBID int64 `json:"tmdbID"` + IMDBID string `json:"imdbID"` + Title string `json:"title"` + EnglishTitle string `json:"englishTitle"` + Year int `json:"year"` + Directors []string `json:"directors"` + WatchedOn string `json:"watchedOn"` + Rating int `json:"rating"` + Summary string `json:"summary"` + Comment string `json:"comment"` +} + +type MovieRepository struct { db *Postgres } -func NewMovieRepositoryPG(db *Postgres) *MovieRepositoryPG { - return &MovieRepositoryPG{ +func NewMovieRepository(db *Postgres) *MovieRepository { + return &MovieRepository{ db: db, } } -func (mr *MovieRepositoryPG) Store(m moviestore.Movie) error { +func (mr *MovieRepository) Store(m Movie) error { if m.ID == "" { m.ID = uuid.New().String() } @@ -45,7 +59,7 @@ SET return nil } -func (mr *MovieRepositoryPG) Delete(id string) error { +func (mr *MovieRepository) Delete(id string) error { if _, err := mr.db.Exec(`DELETE FROM movie WHERE id=$1`, id); err != nil { return fmt.Errorf("%w: %v", moviestore.ErrSqliteFailure, err) } @@ -53,28 +67,28 @@ func (mr *MovieRepositoryPG) Delete(id string) error { return nil } -func (mr *MovieRepositoryPG) FindOne(id string) (moviestore.Movie, error) { +func (mr *MovieRepository) FindOne(id string) (Movie, error) { row := mr.db.QueryRow(` SELECT id, tmdb_id, imdb_id, title, english_title, year, directors, summary, watched_on, rating, comment FROM movie WHERE id=$1`, id) if row.Err() != nil { - return moviestore.Movie{}, row.Err() + return Movie{}, row.Err() } - m := moviestore.Movie{ + m := Movie{ ID: id, } var directors string if err := row.Scan(&m.ID, &m.TMDBID, &m.IMDBID, &m.Title, &m.EnglishTitle, &m.Year, &directors, &m.Summary, &m.WatchedOn, &m.Rating, &m.Comment); err != nil { - return moviestore.Movie{}, fmt.Errorf("%w: %w", moviestore.ErrSqliteFailure, err) + return Movie{}, fmt.Errorf("%w: %w", moviestore.ErrSqliteFailure, err) } m.Directors = strings.Split(directors, ",") return m, nil } -func (mr *MovieRepositoryPG) FindAll() ([]moviestore.Movie, error) { +func (mr *MovieRepository) FindAll() ([]Movie, error) { rows, err := mr.db.Query(` SELECT id, tmdb_id, imdb_id, title, english_title, year, directors, summary, watched_on, rating, comment FROM movie`) @@ -82,10 +96,10 @@ FROM movie`) return nil, fmt.Errorf("%w: %v", moviestore.ErrSqliteFailure, err) } - movies := make([]moviestore.Movie, 0) + movies := make([]Movie, 0) defer rows.Close() for rows.Next() { - m := moviestore.Movie{} + m := Movie{} var directors string if err := rows.Scan(&m.ID, &m.TMDBID, &m.IMDBID, &m.Title, &m.EnglishTitle, &m.Year, &directors, &m.Summary, &m.WatchedOn, &m.Rating, &m.Comment); err != nil { return nil, fmt.Errorf("%w: %v", moviestore.ErrSqliteFailure, err) diff --git a/storage/reviewpg.go b/storage/reviewpg.go index d67cbdf..fe6c9d1 100644 --- a/storage/reviewpg.go +++ b/storage/reviewpg.go @@ -2,47 +2,45 @@ package storage import ( "encoding/json" - - "code.ewintr.nl/emdb/cmd/api-service/moviestore" ) -//const ( -// ReviewSourceIMDB = "imdb" -// -// MentionsSeparator = "|" -//) -// -//type ReviewSource string -// -//type Titles struct { -// Movies []string `json:"movies"` -// TVShows []string `json:"tvShows"` -// Games []string `json:"games"` -// Books []string `json:"books"` -//} -// -//type Review struct { -// ID string -// MovieID string -// Source ReviewSource -// URL string -// Review string -// MovieRating int -// Quality int -// Titles Titles -//} +const ( + ReviewSourceIMDB = "imdb" -type ReviewRepositoryPG struct { + MentionsSeparator = "|" +) + +type ReviewSource string + +type Titles struct { + Movies []string `json:"movies"` + TVShows []string `json:"tvShows"` + Games []string `json:"games"` + Books []string `json:"books"` +} + +type Review struct { + ID string + MovieID string + Source ReviewSource + URL string + Review string + MovieRating int + Quality int + Titles Titles +} + +type ReviewRepository struct { db *Postgres } -func NewReviewRepositoryPG(db *Postgres) *ReviewRepositoryPG { - return &ReviewRepositoryPG{ +func NewReviewRepository(db *Postgres) *ReviewRepository { + return &ReviewRepository{ db: db, } } -func (rr *ReviewRepositoryPG) Store(r moviestore.Review) error { +func (rr *ReviewRepository) Store(r Review) error { titles, err := json.Marshal(r.Titles) if err != nil { return err @@ -59,28 +57,28 @@ mentioned_titles = EXCLUDED.mentioned_titles;`, return nil } -func (rr *ReviewRepositoryPG) FindOne(id string) (moviestore.Review, error) { +func (rr *ReviewRepository) FindOne(id string) (Review, error) { row := rr.db.QueryRow(` SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles FROM review WHERE id=$1`, id) if row.Err() != nil { - return moviestore.Review{}, row.Err() + return Review{}, row.Err() } - r := moviestore.Review{} + r := Review{} var titles string if err := row.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil { - return moviestore.Review{}, err + return Review{}, err } if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil { - return moviestore.Review{}, err + return Review{}, err } return r, nil } -func (rr *ReviewRepositoryPG) FindByMovieID(movieID string) ([]moviestore.Review, error) { +func (rr *ReviewRepository) FindByMovieID(movieID string) ([]Review, error) { rows, err := rr.db.Query(` SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles FROM review @@ -89,15 +87,15 @@ WHERE movie_id=$1`, movieID) return nil, err } - reviews := make([]moviestore.Review, 0) + reviews := make([]Review, 0) var titles string for rows.Next() { - r := moviestore.Review{} + r := Review{} if err := rows.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil { return nil, err } if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil { - return []moviestore.Review{}, err + return []Review{}, err } reviews = append(reviews, r) } @@ -106,29 +104,29 @@ WHERE movie_id=$1`, movieID) return reviews, nil } -func (rr *ReviewRepositoryPG) FindNextUnrated() (moviestore.Review, error) { +func (rr *ReviewRepository) FindNextUnrated() (Review, error) { row := rr.db.QueryRow(` SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles FROM review WHERE quality=0 LIMIT 1`) if row.Err() != nil { - return moviestore.Review{}, row.Err() + return Review{}, row.Err() } - r := moviestore.Review{} + r := Review{} var titles string if err := row.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil { - return moviestore.Review{}, err + return Review{}, err } if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil { - return moviestore.Review{}, err + return Review{}, err } return r, nil } -func (rr *ReviewRepositoryPG) FindUnrated() ([]moviestore.Review, error) { +func (rr *ReviewRepository) FindUnrated() ([]Review, error) { rows, err := rr.db.Query(` SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles FROM review @@ -137,15 +135,15 @@ WHERE quality=0`) return nil, err } - reviews := make([]moviestore.Review, 0) + reviews := make([]Review, 0) var titles string for rows.Next() { - r := moviestore.Review{} + r := Review{} if err := rows.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil { return nil, err } if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil { - return []moviestore.Review{}, err + return []Review{}, err } reviews = append(reviews, r) } @@ -154,29 +152,29 @@ WHERE quality=0`) return reviews, nil } -func (rr *ReviewRepositoryPG) FindNextNoTitles() (moviestore.Review, error) { +func (rr *ReviewRepository) FindNextNoTitles() (Review, error) { row := rr.db.QueryRow(` SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles FROM review WHERE mentioned_titles='{}' LIMIT 1`) if row.Err() != nil { - return moviestore.Review{}, row.Err() + return Review{}, row.Err() } - r := moviestore.Review{} + r := Review{} var titles string if err := row.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil { - return moviestore.Review{}, err + return Review{}, err } if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil { - return moviestore.Review{}, err + return Review{}, err } return r, nil } -func (rr *ReviewRepositoryPG) FindNoTitles() ([]moviestore.Review, error) { +func (rr *ReviewRepository) FindNoTitles() ([]Review, error) { rows, err := rr.db.Query(` SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles FROM review @@ -185,15 +183,15 @@ WHERE mentioned_titles='{}'`) return nil, err } - reviews := make([]moviestore.Review, 0) + reviews := make([]Review, 0) var titles string for rows.Next() { - r := moviestore.Review{} + r := Review{} if err := rows.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil { return nil, err } if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil { - return []moviestore.Review{}, err + return []Review{}, err } reviews = append(reviews, r) } @@ -202,7 +200,7 @@ WHERE mentioned_titles='{}'`) return reviews, nil } -func (rr *ReviewRepositoryPG) FindAll() ([]moviestore.Review, error) { +func (rr *ReviewRepository) FindAll() ([]Review, error) { rows, err := rr.db.Query(` SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles FROM review`) @@ -210,15 +208,15 @@ FROM review`) return nil, err } - reviews := make([]moviestore.Review, 0) + reviews := make([]Review, 0) var titles string for rows.Next() { - r := moviestore.Review{} + r := Review{} if err := rows.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil { return nil, err } if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil { - return []moviestore.Review{}, err + return []Review{}, err } reviews = append(reviews, r) } @@ -227,7 +225,7 @@ FROM review`) return reviews, nil } -func (rr *ReviewRepositoryPG) DeleteByMovieID(id string) error { +func (rr *ReviewRepository) DeleteByMovieID(id string) error { if _, err := rr.db.Exec(`DELETE FROM review WHERE movie_id=$1`, id); err != nil { return err } diff --git a/terminal-client/main.go b/terminal-client/main.go index 709c46c..0b52e19 100644 --- a/terminal-client/main.go +++ b/terminal-client/main.go @@ -30,8 +30,8 @@ func main() { fmt.Printf("could not create new postgres repo: %s", err.Error()) os.Exit(1) } - movieRepo := storage.NewMovieRepositoryPG(dbPostgres) - reviewRepo := storage.NewReviewRepositoryPG(dbPostgres) + movieRepo := storage.NewMovieRepository(dbPostgres) + reviewRepo := storage.NewReviewRepository(dbPostgres) jobQueue := job.NewJobQueue(dbPostgres, logger) p, err := tui.New(movieRepo, reviewRepo, jobQueue, tmdb, tuiLogger) diff --git a/terminal-client/tui/basemodel.go b/terminal-client/tui/basemodel.go index 56ee6c3..0f57b73 100644 --- a/terminal-client/tui/basemodel.go +++ b/terminal-client/tui/basemodel.go @@ -12,8 +12,8 @@ import ( ) type baseModel struct { - movieRepo *storage.MovieRepositoryPG - reviewRepo *storage.ReviewRepositoryPG + movieRepo *storage.MovieRepository + reviewRepo *storage.ReviewRepository jobQueue *job.JobQueue tmdb *client.TMDB tabs *TabSet @@ -24,7 +24,7 @@ type baseModel struct { contentSize tea.WindowSizeMsg } -func NewBaseModel(movieRepo *storage.MovieRepositoryPG, reviewRepo *storage.ReviewRepositoryPG, jobQueue *job.JobQueue, tmdb *client.TMDB, logger *Logger) (tea.Model, tea.Cmd) { +func NewBaseModel(movieRepo *storage.MovieRepository, reviewRepo *storage.ReviewRepository, jobQueue *job.JobQueue, tmdb *client.TMDB, logger *Logger) (tea.Model, tea.Cmd) { logViewport := viewport.New(0, 0) logViewport.KeyMap = viewport.KeyMap{} diff --git a/terminal-client/tui/movie.go b/terminal-client/tui/movie.go index 9ecf2b0..7f89cc6 100644 --- a/terminal-client/tui/movie.go +++ b/terminal-client/tui/movie.go @@ -3,12 +3,12 @@ package tui import ( "fmt" - "code.ewintr.nl/emdb/cmd/api-service/moviestore" + "code.ewintr.nl/emdb/storage" "github.com/charmbracelet/bubbles/list" ) type Movie struct { - m moviestore.Movie + m storage.Movie } func (m Movie) FilterValue() string { @@ -23,7 +23,7 @@ func (m Movie) Description() string { return fmt.Sprintf("%s", m.m.Summary) } -type Movies []moviestore.Movie +type Movies []storage.Movie func (ms Movies) listItems() []list.Item { items := []list.Item{} diff --git a/terminal-client/tui/tabemdb.go b/terminal-client/tui/tabemdb.go index a52aeb6..3347b1d 100644 --- a/terminal-client/tui/tabemdb.go +++ b/terminal-client/tui/tabemdb.go @@ -24,7 +24,7 @@ type StoredMovie struct{} type tabEMDB struct { initialized bool - movieRepo *storage.MovieRepositoryPG + movieRepo *storage.MovieRepository mode string focused string colWidth int @@ -38,7 +38,7 @@ type tabEMDB struct { logger *Logger } -func NewTabEMDB(movieRepo *storage.MovieRepositoryPG, logger *Logger) (tea.Model, tea.Cmd) { +func NewTabEMDB(movieRepo *storage.MovieRepository, logger *Logger) (tea.Model, tea.Cmd) { del := list.NewDefaultDelegate() list := list.New([]list.Item{}, del, 0, 0) list.Title = "Movies" @@ -276,7 +276,7 @@ func (m *tabEMDB) Log(s string) { m.logger.Log(s) } -func FetchMovieList(movieRepo *storage.MovieRepositoryPG) tea.Cmd { +func FetchMovieList(movieRepo *storage.MovieRepository) tea.Cmd { return func() tea.Msg { ems, err := movieRepo.FindAll() if err != nil { diff --git a/terminal-client/tui/tabreview.go b/terminal-client/tui/tabreview.go index 288ee61..cca199a 100644 --- a/terminal-client/tui/tabreview.go +++ b/terminal-client/tui/tabreview.go @@ -5,7 +5,6 @@ import ( "strconv" "strings" - "code.ewintr.nl/emdb/cmd/api-service/moviestore" "code.ewintr.nl/emdb/storage" "github.com/charmbracelet/bubbles/textarea" "github.com/charmbracelet/bubbles/textinput" @@ -16,11 +15,11 @@ import ( type tabReview struct { initialized bool - reviewRepo *storage.ReviewRepositoryPG + reviewRepo *storage.ReviewRepository width int height int mode string - selectedReview moviestore.Review + selectedReview storage.Review reviewViewport viewport.Model inputQuality textinput.Model inputMentions textarea.Model @@ -28,7 +27,7 @@ type tabReview struct { logger *Logger } -func NewTabReview(reviewRepo *storage.ReviewRepositoryPG, logger *Logger) (tea.Model, tea.Cmd) { +func NewTabReview(reviewRepo *storage.ReviewRepository, logger *Logger) (tea.Model, tea.Cmd) { reviewViewport := viewport.New(0, 0) //reviewViewport.KeyMap = viewport.KeyMap{} @@ -104,7 +103,7 @@ func (m *tabReview) Update(msg tea.Msg) (tea.Model, tea.Cmd) { cmds = append(cmds, cmd) } } - case moviestore.Review: + case storage.Review: m.logger.Log(fmt.Sprintf("got review %s", msg.ID)) m.selectedReview = msg review := strings.ReplaceAll(m.selectedReview.Review, "\n", "\n\n") @@ -218,7 +217,7 @@ func (m *tabReview) StoreReview() tea.Cmd { } } -func FetchNextUnratedReview(reviewRepo *storage.ReviewRepositoryPG) tea.Cmd { +func FetchNextUnratedReview(reviewRepo *storage.ReviewRepository) tea.Cmd { return func() tea.Msg { review, err := reviewRepo.FindNextUnrated() if err != nil { diff --git a/terminal-client/tui/tabtmdb.go b/terminal-client/tui/tabtmdb.go index 050b2c5..0e5a8eb 100644 --- a/terminal-client/tui/tabtmdb.go +++ b/terminal-client/tui/tabtmdb.go @@ -12,7 +12,7 @@ import ( ) type tabTMDB struct { - movieRepo *storage.MovieRepositoryPG + movieRepo *storage.MovieRepository jobQueue *job.JobQueue tmdb *client.TMDB initialized bool @@ -22,7 +22,7 @@ type tabTMDB struct { logger *Logger } -func NewTabTMDB(movieRepo *storage.MovieRepositoryPG, jobQueue *job.JobQueue, tmdb *client.TMDB, logger *Logger) (tea.Model, tea.Cmd) { +func NewTabTMDB(movieRepo *storage.MovieRepository, jobQueue *job.JobQueue, tmdb *client.TMDB, logger *Logger) (tea.Model, tea.Cmd) { m := tabTMDB{ movieRepo: movieRepo, jobQueue: jobQueue, diff --git a/terminal-client/tui/tui.go b/terminal-client/tui/tui.go index b72a7b6..264f4e1 100644 --- a/terminal-client/tui/tui.go +++ b/terminal-client/tui/tui.go @@ -52,7 +52,7 @@ func SelectPrevTab() tea.Cmd { } } -func New(movieRepo *storage.MovieRepositoryPG, reviewRepo *storage.ReviewRepositoryPG, jobQueue *job.JobQueue, tmdb *client.TMDB, logger *Logger) (*tea.Program, error) { +func New(movieRepo *storage.MovieRepository, reviewRepo *storage.ReviewRepository, jobQueue *job.JobQueue, tmdb *client.TMDB, logger *Logger) (*tea.Program, error) { logViewport := viewport.New(0, 0) logViewport.KeyMap = viewport.KeyMap{}