package web import ( "net/http" "git.noroutes.net/NoRoutes/vibetunes/internal/auth" "git.noroutes.net/NoRoutes/vibetunes/internal/database" ) func (h *Web) handlePlaylists(w http.ResponseWriter, r *http.Request) { user := auth.UserFromContext(r.Context()) playlists, err := database.ListPlaylistsVisibleToUser(h.DB, user.ID) if err != nil { http.Error(w, "internal error", http.StatusInternalServerError) return } h.page(w, r, "playlists", "playlists", "Playlists", playlists) } func (h *Web) handlePlaylistCreate(w http.ResponseWriter, r *http.Request) { user := auth.UserFromContext(r.Context()) if err := r.ParseForm(); err != nil { http.Error(w, "bad request", http.StatusBadRequest) return } name := r.FormValue("name") if name == "" { http.Redirect(w, r, "/playlists", http.StatusFound) return } if _, err := database.CreatePlaylist(h.DB, user.ID, name, "", false); err != nil { http.Error(w, "internal error", http.StatusInternalServerError) return } http.Redirect(w, r, "/playlists", http.StatusFound) } func (h *Web) handlePlaylist(w http.ResponseWriter, r *http.Request) { user := auth.UserFromContext(r.Context()) id := r.PathValue("id") playlist, err := database.GetPlaylist(h.DB, id) if err != nil { http.NotFound(w, r) return } if playlist.OwnerID != user.ID && !playlist.IsPublic { http.Error(w, "403 Forbidden", http.StatusForbidden) return } entries, err := database.ListPlaylistEntries(h.DB, id) if err != nil { http.Error(w, "internal error", http.StatusInternalServerError) return } var rows []SongRow for _, e := range entries { song, err := database.GetSong(h.DB, e.SongID) if err != nil { continue } rows = append(rows, toSongRow(h.DB, song, albumOf(h.DB, song), user.ID)) } h.page(w, r, "playlist", "playlists", playlist.Name, struct { Playlist *database.Playlist Songs []SongRow Owned bool }{playlist, rows, playlist.OwnerID == user.ID}) } func (h *Web) handlePlaylistDelete(w http.ResponseWriter, r *http.Request) { user := auth.UserFromContext(r.Context()) id := r.PathValue("id") playlist, err := database.GetPlaylist(h.DB, id) if err != nil { http.NotFound(w, r) return } if playlist.OwnerID != user.ID { http.Error(w, "403 Forbidden", http.StatusForbidden) return } if err := database.DeletePlaylist(h.DB, id); err != nil { http.Error(w, "internal error", http.StatusInternalServerError) return } http.Redirect(w, r, "/playlists", http.StatusFound) } func (h *Web) handleFavorites(w http.ResponseWriter, r *http.Request) { user := auth.UserFromContext(r.Context()) artistIDs, _ := database.ListStarredIDs(h.DB, user.ID, "artist") var artists []ArtistView for _, id := range artistIDs { if a, err := database.GetArtist(h.DB, id); err == nil { artists = append(artists, toArtistView(a)) } } albumIDs, _ := database.ListStarredIDs(h.DB, user.ID, "album") var albums []AlbumView for _, id := range albumIDs { if a, err := database.GetAlbum(h.DB, id); err == nil { albums = append(albums, toAlbumView(h.DB, a)) } } songIDs, _ := database.ListStarredIDs(h.DB, user.ID, "song") var songs []SongRow for _, id := range songIDs { if s, err := database.GetSong(h.DB, id); err == nil { songs = append(songs, toSongRow(h.DB, s, albumOf(h.DB, s), user.ID)) } } h.page(w, r, "favorites", "favorites", "Favorites", struct { Artists []ArtistView Albums []AlbumView Songs []SongRow }{artists, albums, songs}) } func (h *Web) handleFavoriteStar(w http.ResponseWriter, r *http.Request) { h.setFavorite(w, r, true) } func (h *Web) handleFavoriteUnstar(w http.ResponseWriter, r *http.Request) { h.setFavorite(w, r, false) } func (h *Web) setFavorite(w http.ResponseWriter, r *http.Request, star bool) { user := auth.UserFromContext(r.Context()) if err := r.ParseForm(); err != nil { http.Error(w, "bad request", http.StatusBadRequest) return } itemType := r.FormValue("item_type") itemID := r.FormValue("item_id") next := safeRedirectPath(r.FormValue("next")) switch itemType { case "song", "album", "artist": default: http.Error(w, "bad request", http.StatusBadRequest) return } var err error if star { err = database.Star(h.DB, user.ID, itemType, itemID) } else { err = database.Unstar(h.DB, user.ID, itemType, itemID) } if err != nil { http.Error(w, "internal error", http.StatusInternalServerError) return } http.Redirect(w, r, next, http.StatusFound) } func (h *Web) handleRecent(w http.ResponseWriter, r *http.Request) { user := auth.UserFromContext(r.Context()) history, err := database.ListRecentlyPlayed(h.DB, user.ID, 100) if err != nil { http.Error(w, "internal error", http.StatusInternalServerError) return } var rows []SongRow seen := map[string]bool{} for _, entry := range history { if seen[entry.SongID] { continue } seen[entry.SongID] = true song, err := database.GetSong(h.DB, entry.SongID) if err != nil { continue } rows = append(rows, toSongRow(h.DB, song, albumOf(h.DB, song), user.ID)) } h.page(w, r, "recent", "recent", "Recently Played", rows) }