From 8bc462878a5d894ad33275c721230b1edae10877 Mon Sep 17 00:00:00 2001 From: Daniel Mason Date: Sun, 11 Apr 2021 20:10:52 +1200 Subject: [PATCH] 0.0.29 - Add image handler - Store images locally --- .env.example | 1 + .gitignore | 2 + .gitlab-ci.yml | 2 +- cmd/go-scrobble/main.go | 6 +++ docs/changelog.md | 4 ++ docs/config.md | 1 + internal/goscrobble/artist.go | 2 +- internal/goscrobble/image.go | 46 +++++++++++++++++++++++ internal/goscrobble/ingress_navidrome.go | 1 - internal/goscrobble/ingress_spotify.go | 17 +++++++-- internal/goscrobble/server.go | 9 ++++- internal/goscrobble/server_static.go | 31 +++++++++++++++ internal/goscrobble/timers.go | 3 ++ internal/goscrobble/track.go | 4 +- web/.env.example | 2 +- web/img/placeholder.jpg | Bin 0 -> 4553 bytes web/src/Api/index.js | 46 +++++++++++------------ web/src/Components/TopTable.js | 28 +++++++------- web/src/Components/TopTableBox.js | 7 +--- 19 files changed, 158 insertions(+), 54 deletions(-) create mode 100644 internal/goscrobble/image.go create mode 100644 web/img/placeholder.jpg diff --git a/.env.example b/.env.example index 653ef4d4..aa3cbdb0 100644 --- a/.env.example +++ b/.env.example @@ -21,3 +21,4 @@ MAIL_FROM_ADDRESS= MAIL_FROM_NAME= GOSCROBBLE_DOMAIN="" +STATIC_DIR="web" diff --git a/.gitignore b/.gitignore index eda2b7ed..88083e5e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,8 @@ web/.env.production web/.env.development +web/img/* + # Test binary, built with `go test -c` *.test diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5ed95d39..3300a85c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,7 +3,7 @@ stages: - bundle variables: - VERSION: 0.0.28 + VERSION: 0.0.29 build-go: image: golang:1.16.2 diff --git a/cmd/go-scrobble/main.go b/cmd/go-scrobble/main.go index 801c98fd..d7dfcf0b 100644 --- a/cmd/go-scrobble/main.go +++ b/cmd/go-scrobble/main.go @@ -51,6 +51,12 @@ func main() { goscrobble.RefereshExpiry = time.Duration(i) * time.Second } + goscrobble.StaticDirectory = "web" + staticDirectoryStr := os.Getenv("STATIC_DIR") + if staticDirectoryStr != "" { + goscrobble.StaticDirectory = staticDirectoryStr + } + // Ignore reverse proxies goscrobble.ReverseProxies = strings.Split(os.Getenv("REVERSE_PROXIES"), ",") diff --git a/docs/changelog.md b/docs/changelog.md index 6d498664..c0c967a9 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,3 +1,7 @@ +# 0.0.29 +- Add image handler +- Store images locally + # 0.0.28 - Fix mobile view on user pages - Fix favicon issue diff --git a/docs/config.md b/docs/config.md index d61d7670..ac9b09cc 100644 --- a/docs/config.md +++ b/docs/config.md @@ -31,3 +31,4 @@ These are stored in `web/.env.production` and `web/.env.development` MAIL_FROM_NAME= // FROM name GOSCROBBLE_DOMAIN="" // Full domain for email links (https://goscrobble.com)) + STATIC_DIR="web" // Location to store images (This will serve from web/static) diff --git a/internal/goscrobble/artist.go b/internal/goscrobble/artist.go index 136befc2..9b82feb4 100644 --- a/internal/goscrobble/artist.go +++ b/internal/goscrobble/artist.go @@ -129,7 +129,7 @@ func getArtistByUUID(uuid string) (Artist, error) { func getTopArtists(userUuid string) (TopArtists, error) { var topArtist TopArtists - rows, err := db.Query("SELECT BIN_TO_UUID(`artists`.`uuid`, true), `artists`.`name`, IFNULL(`artists`.`img`,''), count(*) "+ + rows, err := db.Query("SELECT BIN_TO_UUID(`artists`.`uuid`, true), `artists`.`name`, IFNULL(BIN_TO_UUID(`artists`.`uuid`, true),''), count(*) "+ "FROM `scrobbles` "+ "JOIN `tracks` ON `tracks`.`uuid` = `scrobbles`.`track` "+ "JOIN track_artist ON track_artist.track = tracks.uuid "+ diff --git a/internal/goscrobble/image.go b/internal/goscrobble/image.go new file mode 100644 index 00000000..369cb9eb --- /dev/null +++ b/internal/goscrobble/image.go @@ -0,0 +1,46 @@ +package goscrobble + +import ( + "fmt" + "io" + "net/http" + "os" +) + +func importImage(uuid string, url string) error { + // Create the file + path, err := os.Getwd() + if err != nil { + return err + } + + out, err := os.Create(path + string(os.PathSeparator) + StaticDirectory + string(os.PathSeparator) + "img" + string(os.PathSeparator) + uuid + "_full.jpg") + if err != nil { + return err + } + defer out.Close() + + // Get the data + resp, err := http.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + + // Check server response + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("Bad response status: %s", resp.Status) + } + + // Writer the body to file + _, err = io.Copy(out, resp.Body) + if err != nil { + return err + } + + return nil +} + +func resizeImage(uuid string) error { + return nil +} diff --git a/internal/goscrobble/ingress_navidrome.go b/internal/goscrobble/ingress_navidrome.go index 26583c8d..f928ef30 100644 --- a/internal/goscrobble/ingress_navidrome.go +++ b/internal/goscrobble/ingress_navidrome.go @@ -84,7 +84,6 @@ func (user *User) updateNavidromePlaydata(tx *sql.Tx) error { } response, err := getNavidromeNowPlaying(&tokens) - fmt.Println(response) if err != nil { return errors.New(fmt.Sprintf("Failed to fetch Navidrome Tokens %+v", err)) } diff --git a/internal/goscrobble/ingress_spotify.go b/internal/goscrobble/ingress_spotify.go index ec190635..0f938d41 100644 --- a/internal/goscrobble/ingress_spotify.go +++ b/internal/goscrobble/ingress_spotify.go @@ -238,7 +238,7 @@ func (user *User) updateImageDataFromSpotify() error { client := auth.NewClient(token) client.AutoRetry = true - rows, err := db.Query("SELECT BIN_TO_UUID(`uuid`, true), `name` FROM `artists` WHERE IFNULL(`img`,'') = '' LIMIT 50") + rows, err := db.Query("SELECT BIN_TO_UUID(`uuid`, true), `name` FROM `artists` WHERE IFNULL(`img`,'') NOT IN ('pending', 'complete') LIMIT 50") if err != nil { log.Printf("Failed to fetch config: %+v", err) return errors.New("Failed to fetch artists") @@ -271,11 +271,18 @@ func (user *User) updateImageDataFromSpotify() error { if err != nil { continue } - _ = artist.updateArtist("img", img, tx) + + err = importImage(uuid, img) + if err != nil { + fmt.Printf("Failed to import image: %+v", err) + continue + } + + _ = artist.updateArtist("img", "pending", tx) } tx.Commit() - rows, err = db.Query("SELECT BIN_TO_UUID(`uuid`, true), `name` FROM `albums` WHERE IFNULL(`img`,'') = '' LIMIT 50") + rows, err = db.Query("SELECT BIN_TO_UUID(`uuid`, true), `name` FROM `albums` WHERE IFNULL(`img`,'') NOT IN ('pending', 'complete') LIMIT 50") if err != nil { log.Printf("Failed to fetch config: %+v", err) return errors.New("Failed to fetch artists") @@ -305,10 +312,12 @@ func (user *User) updateImageDataFromSpotify() error { tx, _ = db.Begin() for uuid, img := range toUpdate { album, err = getAlbumByUUID(uuid) + err = importImage(uuid, img) + if err != nil { continue } - _ = album.updateAlbum("img", img, tx) + _ = album.updateAlbum("img", "pending", tx) } tx.Commit() return nil diff --git a/internal/goscrobble/server.go b/internal/goscrobble/server.go index 61c64d44..4716e04b 100644 --- a/internal/goscrobble/server.go +++ b/internal/goscrobble/server.go @@ -22,6 +22,9 @@ type jsonResponse struct { // List of Reverse proxies var ReverseProxies []string +// Static image directory +var StaticDirectory string + // RequestRequest - Incoming JSON! type RequestRequest struct { URL string `json:"url"` @@ -88,6 +91,10 @@ func HandleRequests(port string) { // This just prevents it serving frontend stuff over /api r.PathPrefix("/api") + // SERVE STATIC FILES - NO AUTH + spaStatic := spaStaticHandler{staticPath: StaticDirectory} + r.PathPrefix("/img").Handler(spaStatic) + // SERVE FRONTEND - NO AUTH spa := spaHandler{staticPath: "web/build", indexPath: "index.html"} r.PathPrefix("/").Handler(spa) @@ -733,7 +740,7 @@ func getServerInfo(w http.ResponseWriter, r *http.Request) { } info := ServerInfo{ - Version: "0.0.28", + Version: "0.0.29", RegistrationEnabled: cachedRegistrationEnabled, } diff --git a/internal/goscrobble/server_static.go b/internal/goscrobble/server_static.go index 7e404244..f420d03f 100644 --- a/internal/goscrobble/server_static.go +++ b/internal/goscrobble/server_static.go @@ -6,12 +6,43 @@ import ( "path/filepath" ) +// spaStaticHandler - Handles static imges +type spaStaticHandler struct { + staticPath string + indexPath string +} + // spaHandler - Handles Single Page Applications (React) type spaHandler struct { staticPath string indexPath string } +// ServerHTTP - Frontend React server +func (h spaStaticHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // Get the absolute path to prevent directory traversal + path, err := filepath.Abs(r.URL.Path) + if err != nil { + http.ServeFile(w, r, filepath.Join(h.staticPath, "img/placeholder.jpg")) + return + } + + path = filepath.Join(h.staticPath, path) + + _, err = os.Stat(path) + if os.IsNotExist(err) { + // file does not exist, serve placeholder + http.ServeFile(w, r, filepath.Join(h.staticPath, "img/placeholder.jpg")) + return + } else if err != nil { + http.ServeFile(w, r, filepath.Join(h.staticPath, "img/placeholder.jpg")) + return + } + + // otherwise, use http.FileServer to serve the static images + http.FileServer(http.Dir(h.staticPath)).ServeHTTP(w, r) +} + // ServerHTTP - Frontend React server func (h spaHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Get the absolute path to prevent directory traversal diff --git a/internal/goscrobble/timers.go b/internal/goscrobble/timers.go index 070e2bcb..90b9c267 100644 --- a/internal/goscrobble/timers.go +++ b/internal/goscrobble/timers.go @@ -8,6 +8,9 @@ import ( var endTicker chan bool func StartBackgroundWorkers() { + user, _ := getUserByUsername("idanoo") + go user.updateImageDataFromSpotify() + endTicker := make(chan bool) hourTicker := time.NewTicker(time.Duration(1) * time.Hour) diff --git a/internal/goscrobble/track.go b/internal/goscrobble/track.go index 75487891..85a12838 100644 --- a/internal/goscrobble/track.go +++ b/internal/goscrobble/track.go @@ -166,7 +166,7 @@ func (track *Track) updateTrack(col string, val string, tx *sql.Tx) error { func getTrackByUUID(uuid string) (Track, error) { var track Track - err := db.QueryRow("SELECT BIN_TO_UUID(`tracks`.`uuid`, true), `tracks`.`name`, IFNULL(`albums`.`desc`,''), IFNULL(`albums`.`img`,''), `tracks`.`length`, `tracks`.`mbid`, `tracks`.`spotify_id` "+ + err := db.QueryRow("SELECT BIN_TO_UUID(`tracks`.`uuid`, true), `tracks`.`name`, IFNULL(`albums`.`desc`,''), IFNULL(BIN_TO_UUID(`albums`.`uuid`, true),''), `tracks`.`length`, `tracks`.`mbid`, `tracks`.`spotify_id` "+ "FROM `tracks` "+ "LEFT JOIN track_album ON track_album.track = tracks.uuid "+ "LEFT JOIN albums ON track_album.album = albums.uuid "+ @@ -184,7 +184,7 @@ func getTrackByUUID(uuid string) (Track, error) { func getTopTracks(userUuid string) (TopTracks, error) { var topTracks TopTracks - rows, err := db.Query("SELECT BIN_TO_UUID(`tracks`.`uuid`, true), `tracks`.`name`, IFNULL(`albums`.`img`,''), count(*) "+ + rows, err := db.Query("SELECT BIN_TO_UUID(`tracks`.`uuid`, true), `tracks`.`name`, IFNULL(BIN_TO_UUID(`albums`.`uuid`, true),''), count(*) "+ "FROM `scrobbles` "+ "JOIN `tracks` ON `tracks`.`uuid` = `scrobbles`.`track` "+ "JOIN track_album ON track_album.track = tracks.uuid "+ diff --git a/web/.env.example b/web/.env.example index fbedc8f2..3150c75a 100644 --- a/web/.env.example +++ b/web/.env.example @@ -1 +1 @@ -REACT_APP_API_URL=http://127.0.0.1:42069/api/v1/ +REACT_APP_API_URL=http://127.0.0.1:42069 diff --git a/web/img/placeholder.jpg b/web/img/placeholder.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ff8ff816f4528bbe0fbbd9a6a7503fb82f1a272e GIT binary patch literal 4553 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 literal 0 HcmV?d00001 diff --git a/web/src/Api/index.js b/web/src/Api/index.js index c4c85169..3114a660 100644 --- a/web/src/Api/index.js +++ b/web/src/Api/index.js @@ -49,7 +49,7 @@ function handleErrorResp(error) { } export const PostLogin = (formValues) => { - return axios.post(process.env.REACT_APP_API_URL + "login", formValues) + return axios.post(process.env.REACT_APP_API_URL + "/api/v1/login", formValues) .then((response) => { if (response.data.token) { let expandedUser = jwt(response.data.token) @@ -82,7 +82,7 @@ export const PostLogin = (formValues) => { }; export const PostRefreshToken = (refreshToken) => { - return axios.post(process.env.REACT_APP_API_URL + "refresh", {token: refreshToken}) + return axios.post(process.env.REACT_APP_API_URL + "/api/v1/refresh", {token: refreshToken}) .then((response) => { if (response.data.token) { let expandedUser = jwt(response.data.token) @@ -115,7 +115,7 @@ export const PostRefreshToken = (refreshToken) => { export const PostRegister = (formValues) => { - return axios.post(process.env.REACT_APP_API_URL + "register", formValues) + return axios.post(process.env.REACT_APP_API_URL + "/api/v1/register", formValues) .then((response) => { if (response.data.message) { toast.success(response.data.message); @@ -133,7 +133,7 @@ export const PostRegister = (formValues) => { }; export const PostResetPassword = (formValues) => { - return axios.post(process.env.REACT_APP_API_URL + "resetpassword", formValues) + return axios.post(process.env.REACT_APP_API_URL + "/api/v1/resetpassword", formValues) .then((response) => { if (response.data.message) { toast.success(response.data.message); @@ -151,7 +151,7 @@ export const PostResetPassword = (formValues) => { }; export const sendPasswordReset = (values) => { - return axios.post(process.env.REACT_APP_API_URL + "sendreset", values).then( + return axios.post(process.env.REACT_APP_API_URL + "/api/v1/sendreset", values).then( (data) => { return data.data; }).catch((error) => { @@ -160,7 +160,7 @@ export const sendPasswordReset = (values) => { }; export const getStats = () => { - return axios.get(process.env.REACT_APP_API_URL + "stats").then( + return axios.get(process.env.REACT_APP_API_URL + "/api/v1/stats").then( (data) => { return data.data; }).catch((error) => { @@ -169,7 +169,7 @@ export const getStats = () => { }; export const getRecentScrobbles = (id) => { - return axios.get(process.env.REACT_APP_API_URL + "user/" + id + "/scrobbles", { headers: getHeaders() }) + return axios.get(process.env.REACT_APP_API_URL + "/api/v1/user/" + id + "/scrobbles", { headers: getHeaders() }) .then((data) => { return data.data; }).catch((error) => { @@ -178,7 +178,7 @@ export const getRecentScrobbles = (id) => { }; export const getConfigs = () => { - return axios.get(process.env.REACT_APP_API_URL + "config", { headers: getHeaders() }) + return axios.get(process.env.REACT_APP_API_URL + "/api/v1/config", { headers: getHeaders() }) .then((data) => { return data.data; }).catch((error) => { @@ -193,7 +193,7 @@ export const postConfigs = (values, toggle) => { values.REGISTRATION_ENABLED = "0" } - return axios.post(process.env.REACT_APP_API_URL + "config", values, { headers: getHeaders() }) + return axios.post(process.env.REACT_APP_API_URL + "/api/v1/config", values, { headers: getHeaders() }) .then((data) => { if (data.data && data.data.message) { toast.success(data.data.message); @@ -206,7 +206,7 @@ export const postConfigs = (values, toggle) => { }; export const getProfile = (userName) => { - return axios.get(process.env.REACT_APP_API_URL + "profile/" + userName, { headers: getHeaders() }) + return axios.get(process.env.REACT_APP_API_URL + "/api/v1/profile/" + userName, { headers: getHeaders() }) .then((data) => { return data.data; }).catch((error) => { @@ -215,7 +215,7 @@ export const getProfile = (userName) => { }; export const getUser = () => { - return axios.get(process.env.REACT_APP_API_URL + "user", { headers: getHeaders() }) + return axios.get(process.env.REACT_APP_API_URL + "/api/v1/user", { headers: getHeaders() }) .then((data) => { return data.data; }).catch((error) => { @@ -224,7 +224,7 @@ export const getUser = () => { }; export const patchUser = (values) => { - return axios.patch(process.env.REACT_APP_API_URL + "user", values, { headers: getHeaders() }) + return axios.patch(process.env.REACT_APP_API_URL + "/api/v1/user", values, { headers: getHeaders() }) .then((data) => { return data.data; }).catch((error) => { @@ -233,7 +233,7 @@ export const patchUser = (values) => { }; export const validateResetPassword = (tokenStr) => { - return axios.get(process.env.REACT_APP_API_URL + "user/", { headers: getHeaders() }) + return axios.get(process.env.REACT_APP_API_URL + "/api/v1/user/", { headers: getHeaders() }) .then((data) => { return data.data; }).catch((error) => { @@ -242,7 +242,7 @@ export const validateResetPassword = (tokenStr) => { }; export const getSpotifyClientId = () => { - return axios.get(process.env.REACT_APP_API_URL + "user/spotify", { headers: getHeaders() }) + return axios.get(process.env.REACT_APP_API_URL + "/api/v1/user/spotify", { headers: getHeaders() }) .then((data) => { return data.data }).catch((error) => { @@ -272,7 +272,7 @@ export const spotifyConnectionRequest = () => { }; export const spotifyDisonnectionRequest = () => { - return axios.delete(process.env.REACT_APP_API_URL + "user/spotify", { headers: getHeaders() }) + return axios.delete(process.env.REACT_APP_API_URL + "/api/v1/user/spotify", { headers: getHeaders() }) .then((data) => { toast.success(data.data.message); return true @@ -282,7 +282,7 @@ export const spotifyDisonnectionRequest = () => { } export const navidromeConnectionRequest = (values) => { - return axios.post(process.env.REACT_APP_API_URL + "user/navidrome", values, { headers: getHeaders() }) + return axios.post(process.env.REACT_APP_API_URL + "/api/v1/user/navidrome", values, { headers: getHeaders() }) .then((data) => { toast.success(data.data.message); return true @@ -292,7 +292,7 @@ export const navidromeConnectionRequest = (values) => { }; export const navidromeDisonnectionRequest = () => { - return axios.delete(process.env.REACT_APP_API_URL + "user/navidrome", { headers: getHeaders() }) + return axios.delete(process.env.REACT_APP_API_URL + "/api/v1/user/navidrome", { headers: getHeaders() }) .then((data) => { toast.success(data.data.message); return true @@ -303,7 +303,7 @@ export const navidromeDisonnectionRequest = () => { export const getServerInfo = () => { - return axios.get(process.env.REACT_APP_API_URL + "serverinfo") + return axios.get(process.env.REACT_APP_API_URL + "/api/v1/serverinfo") .then((data) => { return data.data }).catch((error) => { @@ -312,7 +312,7 @@ export const getServerInfo = () => { } export const getArtist = (uuid) => { - return axios.get(process.env.REACT_APP_API_URL + "artists/" + uuid).then( + return axios.get(process.env.REACT_APP_API_URL + "/api/v1/artists/" + uuid).then( (data) => { return data.data; }).catch((error) => { @@ -321,7 +321,7 @@ export const getArtist = (uuid) => { }; export const getAlbum = (uuid) => { - return axios.get(process.env.REACT_APP_API_URL + "albums/" + uuid).then( + return axios.get(process.env.REACT_APP_API_URL + "/api/v1/albums/" + uuid).then( (data) => { return data.data; }).catch((error) => { @@ -330,7 +330,7 @@ export const getAlbum = (uuid) => { }; export const getTrack = (uuid) => { - return axios.get(process.env.REACT_APP_API_URL + "tracks/" + uuid).then( + return axios.get(process.env.REACT_APP_API_URL + "/api/v1/tracks/" + uuid).then( (data) => { return data.data; }).catch((error) => { @@ -339,7 +339,7 @@ export const getTrack = (uuid) => { }; export const getTopTracks = (uuid) => { - return axios.get(process.env.REACT_APP_API_URL + "tracks/top/" + uuid).then( + return axios.get(process.env.REACT_APP_API_URL + "/api/v1/tracks/top/" + uuid).then( (data) => { return data.data; }).catch((error) => { @@ -348,7 +348,7 @@ export const getTopTracks = (uuid) => { } export const getTopArtists = (uuid) => { - return axios.get(process.env.REACT_APP_API_URL + "artists/top/" + uuid).then( + return axios.get(process.env.REACT_APP_API_URL + "/api/v1/artists/top/" + uuid).then( (data) => { return data.data; }).catch((error) => { diff --git a/web/src/Components/TopTable.js b/web/src/Components/TopTable.js index b44a2891..abc64f1a 100644 --- a/web/src/Components/TopTable.js +++ b/web/src/Components/TopTable.js @@ -21,7 +21,7 @@ const TopTable = (props) => { number="1" title={tracks[1].name} link={"/" + props.type + "/" + tracks[1].uuid} - img={tracks[1].img} + uuid={tracks[1].img} /> { Object.keys(props.items).length > 5 && @@ -31,28 +31,28 @@ const TopTable = (props) => { number="2" title={tracks[2].name} link={"/" + props.type + "/" + tracks[2].uuid} - img={tracks[2].img} + uuid={tracks[2].img} /> } @@ -63,63 +63,63 @@ const TopTable = (props) => { number="6" title={tracks[6].name} link={"/" + props.type + "/" + tracks[6].uuid} - img={tracks[6].img} + uuid={tracks[6].img} /> } diff --git a/web/src/Components/TopTableBox.js b/web/src/Components/TopTableBox.js index a2b7fb76..dab8ef80 100644 --- a/web/src/Components/TopTableBox.js +++ b/web/src/Components/TopTableBox.js @@ -3,17 +3,12 @@ import { Link } from 'react-router-dom'; import './TopTableBox.css' const TopTableBox = (props) => { - let img = 'https://www.foot.com/wp-content/uploads/2017/06/placeholder-square-300x300.jpg'; - if (props.img && props.img !== '') { - img = props.img - } - return (