remove sqlite
This commit is contained in:
parent
72e91d27ed
commit
987a83e760
|
@ -7,7 +7,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.ewintr.nl/emdb/cmd/api-service/moviestore"
|
"code.ewintr.nl/emdb/storage"
|
||||||
"github.com/PuerkitoBio/goquery"
|
"github.com/PuerkitoBio/goquery"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
@ -19,7 +19,7 @@ func NewIMDB() *IMDB {
|
||||||
return &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)
|
url := fmt.Sprintf("https://www.imdb.com/title/%s/reviews", m.IMDBID)
|
||||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -40,7 +40,7 @@ func (i *IMDB) GetReviews(m moviestore.Movie) ([]moviestore.Review, error) {
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
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) {
|
doc.Find(".lister-item-content").Each(func(i int, reviewNode *goquery.Selection) {
|
||||||
|
|
||||||
var permaLink string
|
var permaLink string
|
||||||
|
@ -58,10 +58,10 @@ func (i *IMDB) GetReviews(m moviestore.Movie) ([]moviestore.Review, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rat, rev := ScrubIMDBReview(reviewNode.Text())
|
rat, rev := ScrubIMDBReview(reviewNode.Text())
|
||||||
reviews = append(reviews, moviestore.Review{
|
reviews = append(reviews, storage.Review{
|
||||||
ID: uuid.New().String(),
|
ID: uuid.New().String(),
|
||||||
MovieID: m.ID,
|
MovieID: m.ID,
|
||||||
Source: moviestore.ReviewSourceIMDB,
|
Source: storage.ReviewSourceIMDB,
|
||||||
URL: fmt.Sprintf("https://www.imdb.com%s", permaLink),
|
URL: fmt.Sprintf("https://www.imdb.com%s", permaLink),
|
||||||
Review: rev,
|
Review: rev,
|
||||||
MovieRating: rat,
|
MovieRating: rat,
|
||||||
|
|
|
@ -3,7 +3,7 @@ package client
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.ewintr.nl/emdb/cmd/api-service/moviestore"
|
"code.ewintr.nl/emdb/storage"
|
||||||
tmdb "github.com/cyruzin/golang-tmdb"
|
tmdb "github.com/cyruzin/golang-tmdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -24,13 +24,13 @@ func NewTMDB(apikey string) (*TMDB, error) {
|
||||||
}, nil
|
}, 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)
|
results, err := t.c.GetSearchMovies(query, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
movies := make([]moviestore.Movie, len(results.Results))
|
movies := make([]storage.Movie, len(results.Results))
|
||||||
for i, result := range results.Results {
|
for i, result := range results.Results {
|
||||||
movies[i], err = t.GetMovie(result.ID)
|
movies[i], err = t.GetMovie(result.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -41,12 +41,12 @@ func (t TMDB) Search(query string) ([]moviestore.Movie, error) {
|
||||||
return movies, nil
|
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{
|
result, err := t.c.GetMovieDetails(int(id), map[string]string{
|
||||||
"append_to_response": "credits",
|
"append_to_response": "credits",
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return moviestore.Movie{}, err
|
return storage.Movie{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var year int
|
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,
|
Title: result.OriginalTitle,
|
||||||
EnglishTitle: result.Title,
|
EnglishTitle: result.Title,
|
||||||
TMDBID: result.ID,
|
TMDBID: result.ID,
|
||||||
|
|
|
@ -10,19 +10,19 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.ewintr.nl/emdb/cmd/api-service/moviestore"
|
|
||||||
"code.ewintr.nl/emdb/job"
|
"code.ewintr.nl/emdb/job"
|
||||||
|
"code.ewintr.nl/emdb/storage"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MovieAPI struct {
|
type MovieAPI struct {
|
||||||
apis APIIndex
|
apis APIIndex
|
||||||
repo *moviestore.MovieRepository
|
repo *storage.MovieRepository
|
||||||
jq *job.JobQueue
|
jq *job.JobQueue
|
||||||
logger *slog.Logger
|
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{
|
return &MovieAPI{
|
||||||
apis: apis,
|
apis: apis,
|
||||||
repo: repo,
|
repo: repo,
|
||||||
|
@ -93,7 +93,7 @@ func (movieAPI *MovieAPI) Store(w http.ResponseWriter, r *http.Request, urlID st
|
||||||
}
|
}
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
|
|
||||||
var m moviestore.Movie
|
var m storage.Movie
|
||||||
if err := json.Unmarshal(body, &m); err != nil {
|
if err := json.Unmarshal(body, &m); err != nil {
|
||||||
Error(w, http.StatusBadRequest, "could not unmarshal request body", err, logger)
|
Error(w, http.StatusBadRequest, "could not unmarshal request body", err, logger)
|
||||||
return
|
return
|
||||||
|
|
|
@ -6,15 +6,15 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.ewintr.nl/emdb/cmd/api-service/moviestore"
|
"code.ewintr.nl/emdb/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MovieReviewAPI struct {
|
type MovieReviewAPI struct {
|
||||||
repo *moviestore.ReviewRepository
|
repo *storage.ReviewRepository
|
||||||
logger *slog.Logger
|
logger *slog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMovieReviewAPI(repo *moviestore.ReviewRepository, logger *slog.Logger) *MovieReviewAPI {
|
func NewMovieReviewAPI(repo *storage.ReviewRepository, logger *slog.Logger) *MovieReviewAPI {
|
||||||
return &MovieReviewAPI{
|
return &MovieReviewAPI{
|
||||||
repo: repo,
|
repo: repo,
|
||||||
logger: logger.With("api", "moviereview"),
|
logger: logger.With("api", "moviereview"),
|
||||||
|
|
|
@ -6,15 +6,15 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"code.ewintr.nl/emdb/cmd/api-service/moviestore"
|
"code.ewintr.nl/emdb/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ReviewAPI struct {
|
type ReviewAPI struct {
|
||||||
repo *moviestore.ReviewRepository
|
repo *storage.ReviewRepository
|
||||||
logger *slog.Logger
|
logger *slog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewReviewAPI(repo *moviestore.ReviewRepository, logger *slog.Logger) *ReviewAPI {
|
func NewReviewAPI(repo *storage.ReviewRepository, logger *slog.Logger) *ReviewAPI {
|
||||||
return &ReviewAPI{
|
return &ReviewAPI{
|
||||||
repo: repo,
|
repo: repo,
|
||||||
logger: logger.With("api", "review"),
|
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) {
|
func (reviewAPI *ReviewAPI) Store(w http.ResponseWriter, r *http.Request, id string) {
|
||||||
logger := reviewAPI.logger.With("method", "store")
|
logger := reviewAPI.logger.With("method", "store")
|
||||||
|
|
||||||
var review moviestore.Review
|
var review storage.Review
|
||||||
if err := json.NewDecoder(r.Body).Decode(&review); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&review); err != nil {
|
||||||
Error(w, http.StatusBadRequest, "could not decode review", err, logger)
|
Error(w, http.StatusBadRequest, "could not decode review", err, logger)
|
||||||
return
|
return
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"code.ewintr.nl/emdb/cmd/api-service/handler"
|
"code.ewintr.nl/emdb/cmd/api-service/handler"
|
||||||
"code.ewintr.nl/emdb/cmd/api-service/moviestore"
|
"code.ewintr.nl/emdb/cmd/api-service/moviestore"
|
||||||
job2 "code.ewintr.nl/emdb/job"
|
job2 "code.ewintr.nl/emdb/job"
|
||||||
|
"code.ewintr.nl/emdb/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -33,15 +34,15 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
jobQueue := job2.NewJobQueue(db, logger)
|
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()
|
go worker.Run()
|
||||||
|
|
||||||
apis := handler.APIIndex{
|
apis := handler.APIIndex{
|
||||||
"job": handler.NewJobAPI(jobQueue, logger),
|
"job": handler.NewJobAPI(jobQueue, logger),
|
||||||
"movie": handler.NewMovieAPI(handler.APIIndex{
|
"movie": handler.NewMovieAPI(handler.APIIndex{
|
||||||
"review": handler.NewMovieReviewAPI(moviestore.NewReviewRepository(db), logger),
|
"review": handler.NewMovieReviewAPI(storage.NewReviewRepository(db), logger),
|
||||||
}, moviestore.NewMovieRepository(db), jobQueue, logger),
|
}, storage.NewMovieRepository(db), jobQueue, logger),
|
||||||
"review": handler.NewReviewAPI(moviestore.NewReviewRepository(db), logger),
|
"review": handler.NewReviewAPI(storage.NewReviewRepository(db), logger),
|
||||||
}
|
}
|
||||||
|
|
||||||
go http.ListenAndServe(fmt.Sprintf(":%d", *port), handler.NewServer(*apiKey, apis, logger))
|
go http.ListenAndServe(fmt.Sprintf(":%d", *port), handler.NewServer(*apiKey, apis, logger))
|
||||||
|
|
|
@ -38,8 +38,8 @@ func main() {
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
fmt.Println("reviews")
|
fmt.Println("reviews")
|
||||||
reviewRepoSqlite := moviestore.NewReviewRepository(dbSQLite)
|
reviewRepoSqlite := storage.NewReviewRepository(dbSQLite)
|
||||||
reviewRepoPG := storage.NewReviewRepositoryPG(dbPostgres)
|
reviewRepoPG := storage.NewReviewRepository(dbPostgres)
|
||||||
|
|
||||||
reviews, err := reviewRepoSqlite.FindAll()
|
reviews, err := reviewRepoSqlite.FindAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -7,18 +7,18 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.ewintr.nl/emdb/client"
|
"code.ewintr.nl/emdb/client"
|
||||||
"code.ewintr.nl/emdb/cmd/api-service/moviestore"
|
"code.ewintr.nl/emdb/storage"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Worker struct {
|
type Worker struct {
|
||||||
jq *JobQueue
|
jq *JobQueue
|
||||||
movieRepo *moviestore.MovieRepository
|
movieRepo *storage.MovieRepository
|
||||||
reviewRepo *moviestore.ReviewRepository
|
reviewRepo *storage.ReviewRepository
|
||||||
imdb *client.IMDB
|
imdb *client.IMDB
|
||||||
logger *slog.Logger
|
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{
|
return &Worker{
|
||||||
jq: jq,
|
jq: jq,
|
||||||
movieRepo: movieRepo,
|
movieRepo: movieRepo,
|
||||||
|
|
|
@ -8,17 +8,31 @@ import (
|
||||||
"github.com/google/uuid"
|
"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
|
db *Postgres
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMovieRepositoryPG(db *Postgres) *MovieRepositoryPG {
|
func NewMovieRepository(db *Postgres) *MovieRepository {
|
||||||
return &MovieRepositoryPG{
|
return &MovieRepository{
|
||||||
db: db,
|
db: db,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mr *MovieRepositoryPG) Store(m moviestore.Movie) error {
|
func (mr *MovieRepository) Store(m Movie) error {
|
||||||
if m.ID == "" {
|
if m.ID == "" {
|
||||||
m.ID = uuid.New().String()
|
m.ID = uuid.New().String()
|
||||||
}
|
}
|
||||||
|
@ -45,7 +59,7 @@ SET
|
||||||
return nil
|
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 {
|
if _, err := mr.db.Exec(`DELETE FROM movie WHERE id=$1`, id); err != nil {
|
||||||
return fmt.Errorf("%w: %v", moviestore.ErrSqliteFailure, err)
|
return fmt.Errorf("%w: %v", moviestore.ErrSqliteFailure, err)
|
||||||
}
|
}
|
||||||
|
@ -53,28 +67,28 @@ func (mr *MovieRepositoryPG) Delete(id string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mr *MovieRepositoryPG) FindOne(id string) (moviestore.Movie, error) {
|
func (mr *MovieRepository) FindOne(id string) (Movie, error) {
|
||||||
row := mr.db.QueryRow(`
|
row := mr.db.QueryRow(`
|
||||||
SELECT id, tmdb_id, imdb_id, title, english_title, year, directors, summary, watched_on, rating, comment
|
SELECT id, tmdb_id, imdb_id, title, english_title, year, directors, summary, watched_on, rating, comment
|
||||||
FROM movie
|
FROM movie
|
||||||
WHERE id=$1`, id)
|
WHERE id=$1`, id)
|
||||||
if row.Err() != nil {
|
if row.Err() != nil {
|
||||||
return moviestore.Movie{}, row.Err()
|
return Movie{}, row.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
m := moviestore.Movie{
|
m := Movie{
|
||||||
ID: id,
|
ID: id,
|
||||||
}
|
}
|
||||||
var directors string
|
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 {
|
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, ",")
|
m.Directors = strings.Split(directors, ",")
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mr *MovieRepositoryPG) FindAll() ([]moviestore.Movie, error) {
|
func (mr *MovieRepository) FindAll() ([]Movie, error) {
|
||||||
rows, err := mr.db.Query(`
|
rows, err := mr.db.Query(`
|
||||||
SELECT id, tmdb_id, imdb_id, title, english_title, year, directors, summary, watched_on, rating, comment
|
SELECT id, tmdb_id, imdb_id, title, english_title, year, directors, summary, watched_on, rating, comment
|
||||||
FROM movie`)
|
FROM movie`)
|
||||||
|
@ -82,10 +96,10 @@ FROM movie`)
|
||||||
return nil, fmt.Errorf("%w: %v", moviestore.ErrSqliteFailure, err)
|
return nil, fmt.Errorf("%w: %v", moviestore.ErrSqliteFailure, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
movies := make([]moviestore.Movie, 0)
|
movies := make([]Movie, 0)
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
m := moviestore.Movie{}
|
m := Movie{}
|
||||||
var directors string
|
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 {
|
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)
|
return nil, fmt.Errorf("%w: %v", moviestore.ErrSqliteFailure, err)
|
|
@ -2,47 +2,45 @@ package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"code.ewintr.nl/emdb/cmd/api-service/moviestore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
//const (
|
const (
|
||||||
// ReviewSourceIMDB = "imdb"
|
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 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
|
db *Postgres
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewReviewRepositoryPG(db *Postgres) *ReviewRepositoryPG {
|
func NewReviewRepository(db *Postgres) *ReviewRepository {
|
||||||
return &ReviewRepositoryPG{
|
return &ReviewRepository{
|
||||||
db: db,
|
db: db,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *ReviewRepositoryPG) Store(r moviestore.Review) error {
|
func (rr *ReviewRepository) Store(r Review) error {
|
||||||
titles, err := json.Marshal(r.Titles)
|
titles, err := json.Marshal(r.Titles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -59,28 +57,28 @@ mentioned_titles = EXCLUDED.mentioned_titles;`,
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *ReviewRepositoryPG) FindOne(id string) (moviestore.Review, error) {
|
func (rr *ReviewRepository) FindOne(id string) (Review, error) {
|
||||||
row := rr.db.QueryRow(`
|
row := rr.db.QueryRow(`
|
||||||
SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles
|
SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles
|
||||||
FROM review
|
FROM review
|
||||||
WHERE id=$1`, id)
|
WHERE id=$1`, id)
|
||||||
if row.Err() != nil {
|
if row.Err() != nil {
|
||||||
return moviestore.Review{}, row.Err()
|
return Review{}, row.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
r := moviestore.Review{}
|
r := Review{}
|
||||||
var titles string
|
var titles string
|
||||||
if err := row.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil {
|
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 {
|
if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil {
|
||||||
return moviestore.Review{}, err
|
return Review{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return r, nil
|
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(`
|
rows, err := rr.db.Query(`
|
||||||
SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles
|
SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles
|
||||||
FROM review
|
FROM review
|
||||||
|
@ -89,15 +87,15 @@ WHERE movie_id=$1`, movieID)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
reviews := make([]moviestore.Review, 0)
|
reviews := make([]Review, 0)
|
||||||
var titles string
|
var titles string
|
||||||
for rows.Next() {
|
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 {
|
if err := rows.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil {
|
if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil {
|
||||||
return []moviestore.Review{}, err
|
return []Review{}, err
|
||||||
}
|
}
|
||||||
reviews = append(reviews, r)
|
reviews = append(reviews, r)
|
||||||
}
|
}
|
||||||
|
@ -106,29 +104,29 @@ WHERE movie_id=$1`, movieID)
|
||||||
return reviews, nil
|
return reviews, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *ReviewRepositoryPG) FindNextUnrated() (moviestore.Review, error) {
|
func (rr *ReviewRepository) FindNextUnrated() (Review, error) {
|
||||||
row := rr.db.QueryRow(`
|
row := rr.db.QueryRow(`
|
||||||
SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles
|
SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles
|
||||||
FROM review
|
FROM review
|
||||||
WHERE quality=0
|
WHERE quality=0
|
||||||
LIMIT 1`)
|
LIMIT 1`)
|
||||||
if row.Err() != nil {
|
if row.Err() != nil {
|
||||||
return moviestore.Review{}, row.Err()
|
return Review{}, row.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
r := moviestore.Review{}
|
r := Review{}
|
||||||
var titles string
|
var titles string
|
||||||
if err := row.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil {
|
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 {
|
if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil {
|
||||||
return moviestore.Review{}, err
|
return Review{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *ReviewRepositoryPG) FindUnrated() ([]moviestore.Review, error) {
|
func (rr *ReviewRepository) FindUnrated() ([]Review, error) {
|
||||||
rows, err := rr.db.Query(`
|
rows, err := rr.db.Query(`
|
||||||
SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles
|
SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles
|
||||||
FROM review
|
FROM review
|
||||||
|
@ -137,15 +135,15 @@ WHERE quality=0`)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
reviews := make([]moviestore.Review, 0)
|
reviews := make([]Review, 0)
|
||||||
var titles string
|
var titles string
|
||||||
for rows.Next() {
|
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 {
|
if err := rows.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil {
|
if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil {
|
||||||
return []moviestore.Review{}, err
|
return []Review{}, err
|
||||||
}
|
}
|
||||||
reviews = append(reviews, r)
|
reviews = append(reviews, r)
|
||||||
}
|
}
|
||||||
|
@ -154,29 +152,29 @@ WHERE quality=0`)
|
||||||
return reviews, nil
|
return reviews, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *ReviewRepositoryPG) FindNextNoTitles() (moviestore.Review, error) {
|
func (rr *ReviewRepository) FindNextNoTitles() (Review, error) {
|
||||||
row := rr.db.QueryRow(`
|
row := rr.db.QueryRow(`
|
||||||
SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles
|
SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles
|
||||||
FROM review
|
FROM review
|
||||||
WHERE mentioned_titles='{}'
|
WHERE mentioned_titles='{}'
|
||||||
LIMIT 1`)
|
LIMIT 1`)
|
||||||
if row.Err() != nil {
|
if row.Err() != nil {
|
||||||
return moviestore.Review{}, row.Err()
|
return Review{}, row.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
r := moviestore.Review{}
|
r := Review{}
|
||||||
var titles string
|
var titles string
|
||||||
if err := row.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil {
|
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 {
|
if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil {
|
||||||
return moviestore.Review{}, err
|
return Review{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *ReviewRepositoryPG) FindNoTitles() ([]moviestore.Review, error) {
|
func (rr *ReviewRepository) FindNoTitles() ([]Review, error) {
|
||||||
rows, err := rr.db.Query(`
|
rows, err := rr.db.Query(`
|
||||||
SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles
|
SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles
|
||||||
FROM review
|
FROM review
|
||||||
|
@ -185,15 +183,15 @@ WHERE mentioned_titles='{}'`)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
reviews := make([]moviestore.Review, 0)
|
reviews := make([]Review, 0)
|
||||||
var titles string
|
var titles string
|
||||||
for rows.Next() {
|
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 {
|
if err := rows.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil {
|
if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil {
|
||||||
return []moviestore.Review{}, err
|
return []Review{}, err
|
||||||
}
|
}
|
||||||
reviews = append(reviews, r)
|
reviews = append(reviews, r)
|
||||||
}
|
}
|
||||||
|
@ -202,7 +200,7 @@ WHERE mentioned_titles='{}'`)
|
||||||
return reviews, nil
|
return reviews, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rr *ReviewRepositoryPG) FindAll() ([]moviestore.Review, error) {
|
func (rr *ReviewRepository) FindAll() ([]Review, error) {
|
||||||
rows, err := rr.db.Query(`
|
rows, err := rr.db.Query(`
|
||||||
SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles
|
SELECT id, movie_id, source, url, review, movie_rating, quality, mentioned_titles
|
||||||
FROM review`)
|
FROM review`)
|
||||||
|
@ -210,15 +208,15 @@ FROM review`)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
reviews := make([]moviestore.Review, 0)
|
reviews := make([]Review, 0)
|
||||||
var titles string
|
var titles string
|
||||||
for rows.Next() {
|
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 {
|
if err := rows.Scan(&r.ID, &r.MovieID, &r.Source, &r.URL, &r.Review, &r.MovieRating, &r.Quality, &titles); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil {
|
if err := json.Unmarshal([]byte(titles), &r.Titles); err != nil {
|
||||||
return []moviestore.Review{}, err
|
return []Review{}, err
|
||||||
}
|
}
|
||||||
reviews = append(reviews, r)
|
reviews = append(reviews, r)
|
||||||
}
|
}
|
||||||
|
@ -227,7 +225,7 @@ FROM review`)
|
||||||
return reviews, nil
|
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 {
|
if _, err := rr.db.Exec(`DELETE FROM review WHERE movie_id=$1`, id); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,8 +30,8 @@ func main() {
|
||||||
fmt.Printf("could not create new postgres repo: %s", err.Error())
|
fmt.Printf("could not create new postgres repo: %s", err.Error())
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
movieRepo := storage.NewMovieRepositoryPG(dbPostgres)
|
movieRepo := storage.NewMovieRepository(dbPostgres)
|
||||||
reviewRepo := storage.NewReviewRepositoryPG(dbPostgres)
|
reviewRepo := storage.NewReviewRepository(dbPostgres)
|
||||||
jobQueue := job.NewJobQueue(dbPostgres, logger)
|
jobQueue := job.NewJobQueue(dbPostgres, logger)
|
||||||
|
|
||||||
p, err := tui.New(movieRepo, reviewRepo, jobQueue, tmdb, tuiLogger)
|
p, err := tui.New(movieRepo, reviewRepo, jobQueue, tmdb, tuiLogger)
|
||||||
|
|
|
@ -12,8 +12,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type baseModel struct {
|
type baseModel struct {
|
||||||
movieRepo *storage.MovieRepositoryPG
|
movieRepo *storage.MovieRepository
|
||||||
reviewRepo *storage.ReviewRepositoryPG
|
reviewRepo *storage.ReviewRepository
|
||||||
jobQueue *job.JobQueue
|
jobQueue *job.JobQueue
|
||||||
tmdb *client.TMDB
|
tmdb *client.TMDB
|
||||||
tabs *TabSet
|
tabs *TabSet
|
||||||
|
@ -24,7 +24,7 @@ type baseModel struct {
|
||||||
contentSize tea.WindowSizeMsg
|
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 := viewport.New(0, 0)
|
||||||
logViewport.KeyMap = viewport.KeyMap{}
|
logViewport.KeyMap = viewport.KeyMap{}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,12 @@ package tui
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.ewintr.nl/emdb/cmd/api-service/moviestore"
|
"code.ewintr.nl/emdb/storage"
|
||||||
"github.com/charmbracelet/bubbles/list"
|
"github.com/charmbracelet/bubbles/list"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Movie struct {
|
type Movie struct {
|
||||||
m moviestore.Movie
|
m storage.Movie
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Movie) FilterValue() string {
|
func (m Movie) FilterValue() string {
|
||||||
|
@ -23,7 +23,7 @@ func (m Movie) Description() string {
|
||||||
return fmt.Sprintf("%s", m.m.Summary)
|
return fmt.Sprintf("%s", m.m.Summary)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Movies []moviestore.Movie
|
type Movies []storage.Movie
|
||||||
|
|
||||||
func (ms Movies) listItems() []list.Item {
|
func (ms Movies) listItems() []list.Item {
|
||||||
items := []list.Item{}
|
items := []list.Item{}
|
||||||
|
|
|
@ -24,7 +24,7 @@ type StoredMovie struct{}
|
||||||
|
|
||||||
type tabEMDB struct {
|
type tabEMDB struct {
|
||||||
initialized bool
|
initialized bool
|
||||||
movieRepo *storage.MovieRepositoryPG
|
movieRepo *storage.MovieRepository
|
||||||
mode string
|
mode string
|
||||||
focused string
|
focused string
|
||||||
colWidth int
|
colWidth int
|
||||||
|
@ -38,7 +38,7 @@ type tabEMDB struct {
|
||||||
logger *Logger
|
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()
|
del := list.NewDefaultDelegate()
|
||||||
list := list.New([]list.Item{}, del, 0, 0)
|
list := list.New([]list.Item{}, del, 0, 0)
|
||||||
list.Title = "Movies"
|
list.Title = "Movies"
|
||||||
|
@ -276,7 +276,7 @@ func (m *tabEMDB) Log(s string) {
|
||||||
m.logger.Log(s)
|
m.logger.Log(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func FetchMovieList(movieRepo *storage.MovieRepositoryPG) tea.Cmd {
|
func FetchMovieList(movieRepo *storage.MovieRepository) tea.Cmd {
|
||||||
return func() tea.Msg {
|
return func() tea.Msg {
|
||||||
ems, err := movieRepo.FindAll()
|
ems, err := movieRepo.FindAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.ewintr.nl/emdb/cmd/api-service/moviestore"
|
|
||||||
"code.ewintr.nl/emdb/storage"
|
"code.ewintr.nl/emdb/storage"
|
||||||
"github.com/charmbracelet/bubbles/textarea"
|
"github.com/charmbracelet/bubbles/textarea"
|
||||||
"github.com/charmbracelet/bubbles/textinput"
|
"github.com/charmbracelet/bubbles/textinput"
|
||||||
|
@ -16,11 +15,11 @@ import (
|
||||||
|
|
||||||
type tabReview struct {
|
type tabReview struct {
|
||||||
initialized bool
|
initialized bool
|
||||||
reviewRepo *storage.ReviewRepositoryPG
|
reviewRepo *storage.ReviewRepository
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
mode string
|
mode string
|
||||||
selectedReview moviestore.Review
|
selectedReview storage.Review
|
||||||
reviewViewport viewport.Model
|
reviewViewport viewport.Model
|
||||||
inputQuality textinput.Model
|
inputQuality textinput.Model
|
||||||
inputMentions textarea.Model
|
inputMentions textarea.Model
|
||||||
|
@ -28,7 +27,7 @@ type tabReview struct {
|
||||||
logger *Logger
|
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 := viewport.New(0, 0)
|
||||||
//reviewViewport.KeyMap = viewport.KeyMap{}
|
//reviewViewport.KeyMap = viewport.KeyMap{}
|
||||||
|
|
||||||
|
@ -104,7 +103,7 @@ func (m *tabReview) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
cmds = append(cmds, cmd)
|
cmds = append(cmds, cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case moviestore.Review:
|
case storage.Review:
|
||||||
m.logger.Log(fmt.Sprintf("got review %s", msg.ID))
|
m.logger.Log(fmt.Sprintf("got review %s", msg.ID))
|
||||||
m.selectedReview = msg
|
m.selectedReview = msg
|
||||||
review := strings.ReplaceAll(m.selectedReview.Review, "\n", "\n\n")
|
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 {
|
return func() tea.Msg {
|
||||||
review, err := reviewRepo.FindNextUnrated()
|
review, err := reviewRepo.FindNextUnrated()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type tabTMDB struct {
|
type tabTMDB struct {
|
||||||
movieRepo *storage.MovieRepositoryPG
|
movieRepo *storage.MovieRepository
|
||||||
jobQueue *job.JobQueue
|
jobQueue *job.JobQueue
|
||||||
tmdb *client.TMDB
|
tmdb *client.TMDB
|
||||||
initialized bool
|
initialized bool
|
||||||
|
@ -22,7 +22,7 @@ type tabTMDB struct {
|
||||||
logger *Logger
|
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{
|
m := tabTMDB{
|
||||||
movieRepo: movieRepo,
|
movieRepo: movieRepo,
|
||||||
jobQueue: jobQueue,
|
jobQueue: jobQueue,
|
||||||
|
|
|
@ -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 := viewport.New(0, 0)
|
||||||
logViewport.KeyMap = viewport.KeyMap{}
|
logViewport.KeyMap = viewport.KeyMap{}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue