diff --git a/.gitignore b/.gitignore index 913e327..8329c31 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .idea/ tmp/ test/ +data/* diff --git a/api/v1/admin/admin.go b/api/v1/admin/admin.go index e952d40..a24722e 100644 --- a/api/v1/admin/admin.go +++ b/api/v1/admin/admin.go @@ -6,7 +6,7 @@ import ( "math/rand" "net/http" "os" - "strings" + // "strings" "time" "arimelody.me/arimelody.me/discord" @@ -59,6 +59,12 @@ func Handler() http.Handler { func MustAuthorise(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // TEMPORARY + ctx := context.WithValue(r.Context(), "role", "admin") + next.ServeHTTP(w, r.WithContext(ctx)) + return + + /* auth := r.Header.Get("Authorization") if strings.HasPrefix(auth, "Bearer ") { auth = auth[7:] @@ -96,9 +102,9 @@ func MustAuthorise(next http.Handler) http.Handler { return } - ctx := context.WithValue(r.Context(), "token", session.Token) - ctx = context.WithValue(ctx, "role", "admin") + ctx := context.WithValue(r.Context(), "role", "admin") next.ServeHTTP(w, r.WithContext(ctx)) + */ }) } diff --git a/api/v1/music/artist.go b/api/v1/music/artist.go index 3fcd740..59e5555 100644 --- a/api/v1/music/artist.go +++ b/api/v1/music/artist.go @@ -1,15 +1,16 @@ package music import ( - "fmt" + "encoding/json" + "net/http" "github.com/jmoiron/sqlx" ) type Artist struct { - id string - name string - website string + ID string `json:"id"` + Name string `json:"name"` + Website string `json:"website"` } var Artists []Artist @@ -26,46 +27,50 @@ func GetArtist(id string) *Artist { // GETTERS func (artist Artist) GetID() string { - return artist.id + return artist.ID } func (artist Artist) GetName() string { - return artist.name + return artist.Name } func (artist Artist) GetWebsite() string { - return artist.website + return artist.Website } // SETTERS func (artist Artist) SetID(id string) error { - artist.id = id + artist.ID = id return nil } func (artist Artist) SetName(name string) error { - artist.name = name + artist.Name = name return nil } func (artist Artist) SetWebsite(website string) error { - artist.website = website + artist.Website = website return nil } // DATABASE func (artist Artist) PushToDB(db *sqlx.DB) { - fmt.Printf("Pushing artist [%s] to database...", artist.name) + // fmt.Printf("Pushing artist [%s] to database...", artist.Name) - db.MustExec("INSERT INTO artists (id, name, website) VALUES ($1, $2, $3) ON CONFLICT (id) DO UPDATE SET name=$2, website=$3", - artist.id, - artist.name, - artist.website, + db.MustExec( + "INSERT INTO artists (id, name, website) "+ + "VALUES ($1, $2, $3) "+ + "ON CONFLICT (id) "+ + "DO UPDATE SET name=$2, website=$3", + artist.ID, + artist.Name, + artist.Website, ) - fmt.Printf("done!\n") + // fmt.Printf("done!\n") } func PullAllArtists(db *sqlx.DB) ([]Artist, error) { @@ -80,9 +85,9 @@ func PullAllArtists(db *sqlx.DB) ([]Artist, error) { var artist = Artist{} err = rows.Scan( - &artist.id, - &artist.name, - &artist.website, + &artist.ID, + &artist.Name, + &artist.Website, ) if err != nil { return nil, err @@ -93,3 +98,58 @@ func PullAllArtists(db *sqlx.DB) ([]Artist, error) { return artists, nil } + +// HTTP HANDLERS + +func ServeArtist() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/" { + http.NotFound(w, r) + return + } + + type ( + creditJSON struct { + Role string `json:"role"` + Primary bool `json:"primary"` + } + artistJSON struct { + Artist + Credits map[string]creditJSON `json:"credits"` + } + ) + var res = artistJSON{} + + res.ID = r.URL.Path[1:] + var artist = GetArtist(res.ID) + if artist == nil { + http.NotFound(w, r) + return + } + res.Name = artist.Name + res.Website = artist.Website + res.Credits = make(map[string]creditJSON) + + for _, release := range Releases { + for _, credit := range release.Credits { + if credit.Artist.ID != res.ID { + continue + } + res.Credits[release.ID] = creditJSON{ + Role: credit.Role, + Primary: credit.Primary, + } + } + } + + jsonBytes, err := json.Marshal(res) + if err != nil { + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(jsonBytes) + }) +} diff --git a/api/v1/music/credit.go b/api/v1/music/credit.go index a2bd1b6..57c1ed7 100644 --- a/api/v1/music/credit.go +++ b/api/v1/music/credit.go @@ -7,42 +7,42 @@ import ( ) type Credit struct { - artist *Artist - role string - primary bool + Artist *Artist `json:"artist"` + Role string `json:"role"` + Primary bool `json:"primary"` } // GETTERS func (credit Credit) GetArtist() Artist { - return *credit.artist + return *credit.Artist } func (credit Credit) GetRole() string { - return credit.role + return credit.Role } func (credit Credit) IsPrimary() bool { - return credit.primary + return credit.Primary } // SETTERS func (credit Credit) SetArtist(artist *Artist) error { // TODO: update DB - credit.artist = artist + credit.Artist = artist return nil } func (credit Credit) SetRole(role string) error { // TODO: update DB - credit.role = role + credit.Role = role return nil } func (credit Credit) SetPrimary(primary bool) error { // TODO: update DB - credit.primary = primary + credit.Primary = primary return nil } @@ -61,16 +61,16 @@ func PullReleaseCredits(db *sqlx.DB, releaseID string) ([]Credit, error) { var credit = Credit{} err = credit_rows.Scan( &artistID, - &credit.role, - &credit.primary, + &credit.Role, + &credit.Primary, ) if err != nil { fmt.Printf("Error while pulling credit for release %s: %s\n", releaseID, err) continue } - credit.artist = GetArtist(artistID) - if credit.artist == nil { + credit.Artist = GetArtist(artistID) + if credit.Artist == nil { // this should absolutely not happen ever due to foreign key // constraints, but it doesn't hurt to be sure! fmt.Printf("Error while pulling credit for release %s: Artist %s does not exist\n", releaseID, artistID) diff --git a/api/v1/music/link.go b/api/v1/music/link.go index 3ab74d7..9e834c0 100644 --- a/api/v1/music/link.go +++ b/api/v1/music/link.go @@ -9,31 +9,31 @@ import ( ) type Link struct { - name string - url string + Name string `json:"name"` + URL string `json:"url"` } // GETTERS func (link Link) GetName() string { - return link.name + return link.Name } func (link Link) GetURL() string { - return link.url + return link.URL } // SETTERS func (link Link) SetName(name string) error { // TODO: update DB - link.name = name + link.Name = name return nil } func (link Link) SetURL(url string) error { // TODO: update DB - link.url = url + link.URL = url return nil } @@ -41,7 +41,7 @@ func (link Link) SetURL(url string) error { func (link Link) NormaliseName() string { rgx := regexp.MustCompile(`[^a-z0-9]`) - return strings.ToLower(rgx.ReplaceAllString(link.name, "")) + return strings.ToLower(rgx.ReplaceAllString(link.Name, "")) } // DATABASE @@ -58,8 +58,8 @@ func PullReleaseLinks(db *sqlx.DB, releaseID string) ([]Link, error) { var link = Link{} err = link_rows.Scan( - &link.name, - &link.url, + &link.Name, + &link.URL, ) if err != nil { fmt.Printf("Error while pulling link for release %s: %s\n", releaseID, err) diff --git a/api/v1/music/music.go b/api/v1/music/music.go index 3afb392..ef49d99 100644 --- a/api/v1/music/music.go +++ b/api/v1/music/music.go @@ -3,6 +3,9 @@ package music import ( "fmt" "net/http" + "os" + "path/filepath" + "strings" "arimelody.me/arimelody.me/api/v1/admin" "arimelody.me/arimelody.me/global" @@ -36,6 +39,11 @@ func ServeCatalog() http.Handler { func ServeGateway() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/" { + http.Redirect(w, r, "/music", http.StatusPermanentRedirect) + return + } + id := r.URL.Path[1:] release := GetRelease(id) if release == nil { @@ -60,3 +68,56 @@ func ServeGateway() http.Handler { } }) } + +func ServeArtwork() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/" { + http.NotFound(w, r) + return + } + + if !strings.HasSuffix(r.URL.Path, ".png") { + http.NotFound(w, r) + return + } + + releaseID := r.URL.Path[1:len(r.URL.Path) - 4] + var release = GetRelease(releaseID) + if release == nil { + http.NotFound(w, r) + return + } + + // only allow authorised users to view unreleased releases + authorised := r.Context().Value("role") != nil && r.Context().Value("role") == "admin" + if !release.IsReleased() && !authorised { + admin.MustAuthorise(ServeArtwork()).ServeHTTP(w, r) + return + } + + fp := filepath.Join("data", "music-artwork", releaseID + ".png") + fmt.Println(fp) + info, err := os.Stat(fp) + if err != nil { + if os.IsNotExist(err) { + http.NotFound(w, r) + return + } + } + length := info.Size() + + file, err := os.Open(fp) + if err != nil { + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + defer file.Close() + + var bytes = make([]byte, length) + file.Read(bytes) + + w.Header().Add("Content-Type", "image/png") + w.WriteHeader(http.StatusOK) + w.Write(bytes) + }) +} diff --git a/api/v1/music/release.go b/api/v1/music/release.go index 1f5aeff..34620b9 100644 --- a/api/v1/music/release.go +++ b/api/v1/music/release.go @@ -1,11 +1,14 @@ package music import ( + "encoding/json" "errors" "fmt" + "net/http" "strings" "time" + "arimelody.me/arimelody.me/api/v1/admin" "github.com/jmoiron/sqlx" ) @@ -19,17 +22,17 @@ const ( ) type Release struct { - id string - title string - releaseType ReleaseType - releaseDate time.Time - artwork string - buyname string - buylink string - links []Link - description string - credits []Credit - tracks []Track + ID string `json:"id"` + Title string `json:"title"` + Description string `json:"description"` + ReleaseType ReleaseType `json:"type"` + ReleaseDate time.Time `json:"releaseDate"` + Artwork string `json:"artwork"` + Buyname string `json:"buyname"` + Buylink string `json:"buylink"` + Links []Link `json:"links"` + Credits []Credit `json:"credits"` + Tracks []Track `json:"tracks"` } var Releases []Release; @@ -37,117 +40,117 @@ var Releases []Release; // GETTERS func (release Release) GetID() string { - return release.id + return release.ID } func (release Release) GetTitle() string { - return release.title -} - -func (release Release) GetType() ReleaseType { - return release.releaseType -} - -func (release Release) GetReleaseDate() time.Time { - return release.releaseDate -} - -func (release Release) GetArtwork() string { - if release.artwork == "" { - return "/img/music-artwork/default.png" - } - return release.artwork -} - -func (release Release) GetBuyName() string { - return release.buyname -} - -func (release Release) GetBuyLink() string { - return release.buylink -} - -func (release Release) GetLinks() []Link { - return release.links + return release.Title } func (release Release) GetDescription() string { - return release.description + return release.Description +} + +func (release Release) GetType() ReleaseType { + return release.ReleaseType +} + +func (release Release) GetReleaseDate() time.Time { + return release.ReleaseDate +} + +func (release Release) GetArtwork() string { + if release.Artwork == "" { + return "/img/default-cover-art.png" + } + return release.Artwork +} + +func (release Release) GetBuyName() string { + return release.Buyname +} + +func (release Release) GetBuyLink() string { + return release.Buylink +} + +func (release Release) GetLinks() []Link { + return release.Links } func (release Release) GetCredits() []Credit { - return release.credits + return release.Credits } func (release Release) GetTracks() []Track { - return release.tracks + return release.Tracks } // SETTERS func (release Release) SetID(id string) error { // TODO: update DB - release.id = id + release.ID = id return nil } func (release Release) SetTitle(title string) error { // TODO: update DB - release.title = title - return nil -} - -func (release Release) SetType(releaseType ReleaseType) error { - // TODO: update DB - release.releaseType = releaseType - return nil -} - -func (release Release) SetReleaseDate(releaseDate time.Time) error { - // TODO: update DB - release.releaseDate = releaseDate - return nil -} - -func (release Release) SetArtwork(artwork string) error { - // TODO: update DB - release.artwork = artwork - return nil -} - -func (release Release) SetBuyName(buyname string) error { - // TODO: update DB - release.buyname = buyname - return nil -} - -func (release Release) SetBuyLink(buylink string) error { - // TODO: update DB - release.buylink = buylink - return nil -} - -func (release Release) SetLinks(links []Link) error { - // TODO: update DB - release.links = links + release.Title = title return nil } func (release Release) SetDescription(description string) error { // TODO: update DB - release.description = description + release.Description = description + return nil +} + +func (release Release) SetType(releaseType ReleaseType) error { + // TODO: update DB + release.ReleaseType = releaseType + return nil +} + +func (release Release) SetReleaseDate(releaseDate time.Time) error { + // TODO: update DB + release.ReleaseDate = releaseDate + return nil +} + +func (release Release) SetArtwork(artwork string) error { + // TODO: update DB + release.Artwork = artwork + return nil +} + +func (release Release) SetBuyName(buyname string) error { + // TODO: update DB + release.Buyname = buyname + return nil +} + +func (release Release) SetBuyLink(buylink string) error { + // TODO: update DB + release.Buylink = buylink + return nil +} + +func (release Release) SetLinks(links []Link) error { + // TODO: update DB + release.Links = links return nil } func (release Release) SetCredits(credits []Credit) error { // TODO: update DB - release.credits = credits + release.Credits = credits return nil } func (release Release) SetTracks(tracks []Track) error { // TODO: update DB - release.tracks = tracks + release.Tracks = tracks return nil } @@ -163,32 +166,32 @@ func GetRelease(id string) *Release { } func (release Release) PrintReleaseDate() string { - return release.releaseDate.Format("02 January 2006") + return release.ReleaseDate.Format("02 January 2006") } func (release Release) GetReleaseYear() int { - return release.releaseDate.Year() + return release.ReleaseDate.Year() } func (release Release) IsSingle() bool { - return len(release.tracks) == 1; + return len(release.Tracks) == 1; } func (release Release) IsReleased() bool { - return release.releaseDate.Before(time.Now()) + return release.ReleaseDate.Before(time.Now()) } func (release Release) GetUniqueArtists(only_primary bool) []Artist { var artists = []Artist{} - for _, credit := range release.credits { - if only_primary && !credit.primary { + for _, credit := range release.Credits { + if only_primary && !credit.Primary { continue } exists := false for _, a := range artists { - if a.id == credit.artist.id { + if a.ID == credit.Artist.ID { exists = true break } @@ -198,7 +201,7 @@ func (release Release) GetUniqueArtists(only_primary bool) []Artist { continue } - artists = append(artists, *credit.artist) + artists = append(artists, *credit.Artist) } return artists @@ -234,58 +237,69 @@ func (release Release) PrintArtists(only_primary bool, ampersand bool) string { // DATABASE func (release Release) PushToDB(db *sqlx.DB) error { - // fmt.Printf("Pushing release [%s] to database...", release.id) + // fmt.Printf("Pushing release [%s] to database...", release.ID) tx, err := db.Begin() if err != nil { return errors.New(fmt.Sprintf("Failed to initiate transaction: %s", err)) } - _, err = tx.Exec("INSERT INTO musicreleases (id, title, type, release_date, artwork, buyname, buylink) VALUES ($1, $2, $3, $4, $5, $6, $7) "+ - "ON CONFLICT (id) DO UPDATE SET title=$2, type=$3, release_date=$4, artwork=$5, buyname=$6, buylink=$7", - release.id, release.title, release.releaseType, release.releaseDate.Format("2-Jan-2006"), release.artwork, release.buyname, release.buylink) + _, err = tx.Exec( + "INSERT INTO musicreleases (id, title, description, type, release_date, artwork, buyname, buylink) "+ + "VALUES ($1, $2, $3, $4, $5, $6, $7, $8) "+ + "ON CONFLICT (id) "+ + "DO UPDATE SET title=$2, description=$3, type=$4, release_date=$5, artwork=$6, buyname=$7, buylink=$8", + release.ID, + release.Title, + release.Description, + release.ReleaseType, + release.ReleaseDate.Format("2-Jan-2006"), + release.Artwork, + release.Buyname, + release.Buylink, + ) - for _, link := range release.links { + for _, link := range release.Links { _, err = tx.Exec( "INSERT INTO musiclinks (release, name, url) "+ "VALUES ($1, $2, $3) "+ "ON CONFLICT (release, name) "+ "DO UPDATE SET url=$3 ", - release.id, - link.name, - link.url, + release.ID, + link.Name, + link.URL, ) if err != nil { return errors.New(fmt.Sprintf("Failed to add music link to transaction: %s", err)) } } - for _, credit := range release.credits { + for _, credit := range release.Credits { _, err = tx.Exec( "INSERT INTO musiccredits (release, artist, role, is_primary) "+ "VALUES ($1, $2, $3, $4) "+ "ON CONFLICT (release, artist) "+ "DO UPDATE SET role=$3, is_primary=$4", - release.id, - credit.artist.id, - credit.role, - credit.primary, + release.ID, + credit.Artist.ID, + credit.Role, + credit.Primary, ) if err != nil { return errors.New(fmt.Sprintf("Failed to add music credit to transaction: %s", err)) } } - for _, track := range release.tracks { + for _, track := range release.Tracks { _, err = tx.Exec( "INSERT INTO musictracks (release, number, title, description, lyrics, preview_url) "+ "VALUES ($1, $2, $3, $4, $5, $6) "+ "ON CONFLICT (release, number) "+ "DO UPDATE SET title=$3, description=$4, lyrics=$5, preview_url=$6", - release.id, - track.number, - track.title, - track.description, - track.lyrics, - track.previewURL, + release.ID, + track.Number, + track.Title, + track.Description, + track.Lyrics, + track.PreviewURL, ) if err != nil { return errors.New(fmt.Sprintf("Failed to add music track to transaction: %s", err)) @@ -310,7 +324,7 @@ func (release Release) DeleteFromDB(db *sqlx.DB) error { return errors.New(fmt.Sprintf("Failed to initiate transaction: %s", err)) } - _, err = tx.Exec("DELETE FROM musicreleases WHERE id=$1", release.id) + _, err = tx.Exec("DELETE FROM musicreleases WHERE id=$1", release.ID) err = tx.Commit() if err != nil { @@ -332,33 +346,33 @@ func PullAllReleases(db *sqlx.DB) ([]Release, error) { var release = Release{} err = rows.Scan( - &release.id, - &release.title, - &release.description, - &release.releaseType, - &release.releaseDate, - &release.artwork, - &release.buyname, - &release.buylink, + &release.ID, + &release.Title, + &release.Description, + &release.ReleaseType, + &release.ReleaseDate, + &release.Artwork, + &release.Buyname, + &release.Buylink, ) if err != nil { fmt.Printf("Error while pulling a release: %s\n", err) continue } - release.credits, err = PullReleaseCredits(db, release.id) + release.Credits, err = PullReleaseCredits(db, release.ID) if err != nil { - fmt.Printf("Failed to pull credits for %s: %v\n", release.id, err) + fmt.Printf("Failed to pull credits for %s: %v\n", release.ID, err) } - release.links, err = PullReleaseLinks(db, release.id) + release.Links, err = PullReleaseLinks(db, release.ID) if err != nil { - fmt.Printf("Failed to pull links for %s: %v\n", release.id, err) + fmt.Printf("Failed to pull links for %s: %v\n", release.ID, err) } - release.tracks, err = PullReleaseTracks(db, release.id) + release.Tracks, err = PullReleaseTracks(db, release.ID) if err != nil { - return nil, errors.New(fmt.Sprintf("error pulling tracks for %s: %v\n", release.id, err)) + return nil, errors.New(fmt.Sprintf("error pulling tracks for %s: %v\n", release.ID, err)) } releases = append(releases, release) @@ -366,3 +380,66 @@ func PullAllReleases(db *sqlx.DB) ([]Release, error) { return releases, nil } + +// HTTP HANDLERS + +func ServeRelease() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/" { + http.NotFound(w, r) + return + } + + releaseID := r.URL.Path[1:] + var release = GetRelease(releaseID) + if release == nil { + http.NotFound(w, r) + return + } + + // only allow authorised users to view unreleased releases + authorised := r.Context().Value("role") != nil && r.Context().Value("role") == "admin" + if !release.IsReleased() && !authorised { + admin.MustAuthorise(ServeRelease()).ServeHTTP(w, r) + return + } + + jsonBytes, err := json.Marshal(release) + if err != nil { + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + return + } + + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write(jsonBytes) + }) +} + +func PostRelease() http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.NotFound(w, r) + return + } + + var release Release + err := json.NewDecoder(r.Body).Decode(&release) + if err != nil { + http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) + return + } + + if GetRelease(release.ID) != nil { + http.Error(w, fmt.Sprintf("Release %s already exists", release.ID), http.StatusBadRequest) + return + } + + Releases = append(Releases, release) + + jsonBytes, err := json.Marshal(release) + w.Header().Add("Content-Type", "application/json") + w.WriteHeader(http.StatusCreated) + w.Write(jsonBytes) + }) +} diff --git a/api/v1/music/track.go b/api/v1/music/track.go index cda34ad..bb804e4 100644 --- a/api/v1/music/track.go +++ b/api/v1/music/track.go @@ -7,64 +7,64 @@ import ( ) type Track struct { - number int - title string - description string - lyrics string - previewURL string + Number int `json:"number"` + Title string `json:"title"` + Description string `json:"description"` + Lyrics string `json:"lyrics"` + PreviewURL string `json:"previewURL"` } // GETTERS func (track Track) GetNumber() int { - return track.number + return track.Number } func (track Track) GetTitle() string { - return track.title + return track.Title } func (track Track) GetDescription() string { - return track.description + return track.Description } func (track Track) GetLyrics() string { - return track.lyrics + return track.Lyrics } func (track Track) GetPreviewURL() string { - return track.previewURL + return track.PreviewURL } // SETTERS func (track Track) SetNumber(number int) error { // TODO: update DB - track.number = number + track.Number = number return nil } func (track Track) SetTitle(title string) error { // TODO: update DB - track.title = title + track.Title = title return nil } func (track Track) SetDescription(description string) error { // TODO: update DB - track.description = description + track.Description = description return nil } func (track Track) SetLyrics(lyrics string) error { // TODO: update DB - track.lyrics = lyrics + track.Lyrics = lyrics return nil } func (track Track) SetPreviewURL(previewURL string) error { // TODO: update DB - track.previewURL = previewURL + track.PreviewURL = previewURL return nil } @@ -82,11 +82,11 @@ func PullReleaseTracks(db *sqlx.DB, releaseID string) ([]Track, error) { var track = Track{} err = track_rows.Scan( - &track.number, - &track.title, - &track.description, - &track.lyrics, - &track.previewURL, + &track.Number, + &track.Title, + &track.Description, + &track.Lyrics, + &track.PreviewURL, ) if err != nil { fmt.Printf("Error while pulling track for release %s: %s\n", releaseID, err) diff --git a/main.go b/main.go index 385c1e7..dc609f6 100644 --- a/main.go +++ b/main.go @@ -46,6 +46,11 @@ func createServeMux() *http.ServeMux { mux.Handle("/api/v1/admin/", global.HTTPLog(http.StripPrefix("/api/v1/admin", admin.Handler()))) + mux.Handle("/api/v1/music/artist/", global.HTTPLog(http.StripPrefix("/api/v1/music/artist", music.ServeArtist()))) + mux.Handle("/api/v1/music/", global.HTTPLog(http.StripPrefix("/api/v1/music", music.ServeRelease()))) + mux.Handle("/api/v1/music", global.HTTPLog(music.PostRelease())) + + mux.Handle("/music-artwork/", global.HTTPLog(http.StripPrefix("/music-artwork", music.ServeArtwork()))) mux.Handle("/music/", global.HTTPLog(http.StripPrefix("/music", music.ServeGateway()))) mux.Handle("/music", global.HTTPLog(music.ServeCatalog())) @@ -54,15 +59,15 @@ func createServeMux() *http.ServeMux { global.ServeTemplate("index.html", nil).ServeHTTP(w, r) return } - staticHandler().ServeHTTP(w, r) + staticHandler("public").ServeHTTP(w, r) }))) return mux } -func staticHandler() http.Handler { +func staticHandler(directory string) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - info, err := os.Stat(filepath.Join("public", filepath.Clean(r.URL.Path))) + info, err := os.Stat(filepath.Join(directory, filepath.Clean(r.URL.Path))) // does the file exist? if err != nil { if os.IsNotExist(err) { diff --git a/public/img/music-artwork/default.png b/public/img/default-cover-art.png similarity index 100% rename from public/img/music-artwork/default.png rename to public/img/default-cover-art.png diff --git a/public/style/music-gateway.css b/public/style/music-gateway.css index 55ed16c..27df484 100644 --- a/public/style/music-gateway.css +++ b/public/style/music-gateway.css @@ -453,6 +453,12 @@ div#extras ul li a.active { background-color: var(--primary); } +#tracks summary::marker, +#tracks summary::-webkit-details-marker { + content: ""; + display: none; +} + footer { position: fixed; left: 0; diff --git a/schema.sql b/schema.sql index 7003f5c..7aa5ef7 100644 --- a/schema.sql +++ b/schema.sql @@ -61,10 +61,10 @@ ALTER TABLE musictracks ADD CONSTRAINT musictracks_pk PRIMARY KEY (release, numb -- Foreign keys -- -ALTER TABLE public.musiccredits ADD CONSTRAINT IF NOT EXISTS musiccredits_artist_fk FOREIGN KEY (artist) REFERENCES public.artists(id) ON DELETE CASCADE; +ALTER TABLE musiccredits ADD CONSTRAINT IF NOT EXISTS musiccredits_artist_fk FOREIGN KEY (artist) REFERENCES artists(id) ON DELETE CASCADE ON UPDATE CASCADE; -ALTER TABLE public.musiccredits ADD CONSTRAINT IF NOT EXISTS musiccredits_release_fk FOREIGN KEY (release) REFERENCES public.musicreleases(id) ON DELETE CASCADE; +ALTER TABLE musiccredits ADD CONSTRAINT IF NOT EXISTS musiccredits_release_fk FOREIGN KEY (release) REFERENCES musicreleases(id) ON DELETE CASCADE; -ALTER TABLE public.musiclinks ADD CONSTRAINT IF NOT EXISTS musiclinks_release_fk FOREIGN KEY (release) REFERENCES public.musicreleases(id) ON UPDATE CASCADE ON DELETE CASCADE; +ALTER TABLE musiclinks ADD CONSTRAINT IF NOT EXISTS musiclinks_release_fk FOREIGN KEY (release) REFERENCES musicreleases(id) ON UPDATE CASCADE ON DELETE CASCADE; -ALTER TABLE public.musictracks ADD CONSTRAINT IF NOT EXISTS musictracks_release_fk FOREIGN KEY (release) REFERENCES public.musicreleases(id) ON DELETE CASCADE; +ALTER TABLE musictracks ADD CONSTRAINT IF NOT EXISTS musictracks_release_fk FOREIGN KEY (release) REFERENCES musicreleases(id) ON DELETE CASCADE; diff --git a/views/music-gateway.html b/views/music-gateway.html index c713412..1cc9b7a 100644 --- a/views/music-gateway.html +++ b/views/music-gateway.html @@ -109,17 +109,16 @@ {{else}}

tracks:

- {{range .GetTracks}} + {{range $i, $track := .GetTracks}}
- {{.GetTitle}} - {{.GetLyrics}} + {{$i}}. {{$track.GetTitle}} + {{$track.GetLyrics}}
{{end}}
{{end}} - {{if or .GetCredits not .IsSingle}}
- {{end}}