package http import ( "dwelling-radio/internal/radio" "dwelling-radio/pkg/oggtag" "encoding/json" "fmt" "log" "net/http" "time" ) type DJHandlers struct { listeners *radio.ListenerCounter playlist *radio.Playlist songList *radio.SongList mostLSong *radio.MostListenedSong fallbackSong string } func NewDJHandlers(l *radio.ListenerCounter, p *radio.Playlist, sl *radio.SongList, mls *radio.MostListenedSong, fS string) *DJHandlers { return &DJHandlers{listeners: l, playlist: p, songList: sl, mostLSong: mls, fallbackSong: fS} } func (dj *DJHandlers) ListenersGet(w http.ResponseWriter, _ *http.Request) { w.Header().Add("Content-Type", "application/json") json.NewEncoder(w).Encode(dj.listeners) } func (dj *DJHandlers) ListenersInc(w http.ResponseWriter, _ *http.Request) { l := dj.listeners.Inc() go dj.songList.UpdateCurrentMaxListeners(l) w.WriteHeader(http.StatusCreated) w.Header().Add("Content-Type", "text/plain") fmt.Fprint(w, l) } func (dj *DJHandlers) ListenersDec(w http.ResponseWriter, _ *http.Request) { l, err := dj.listeners.Dec() if err != nil { log.Print(err) http.Error(w, err.Error(), http.StatusBadRequest) return } w.WriteHeader(http.StatusOK) w.Header().Add("Content-Type", "text/plain") fmt.Fprint(w, l) } func (dj *DJHandlers) PlaylistNext(w http.ResponseWriter, _ *http.Request) { w.Header().Add("Content-Type", "text/plain") nxt := dj.playlist.Next() if nxt == "" { log.Println("the end of a playlist has been reached") if nxt = dj.fallbackSong; nxt == "" { log.Println("a fallback song is not set") http.Error(w, "a playlist is empty and a fallback song is not set", http.StatusNotFound) return } } go func() { oggf, err := oggtag.NewOggFile(nxt) if err != nil { log.Println("cannot read an OGG file", nxt, ":", err) http.Error(w, "cannot read an OGG file", http.StatusInternalServerError) return } song := radio.Song{ Artist: oggf.GetTag("artist"), Title: oggf.GetTag("title"), Duration: oggf.GetDuration(), MaxListeners: dj.listeners.Current(), StartAt: time.Now()} if dj.songList.Current() != nil { dj.mostLSong.Update(*dj.songList.Current()) } dj.songList.Add(song) }() fmt.Fprintln(w, nxt) } func (dj *DJHandlers) Song(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "application/json") err := json.NewEncoder(w).Encode(dj.songList.Current()) if err != nil { log.Println("DJHandlers.Song:", err) http.Error(w, "cannot obtain current song", http.StatusInternalServerError) } } func (dj *DJHandlers) Songs(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "application/json") err := json.NewEncoder(w).Encode(dj.songList.List()) if err != nil { log.Println("DJHandlers.Songs:", err) http.Error(w, "cannot obtain list of last songs", http.StatusInternalServerError) } } func (dj *DJHandlers) Status(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "application/json") var curSong *radio.Song = nil if dj.songList.Current() != nil { curSong = &radio.Song{} *curSong = *dj.songList.Current() } err := json.NewEncoder(w).Encode(&struct { Current *radio.Song `json:"current_song,omitempty"` Listeners *radio.ListenerCounter `json:"listeners"` List []radio.Song `json:"last_songs,omitempty"` Mls *radio.MostListenedSong `json:"most_listened_song,omitempty"` }{ Current: curSong, Listeners: dj.listeners, List: dj.songList.List(), Mls: dj.mostLSong.Get()}) if err != nil { log.Println("DJHandlers.Status:", err) http.Error(w, "status parsing failed", http.StatusInternalServerError) } } func (dj *DJHandlers) MostListenedSong(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "application/json") mls := dj.mostLSong.Get() if mls == nil { w.WriteHeader(http.StatusNotFound) return } err := json.NewEncoder(w).Encode(mls) if err != nil { log.Println("DJHandlers.MostListenedSong:", err) http.Error(w, "MostListenedSong parsing failed", http.StatusInternalServerError) } }