fetch.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. package server
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "strconv"
  6. "github.com/felamaslen/gmus-backend/pkg/database"
  7. "github.com/felamaslen/gmus-backend/pkg/logger"
  8. "github.com/felamaslen/gmus-backend/pkg/read"
  9. "github.com/felamaslen/gmus-backend/pkg/repository"
  10. "github.com/go-redis/redis/v7"
  11. "github.com/jmoiron/sqlx"
  12. )
  13. type ArtistsResponse struct {
  14. Artists []string `json:"artists"`
  15. }
  16. func routeFetchArtists(l *logger.Logger, rdb *redis.Client, w http.ResponseWriter, r *http.Request) error {
  17. db := database.GetConnection()
  18. artists, err := repository.SelectAllArtists(db)
  19. if err != nil {
  20. return err
  21. }
  22. response, err := json.Marshal(ArtistsResponse{
  23. Artists: *artists,
  24. })
  25. if err != nil {
  26. return err
  27. }
  28. w.Write(response)
  29. return nil
  30. }
  31. type AlbumsResponse struct {
  32. Artist string `json:"artist"`
  33. Albums []string `json:"albums"`
  34. }
  35. func routeFetchAlbums(l *logger.Logger, rdb *redis.Client, w http.ResponseWriter, r *http.Request) error {
  36. artist := r.URL.Query().Get("artist")
  37. db := database.GetConnection()
  38. albums, err := repository.SelectAlbumsByArtist(db, artist)
  39. if err != nil {
  40. return err
  41. }
  42. response, err := json.Marshal(AlbumsResponse{
  43. Artist: artist,
  44. Albums: *albums,
  45. })
  46. if err != nil {
  47. return err
  48. }
  49. w.Write(response)
  50. return nil
  51. }
  52. type SongsResponse struct {
  53. Artist string `json:"artist"`
  54. Songs *[]*read.SongExternal `json:"songs"`
  55. }
  56. func routeFetchSongs(l *logger.Logger, rdb *redis.Client, w http.ResponseWriter, r *http.Request) error {
  57. artist := r.URL.Query().Get("artist")
  58. db := database.GetConnection()
  59. songs, err := repository.SelectSongsByArtist(db, artist)
  60. if err != nil {
  61. return err
  62. }
  63. response, err := json.Marshal(SongsResponse{
  64. Artist: artist,
  65. Songs: songs,
  66. })
  67. if err != nil {
  68. return err
  69. }
  70. w.Write(response)
  71. return nil
  72. }
  73. func validateSongId(w http.ResponseWriter, r *http.Request) (id int, err error) {
  74. idRaw := r.URL.Query().Get("id")
  75. id, err = strconv.Atoi(idRaw)
  76. if err != nil {
  77. http.Error(w, "Must provide a valid id", http.StatusBadRequest)
  78. } else if id < 1 {
  79. http.Error(w, "id must be non-negative", http.StatusBadRequest)
  80. }
  81. return
  82. }
  83. func routeFetchSongInfo(l *logger.Logger, rdb *redis.Client, w http.ResponseWriter, r *http.Request) error {
  84. id, err := validateSongId(w, r)
  85. if err != nil {
  86. return nil
  87. }
  88. db := database.GetConnection()
  89. song, err := repository.SelectSong(db, id)
  90. if err != nil {
  91. if err.Error() == "No such ID" {
  92. http.Error(w, "Song not found", http.StatusNotFound)
  93. return nil
  94. }
  95. return err
  96. }
  97. response, err := json.Marshal(read.SongExternal{
  98. Id: id,
  99. TrackNumber: song.TrackNumber,
  100. Title: song.Title,
  101. Artist: song.Artist,
  102. Album: song.Album,
  103. Duration: song.Duration,
  104. })
  105. if err != nil {
  106. return err
  107. }
  108. w.Write(response)
  109. return nil
  110. }
  111. type NullResponse struct {
  112. Id int `json:"id"`
  113. }
  114. func respondWithSongOrNull(db *sqlx.DB, w http.ResponseWriter, id int) error {
  115. if id == 0 {
  116. response, _ := json.Marshal(NullResponse{})
  117. w.Write(response)
  118. return nil
  119. }
  120. song, err := repository.SelectSong(db, id)
  121. if err != nil {
  122. return err
  123. }
  124. response, err := json.Marshal(read.SongExternal{
  125. Id: id,
  126. TrackNumber: song.TrackNumber,
  127. Title: song.Title,
  128. Artist: song.Artist,
  129. Album: song.Album,
  130. Duration: song.Duration,
  131. })
  132. if err != nil {
  133. return err
  134. }
  135. w.Write(response)
  136. return nil
  137. }
  138. func routeFetchNextSongId(l *logger.Logger, rdb *redis.Client, w http.ResponseWriter, r *http.Request) error {
  139. id, err := validateSongId(w, r)
  140. if err != nil {
  141. return nil
  142. }
  143. db := database.GetConnection()
  144. nextId, err := repository.GetNextSongId(db, int64(id))
  145. if err != nil {
  146. return err
  147. }
  148. if err := respondWithSongOrNull(db, w, int(nextId)); err != nil {
  149. return err
  150. }
  151. return nil
  152. }
  153. func routeFetchPrevSongId(l *logger.Logger, rdb *redis.Client, w http.ResponseWriter, r *http.Request) error {
  154. id, err := validateSongId(w, r)
  155. if err != nil {
  156. return nil
  157. }
  158. db := database.GetConnection()
  159. prevId, err := repository.GetPrevSongId(db, int64(id))
  160. if err != nil {
  161. return err
  162. }
  163. if err := respondWithSongOrNull(db, w, int(prevId)); err != nil {
  164. return err
  165. }
  166. return nil
  167. }