Sfoglia il codice sorgente

feat: routes to get next and previous song info

Fela Maslen 5 anni fa
parent
commit
3e6e3a468f

+ 8 - 0
gmus-backend/README.md

@@ -71,3 +71,11 @@ Fetches songs for a particular artist, and outputs them in JSON format.
 #### `GET /song-info?id=<id>`
 
 Fetches info for a particular song, based on its ID, and outputs it in JSON format.
+
+#### `GET /next-song?id=<id>`
+
+Fetches next song info.
+
+#### `GET /prev-song?id=<id>`
+
+Fetches previous song info.

+ 82 - 7
gmus-backend/pkg/server/fetch.go

@@ -10,6 +10,7 @@ import (
 	"github.com/felamaslen/gmus-backend/pkg/read"
 	"github.com/felamaslen/gmus-backend/pkg/repository"
 	"github.com/go-redis/redis/v7"
+	"github.com/jmoiron/sqlx"
 )
 
 type ArtistsResponse struct {
@@ -88,21 +89,26 @@ func routeFetchSongs(l *logger.Logger, rdb *redis.Client, w http.ResponseWriter,
 	return nil
 }
 
-func routeFetchSongInfo(l *logger.Logger, rdb *redis.Client, w http.ResponseWriter, r *http.Request) error {
+func validateSongId(w http.ResponseWriter, r *http.Request) (id int, err error) {
 	idRaw := r.URL.Query().Get("id")
-	idInt, err := strconv.Atoi(idRaw)
+	id, err = strconv.Atoi(idRaw)
 	if err != nil {
 		http.Error(w, "Must provide a valid id", http.StatusBadRequest)
-		return nil
-	}
-	if idInt < 1 {
+	} else if id < 1 {
 		http.Error(w, "id must be non-negative", http.StatusBadRequest)
+	}
+	return
+}
+
+func routeFetchSongInfo(l *logger.Logger, rdb *redis.Client, w http.ResponseWriter, r *http.Request) error {
+	id, err := validateSongId(w, r)
+	if err != nil {
 		return nil
 	}
 
 	db := database.GetConnection()
 
-	song, err := repository.SelectSong(db, idInt)
+	song, err := repository.SelectSong(db, id)
 	if err != nil {
 		if err.Error() == "No such ID" {
 			http.Error(w, "Song not found", http.StatusNotFound)
@@ -112,7 +118,7 @@ func routeFetchSongInfo(l *logger.Logger, rdb *redis.Client, w http.ResponseWrit
 	}
 
 	response, err := json.Marshal(read.SongExternal{
-		Id:          idInt,
+		Id:          id,
 		TrackNumber: song.TrackNumber,
 		Title:       song.Title,
 		Artist:      song.Artist,
@@ -126,3 +132,72 @@ func routeFetchSongInfo(l *logger.Logger, rdb *redis.Client, w http.ResponseWrit
 	w.Write(response)
 	return nil
 }
+
+type NullResponse struct {
+	Id int `json:"id"`
+}
+
+func respondWithSongOrNull(db *sqlx.DB, w http.ResponseWriter, id int) error {
+	if id == 0 {
+		response, _ := json.Marshal(NullResponse{})
+		w.Write(response)
+		return nil
+	}
+
+	song, err := repository.SelectSong(db, id)
+	if err != nil {
+		return err
+	}
+
+	response, err := json.Marshal(read.SongExternal{
+		Id:          id,
+		TrackNumber: song.TrackNumber,
+		Title:       song.Title,
+		Artist:      song.Artist,
+		Album:       song.Album,
+		Duration:    song.Duration,
+	})
+
+	if err != nil {
+		return err
+	}
+
+	w.Write(response)
+	return nil
+}
+
+func routeFetchNextSongId(l *logger.Logger, rdb *redis.Client, w http.ResponseWriter, r *http.Request) error {
+	id, err := validateSongId(w, r)
+	if err != nil {
+		return nil
+	}
+
+	db := database.GetConnection()
+	nextId, err := repository.GetNextSongId(db, int64(id))
+	if err != nil {
+		return err
+	}
+
+	if err := respondWithSongOrNull(db, w, int(nextId)); err != nil {
+		return err
+	}
+	return nil
+}
+
+func routeFetchPrevSongId(l *logger.Logger, rdb *redis.Client, w http.ResponseWriter, r *http.Request) error {
+	id, err := validateSongId(w, r)
+	if err != nil {
+		return nil
+	}
+
+	db := database.GetConnection()
+	prevId, err := repository.GetPrevSongId(db, int64(id))
+	if err != nil {
+		return err
+	}
+
+	if err := respondWithSongOrNull(db, w, int(prevId)); err != nil {
+		return err
+	}
+	return nil
+}

+ 3 - 0
gmus-backend/pkg/server/server.go

@@ -31,6 +31,9 @@ func StartServer() {
 
 	router.Path("/song-info").Methods("GET").HandlerFunc(routeHandler(l, rdb, routeFetchSongInfo))
 
+	router.Path("/next-song").Methods("GET").HandlerFunc(routeHandler(l, rdb, routeFetchNextSongId))
+	router.Path("/prev-song").Methods("GET").HandlerFunc(routeHandler(l, rdb, routeFetchPrevSongId))
+
 	port := conf.Port
 
 	handler := cors.AllowAll().Handler(router)