Add extra info to track page + API

This commit is contained in:
Daniel Mason 2021-08-12 20:52:47 +12:00
parent 97dd3e5bba
commit f914575e09
Signed by: idanoo
GPG Key ID: 387387CDBC02F132
9 changed files with 3349 additions and 2525 deletions

View File

@ -75,8 +75,8 @@ func main() {
defer goscrobble.CloseRedisConn()
// Start background workers
go goscrobble.StartBackgroundWorkers()
defer goscrobble.EndBackgroundWorkers()
// go goscrobble.StartBackgroundWorkers()
// defer goscrobble.EndBackgroundWorkers()
// Boot up API webserver \o/
goscrobble.HandleRequests(port)

View File

@ -554,12 +554,20 @@ func getTrack(w http.ResponseWriter, r *http.Request) {
return
}
// Load track obj
track, err := getTrackByUUID(uuid)
if err != nil {
throwOkError(w, err.Error())
return
}
// Load in Album/Artist info
err = track.loadExtraTrackInfo()
if err != nil {
throwOkError(w, err.Error())
return
}
json, _ := json.Marshal(&track)
w.WriteHeader(http.StatusOK)
w.Write(json)

View File

@ -9,13 +9,15 @@ import (
)
type Track struct {
UUID string `json:"uuid"`
Name string `json:"name"`
Length int `json:"length"`
Desc string `json:"desc"`
Img string `json:"img"`
MusicBrainzID string `json:"mbid"`
SpotifyID string `json:"spotify_id"`
UUID string `json:"uuid"`
Name string `json:"name"`
Length int `json:"length"`
Desc string `json:"desc"`
Img string `json:"img"`
MusicBrainzID string `json:"mbid"`
SpotifyID string `json:"spotify_id"`
Artists []Artist `json:"artists"` // Optional Artist
Albums []Album `json:"albums"` // Optional Albums
}
type TopTrack struct {
@ -219,3 +221,76 @@ func getTopTracks(userUuid string) (TopTracks, error) {
return topTracks, nil
}
func (track *Track) loadExtraTrackInfo() error {
err := track.getArtistsForTrack()
if err != nil {
return err
}
err = track.getAlbumsForTrack()
return err
}
func (track *Track) getArtistsForTrack() error {
artists := []Artist{}
rows, err := db.Query("SELECT BIN_TO_UUID(`track_artist`.`artist`, true) "+
"FROM `track_artist` "+
"WHERE `track_artist`.`track` = UUID_TO_BIN(?, true)",
track.UUID)
if err != nil {
log.Printf("Failed to fetch artists for track: %+v", err)
return errors.New("Failed to fetch top tracks")
}
defer rows.Close()
for rows.Next() {
var artistUUID string
err := rows.Scan(&artistUUID)
if err != nil {
log.Printf("Failed to fetch track_artist: %+v", err)
return errors.New("Failed to fetch track")
}
artist, err := getArtistByUUID(artistUUID)
if err != nil {
return err
}
artists = append(artists, artist)
}
track.Artists = artists
return nil
}
func (track *Track) getAlbumsForTrack() error {
albums := []Album{}
rows, err := db.Query("SELECT BIN_TO_UUID(`track_album`.`album`, true) "+
"FROM `track_album` "+
"WHERE `track_album`.`track` = UUID_TO_BIN(?, true)",
track.UUID)
if err != nil {
log.Printf("Failed to fetch album for track: %+v", err)
return errors.New("Failed to fetch top tracks")
}
defer rows.Close()
for rows.Next() {
var albumUUID string
err := rows.Scan(&albumUUID)
if err != nil {
log.Printf("Failed to fetch track_album: %+v", err)
return errors.New("Failed to fetch track")
}
album, err := getAlbumByUUID(albumUUID)
if err != nil {
return err
}
albums = append(albums, album)
}
track.Albums = albums
return nil
}

View File

@ -145,7 +145,7 @@ func filterSlice(s []string) []string {
}
var result []string
for item, _ := range m {
for item := range m {
result = append(result, item)
}

View File

@ -1 +0,0 @@
DROP TABLE IF EXISTS `files`;

View File

@ -1,7 +0,0 @@
CREATE TABLE IF NOT EXISTS `files` (
`uuid` BINARY(16) PRIMARY KEY,
`path` VARCHAR(255) NOT NULL,
`filesize` INT NULL DEFAULT NULL,
`dimension` VARCHAR(4) NOT NULL,
KEY `dimensionLookup` (`uuid`, `dimension`)
) DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci;

5706
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -51,7 +51,6 @@
]
},
"devDependencies": {
"redux-devtools-extension": "^2.13.9",
"webpack-dev-server": "^3.11.1"
"redux-devtools-extension": "^2.13.9"
}
}

View File

@ -3,6 +3,7 @@ import '../App.css';
import './Track.css';
import ScaleLoader from 'react-spinners/ScaleLoader';
import { getTrack } from '../Api/index'
import { Link } from 'react-router-dom';
const Track = (route) => {
const [loading, setLoading] = useState(true);
@ -49,18 +50,53 @@ const Track = (route) => {
length = new Date(track.length * 1000).toISOString().substr(11, 8)
}
let artists = [];
for (let artist of track.artists) {
const row = (
<Link
key={artist.uuid}
to={"/artist/" + artist.uuid}
>{artist.name} </Link>
);
artists.push(row);
}
let albums = [];
for (let album of track.albums) {
const row = (
<Link
key={album.uuid}
to={"/album/" + album.uuid}
>{album.name} </Link>
);
albums.push(row);
}
return (
<div className="pageWrapper">
<h1>
{track.name}
</h1>
<div className="pageBody" style={{textAlign: `center`}}>
<img src={process.env.REACT_APP_API_URL + "/img/" + track.img + "_full.jpg"} alt={track.name} style={{maxWidth: `300px`, maxHeight: `300px`}}/><br/><br/>
{track.mbid && <a rel="noreferrer" target="_blank" href={"https://musicbrainz.org/track/" + track.mbid}>Open on MusicBrainz<br/></a>}
{track.spotify_id && <a rel="noreferrer" target="_blank" href={"https://open.spotify.com/track/" + track.spotify_id}>Open on Spotify<br/></a>}
Track Length: {length && length}
<div className="pageBody">
<div style={{display: `flex`, flexWrap: `wrap`, textAlign: `center`}}>
<div style={{width: `300px`, padding: `0 10px 10px 10px`, textAlign: `left`}}>
<h1 style={{margin: 0}}>
{track.name}
</h1>
<span>
{artists}
</span>
<br/>
<span>
{albums}
</span>
<img src={process.env.REACT_APP_API_URL + "/img/" + track.img + "_full.jpg"} alt={track.name} style={{maxWidth: `300px`, maxHeight: `300px`}}/><br/><br/>
{track.mbid && <a rel="noreferrer" target="_blank" href={"https://musicbrainz.org/track/" + track.mbid}>Open on MusicBrainz<br/></a>}
{track.spotify_id && <a rel="noreferrer" target="_blank" href={"https://open.spotify.com/track/" + track.spotify_id}>Open on Spotify<br/></a>}
Track Length: {length && length}
</div>
<div style={{width: `600px`, padding: `0 10px 10px 10px`}}>
<h3>Top Users</h3>
<br/>
</div>
</div>
</div>
</div>
);