diff --git a/package.json b/package.json
index b7fb322..f8f40e3 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,7 @@
"dependencies": {
"babel-polyfill": "^6.16.0",
"bootstrap": "^3.3.6",
+ "bootswatch": "^3.3.7",
"font-awesome": "^4.7.0",
"history": "^4.4.0",
"jquery": "^2.2.4",
diff --git a/src/internal/movies/handlers.go b/src/internal/movies/handlers.go
index 8fe2a4d..08c14e8 100644
--- a/src/internal/movies/handlers.go
+++ b/src/internal/movies/handlers.go
@@ -6,6 +6,7 @@ import (
"net/http"
"net/url"
+ "github.com/gorilla/mux"
"github.com/odwrtw/papi"
polochon "github.com/odwrtw/polochon/lib"
"github.com/odwrtw/polochon/modules/pam"
@@ -134,3 +135,16 @@ func ExplorePopular(env *web.Env, w http.ResponseWriter, r *http.Request) error
return env.RenderJSON(w, movies)
}
+
+// GetDetailsHandler retrieves details for a movie
+func GetDetailsHandler(env *web.Env, w http.ResponseWriter, r *http.Request) error {
+ vars := mux.Vars(r)
+ id := vars["id"]
+
+ m := New(id)
+ if err := m.GetDetails(env, true); err != nil {
+ return err
+ }
+
+ return env.RenderJSON(w, m)
+}
diff --git a/src/internal/movies/movies.go b/src/internal/movies/movies.go
index f1f60bd..92148ef 100644
--- a/src/internal/movies/movies.go
+++ b/src/internal/movies/movies.go
@@ -2,6 +2,7 @@ package movies
import (
"fmt"
+ "os"
"path/filepath"
"github.com/Sirupsen/logrus"
@@ -50,7 +51,8 @@ var (
type Movie struct {
sqly.BaseModel
polochon.Movie
- PolochonURL string
+ PolochonURL string `json:"polochon_url"`
+ PosterURL string `json:"poster_url"`
}
func New(imdbID string) *Movie {
@@ -62,12 +64,12 @@ func New(imdbID string) *Movie {
}
// Get returns show details in database from id or imdbid or an error
-func (m *Movie) Get(db *sqlx.DB) error {
+func (m *Movie) Get(env *web.Env) error {
var err error
if m.ID != "" {
- err = db.QueryRowx(getMovieQueryByID, m.ID).StructScan(m)
+ err = env.Database.QueryRowx(getMovieQueryByID, m.ID).StructScan(m)
} else if m.ImdbID != "" {
- err = db.QueryRowx(getMovieQueryByImdbID, m.ImdbID).StructScan(m)
+ err = env.Database.QueryRowx(getMovieQueryByImdbID, m.ImdbID).StructScan(m)
} else {
err = fmt.Errorf("Can't get movie details, you have to specify an ID or ImdbID")
}
@@ -77,6 +79,10 @@ func (m *Movie) Get(db *sqlx.DB) error {
}
return err
}
+
+ // Set the poster url
+ m.PosterURL = m.GetPosterURL(env)
+
return nil
}
@@ -101,7 +107,7 @@ func (m *Movie) GetDetails(env *web.Env, force bool) error {
var dbFunc func(db *sqlx.DB) error
var err error
- err = m.Get(env.Database)
+ err = m.Get(env)
switch err {
case nil:
log.Debug("movie found in database")
@@ -133,14 +139,16 @@ func (m *Movie) GetDetails(env *web.Env, force bool) error {
log.Debug("movie added in database")
// Download poster
- imgPath := filepath.Join(env.Config.PublicDir, "img", "movies", m.ImdbID+".jpg")
- err = web.Download(m.Thumb, imgPath)
+ err = web.Download(m.Thumb, m.imgFile(env))
if err != nil {
return err
}
log.Debug("poster downloaded")
+ // Set the poster url
+ m.PosterURL = m.GetPosterURL(env)
+
return nil
}
@@ -177,3 +185,23 @@ func (m *Movie) Delete(db *sqlx.DB) error {
}
return nil
}
+
+// imgURL returns the default image url
+func (m *Movie) imgURL(env *web.Env) string {
+ return fmt.Sprintf("img/movies/%s.jpg", m.ImdbID)
+}
+
+// imgFile returns the image location on disk
+func (m *Movie) imgFile(env *web.Env) string {
+ return filepath.Join(env.Config.PublicDir, m.imgURL(env))
+}
+
+// GetPosterURL returns the image URL or the default image if the poster is not yet downloaded
+func (m *Movie) GetPosterURL(env *web.Env) string {
+ // Check if the movie image exists
+ if _, err := os.Stat(m.imgFile(env)); os.IsNotExist(err) {
+ // TODO image in the config ?
+ return "img/noimage.png"
+ }
+ return m.imgURL(env)
+}
diff --git a/src/internal/web/download.go b/src/internal/web/download.go
index ce84275..6002d3f 100644
--- a/src/internal/web/download.go
+++ b/src/internal/web/download.go
@@ -1,19 +1,33 @@
package web
import (
+ "image"
+ "image/jpeg"
"io"
"net/http"
"os"
+ "path"
+
+ "github.com/nfnt/resize"
)
// Download used for downloading file
var Download = func(srcURL, dest string) error {
+ if err := createDirectory(dest); err != nil {
+ return err
+ }
+
resp, err := http.Get(srcURL)
if err != nil {
return err
}
defer resp.Body.Close()
+ img, err := resizeImage(resp.Body)
+ if err != nil {
+ return err
+ }
+
// Create the file
file, err := os.Create(dest)
if err != nil {
@@ -21,10 +35,19 @@ var Download = func(srcURL, dest string) error {
}
defer file.Close()
- // Write from the net to the file
- _, err = io.Copy(file, resp.Body)
- if err != nil {
- return err
- }
- return nil
+ return jpeg.Encode(file, img, nil)
+}
+
+// createDirectory creates the destination directory
+func createDirectory(dest string) error {
+ return os.MkdirAll(path.Dir(dest), os.ModePerm)
+}
+
+func resizeImage(img io.Reader) (image.Image, error) {
+ image, _, err := image.Decode(img)
+ if err != nil {
+ return nil, err
+ }
+
+ return resize.Resize(300, 0, image, resize.Lanczos3), nil
}
diff --git a/src/main.go b/src/main.go
index 413482e..f43ad06 100644
--- a/src/main.go
+++ b/src/main.go
@@ -75,6 +75,7 @@ func main() {
env.Handle("/movies/polochon", movies.FromPolochon).WithRole(users.UserRole)
env.Handle("/movies/explore/popular", movies.ExplorePopular).WithRole(users.UserRole)
+ env.Handle("/movies/{id:tt[0-9]+}/get_details", movies.GetDetailsHandler).WithRole(users.UserRole)
n := negroni.Classic()
n.Use(authMiddleware)
diff --git a/src/public/js/actions/actionCreators.js b/src/public/js/actions/actionCreators.js
index 1de4db5..c9ba18c 100644
--- a/src/public/js/actions/actionCreators.js
+++ b/src/public/js/actions/actionCreators.js
@@ -69,6 +69,13 @@ export function getUserInfos() {
)
}
+export function getMovieDetails(imdb_id) {
+ return request(
+ 'MOVIE_GET_DETAILS',
+ configureAxios().get(`/movies/${imdb_id}/get_details`)
+ )
+}
+
export function fetchMovies(url) {
return request(
'MOVIE_LIST_FETCH',
diff --git a/src/public/js/app.js b/src/public/js/app.js
index 32574ef..be8e084 100644
--- a/src/public/js/app.js
+++ b/src/public/js/app.js
@@ -43,9 +43,7 @@ class Main extends React.Component {
- {props.data.runtime} min + {props.movie.runtime} min
- {props.data.rating} ({props.data.votes} counts) + {props.movie.rating} ({props.movie.votes} counts)
-{props.data.plot}
+{props.movie.plot}