From 8b4335c18752ce96e452dc232e57695c2fdf6a6d Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Thu, 21 Jul 2022 21:14:14 +0200 Subject: intermediate commit * add dummy backend * enable spotify searching * JS: use let instead of var * improve logging * support adding new songs from search * rename Song.Id to Song.Uri --- dummyBackend.go | 29 ++++++++++++++++++++ main.go | 31 +++++++++++++++++----- player.go | 2 ++ spotify.go | 24 +++++++++++++++++ web/client.html | 82 ++++++++++++++++++++++++++++++++++++++++++++------------- wrms.go | 45 +++++++++++++++++-------------- 6 files changed, 169 insertions(+), 44 deletions(-) create mode 100644 dummyBackend.go diff --git a/dummyBackend.go b/dummyBackend.go new file mode 100644 index 0000000..f2eae57 --- /dev/null +++ b/dummyBackend.go @@ -0,0 +1,29 @@ +package main + +import ( + "crypto/sha1" + "encoding/base64" +) + +type DummyBackend struct{} + +func (dummy *DummyBackend) Play(song Song) { +} + +func (dummy *DummyBackend) Pause() { +} + +func (dummy *DummyBackend) Search(keyword string) []Song { + + s := NewDummySong("Dummy Mc Crashtest", "exactly "+keyword) + return []Song{s} +} + +func NewDummySong(title string, artist string) Song { + s := Song{title, artist, "dummy", "", 0, 0, map[string]struct{}{}, map[string]struct{}{}} + h := sha1.New() + h.Write([]byte(title)) + h.Write([]byte(artist)) + s.Uri = base64.URLEncoding.EncodeToString(h.Sum(nil)) + return s +} diff --git a/main.go b/main.go index 9c89693..657b211 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "html/template" + "io/ioutil" "log" "net/http" @@ -40,6 +41,8 @@ func searchHandler(w http.ResponseWriter, r *http.Request) { log.Fatal(err) return } + + log.Println("Search returned", string(data)) w.Write(data) } @@ -51,9 +54,9 @@ func genericVoteHandler(w http.ResponseWriter, r *http.Request, vote string) { } connId := uuidCookie.Value - songId := r.URL.Query().Get("song") - log.Println("%s song %s via url %s", vote, songId, r.URL) - wrms.AdjustSongWeight(connId, songId, vote) + songUri := r.URL.Query().Get("song") + log.Println("%s song %s via url %s", vote, songUri, r.URL) + wrms.AdjustSongWeight(connId, songUri, vote) } func upHandler(w http.ResponseWriter, r *http.Request) { @@ -69,7 +72,23 @@ func unvoteHandler(w http.ResponseWriter, r *http.Request) { } func addHandler(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "Added") + data, err := ioutil.ReadAll(r.Body) + if err != nil { + log.Println("Failed to read request body", string(data)) + http.Error(w, "Failed to read request body", http.StatusInternalServerError) + return + } + + song, err := NewSongFromJson(data) + if err != nil { + http.Error(w, "Could not parse song", http.StatusBadRequest) + return + } + + log.Println(fmt.Sprintf("Added song %s", string(data))) + wrms.AddSong(song) + wrms.Broadcast(Event{"add", []Song{song}}) + fmt.Fprintf(w, "Added song %s", string(data)) } func playPauseHandler(w http.ResponseWriter, r *http.Request) { @@ -163,8 +182,8 @@ func setupRoutes() { func main() { setupRoutes() - wrms.AddSong(NewSong("Lala", "SNFMT", "local")) - wrms.AddSong(NewSong("Hobelbank", "MC Wankwichtel", "local")) + wrms.AddSong(NewDummySong("Lala", "SNFMT")) + wrms.AddSong(NewDummySong("Hobelbank", "MC Wankwichtel")) log.Println(wrms) defer wrms.Close() diff --git a/player.go b/player.go index 1f5967d..d46311f 100644 --- a/player.go +++ b/player.go @@ -24,6 +24,8 @@ func NewPlayer() Player { } available_backends["spotify"] = spotify + available_backends["dummy"] = &DummyBackend{} + return Player{available_backends} } diff --git a/spotify.go b/spotify.go index a813254..a4d8080 100644 --- a/spotify.go +++ b/spotify.go @@ -9,6 +9,7 @@ package main import ( "errors" + "fmt" "os" // "github.com/librespot-org/librespot-golang/Spotify" @@ -64,6 +65,29 @@ func (spotify *SpotifyBackend) Pause() { } func (spotify *SpotifyBackend) Search(keyword string) []Song { + session := spotify.session + resp, err := session.Mercury().Search(keyword, 12, session.Country(), session.Username()) + + if err != nil { + fmt.Println("Failed to search:", err) + return []Song{} + } + + res := resp.Results + + fmt.Println("Search results for ", keyword) + fmt.Println("=============================") + + if res.Error != nil { + fmt.Println("Search result error:", res.Error) + } + + fmt.Printf("\nTracks: %d (total %d)\n", len(res.Tracks.Hits), res.Tracks.Total) + + for _, track := range res.Tracks.Hits { + fmt.Printf(" => %v (%s)\n", track, track.Uri) + } + return []Song{} } diff --git a/web/client.html b/web/client.html index 8e3faab..38e1652 100644 --- a/web/client.html +++ b/web/client.html @@ -45,17 +45,27 @@ @@ -214,6 +255,11 @@ + +

Playing

diff --git a/wrms.go b/wrms.go index b648744..f7a7395 100644 --- a/wrms.go +++ b/wrms.go @@ -1,8 +1,7 @@ package main import ( - "crypto/sha1" - "encoding/base64" + "encoding/json" "fmt" "log" @@ -15,21 +14,24 @@ type Song struct { Title string `json:"title"` Artist string `json:"artist"` Source string `json:"source"` - Id string `json:"id"` + Uri string `json:"uri"` Weight int `json:"weight"` index int `json:"-"` // used by heap.Interface Upvotes map[string]struct{} `json:"-"` Downvotes map[string]struct{} `json:"-"` } -func NewSong(title string, artist string, source string) Song { - s := Song{title, artist, source, "", 0, 0, map[string]struct{}{}, map[string]struct{}{}} - h := sha1.New() - h.Write([]byte(title)) - h.Write([]byte(artist)) - h.Write([]byte(source)) - s.Id = base64.URLEncoding.EncodeToString(h.Sum(nil)) - return s +func NewSongFromJson(data []byte) (Song, error) { + var s Song + err := json.Unmarshal(data, &s) + if err != nil { + log.Println(fmt.Sprintf("Failed to parse song data %s with %s", string(data), err)) + return s, err + } + + s.Upvotes = map[string]struct{}{} + s.Downvotes = map[string]struct{}{} + return s, nil } type Event struct { @@ -79,15 +81,17 @@ func (wrms *Wrms) Broadcast(cmd Event) { func (wrms *Wrms) AddSong(song Song) { wrms.Songs = append(wrms.Songs, song) - wrms.Queue.Add(&wrms.Songs[len(wrms.Songs) - 1]) + s := &wrms.Songs[len(wrms.Songs)-1] + wrms.Queue.Add(s) + log.Println(fmt.Sprintf("Added song %s (ptr=%p) to Songs", s.Uri, s)) } func (wrms *Wrms) Next() { wrms.CurrentSong = wrms.Queue.PopSong() for i, s := range wrms.Songs { - if s.Id == wrms.CurrentSong.Id { - wrms.Songs[i] = wrms.Songs[len(wrms.Songs) - 1] - wrms.Songs = wrms.Songs[:len(wrms.Songs) - 1] + if s.Uri == wrms.CurrentSong.Uri { + wrms.Songs[i] = wrms.Songs[len(wrms.Songs)-1] + wrms.Songs = wrms.Songs[:len(wrms.Songs)-1] break } } @@ -109,17 +113,18 @@ func (wrms *Wrms) PlayPause() { wrms.Broadcast(ev) } -func (wrms *Wrms) AdjustSongWeight(connId string, songId string, vote string) { +func (wrms *Wrms) AdjustSongWeight(connId string, songUri string, vote string) { for i := 0; i < len(wrms.Songs); i++ { s := &wrms.Songs[i] - if s.Id != songId { + if s.Uri != songUri { continue } + log.Println(fmt.Sprintf("Adjusting song %s (ptr=%p)", s.Uri, s)) switch vote { case "up": if _, ok := s.Upvotes[connId]; ok { - log.Println(fmt.Sprintf("Double upvote of song %s by connections %s", songId, connId)) + log.Println(fmt.Sprintf("Double upvote of song %s by connections %s", songUri, connId)) return } @@ -134,7 +139,7 @@ func (wrms *Wrms) AdjustSongWeight(connId string, songId string, vote string) { case "down": if _, ok := s.Downvotes[connId]; ok { - log.Println(fmt.Sprintf("Double downvote of song %s by connections %s", songId, connId)) + log.Println(fmt.Sprintf("Double downvote of song %s by connections %s", songUri, connId)) return } @@ -157,7 +162,7 @@ func (wrms *Wrms) AdjustSongWeight(connId string, songId string, vote string) { delete(s.Upvotes, connId) s.Weight -= 1 } else { - log.Println(fmt.Sprintf("Double downvote of song %s by connections %s", songId, connId)) + log.Println(fmt.Sprintf("Double downvote of song %s by connections %s", songUri, connId)) return } -- cgit v1.2.3