github.com/jaredwarren/rpi_music@v0.1.2/server/song.go (about) 1 package server 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "html/template" 7 "net/http" 8 "strings" 9 10 "github.com/gorilla/mux" 11 "github.com/jaredwarren/rpi_music/log" 12 "github.com/jaredwarren/rpi_music/model" 13 "github.com/jaredwarren/rpi_music/player" 14 ) 15 16 // JSONHandler 17 func (s *Server) JSONHandler(w http.ResponseWriter, r *http.Request) { 18 w.Header().Set("Content-Type", "application/json") 19 vars := mux.Vars(r) 20 key := vars["song_id"] 21 if key == "" { 22 json.NewEncoder(w).Encode(map[string]string{ 23 "error": "song_id required", 24 }) 25 return 26 } 27 28 song, err := s.db.GetSong(key) 29 if err != nil { 30 json.NewEncoder(w).Encode(map[string]string{ 31 "error": err.Error(), 32 }) 33 return 34 } 35 if song == nil { 36 json.NewEncoder(w).Encode(map[string]string{ 37 "error": "song not found", 38 }) 39 return 40 } 41 json.NewEncoder(w).Encode(song) 42 } 43 44 func (s *Server) EditSongFormHandler(w http.ResponseWriter, r *http.Request) { 45 vars := mux.Vars(r) 46 key := vars["song_id"] 47 if key == "" { 48 s.httpError(w, fmt.Errorf("song_id required"), http.StatusBadRequest) 49 return 50 } 51 52 song, err := s.db.GetSong(key) 53 if err != nil { 54 s.httpError(w, fmt.Errorf("EditSongFormHandler|GetSong|%w", err), http.StatusBadRequest) 55 return 56 } 57 if song == nil { 58 s.httpError(w, fmt.Errorf("EditSongFormHandler|GetSong|%w", err), http.StatusBadRequest) 59 return 60 } 61 62 fullData := map[string]interface{}{ 63 "Song": song, 64 TemplateTag: s.GetToken(w, r), 65 } 66 67 files := []string{ 68 "templates/edit_song.html", 69 "templates/layout.html", 70 } 71 editSongFormTpl := template.Must(template.ParseFiles(files...)) 72 s.render(w, r, editSongFormTpl, fullData) 73 } 74 75 func (s *Server) ListSongHandler(w http.ResponseWriter, r *http.Request) { 76 cp := player.GetPlayer() 77 song := player.GetPlaying() 78 79 songs, err := s.db.ListSongs() 80 if err != nil { 81 s.httpError(w, fmt.Errorf("ListSongHandler|ListSongs|%w", err), http.StatusBadRequest) 82 return 83 } 84 fullData := map[string]interface{}{ 85 "Songs": songs, 86 "CurrentSong": song, 87 "Player": cp, 88 TemplateTag: s.GetToken(w, r), 89 } 90 91 // for now 92 files := []string{ 93 "templates/index.html", 94 "templates/layout.html", 95 } 96 homepageTpl := template.Must(template.ParseFiles(files...)) 97 98 s.render(w, r, homepageTpl, fullData) 99 } 100 101 func (s *Server) NewSongFormHandler(w http.ResponseWriter, r *http.Request) { 102 fullData := map[string]interface{}{ 103 "Song": model.NewSong(), 104 TemplateTag: s.GetToken(w, r), 105 } 106 files := []string{ 107 "templates/edit_song.html", 108 "templates/layout.html", 109 } 110 // TODO: maybe these would be better as objects 111 tpl := template.Must(template.New("base").ParseFiles(files...)) 112 s.render(w, r, tpl, fullData) 113 } 114 115 func (s *Server) NewSongHandler(w http.ResponseWriter, r *http.Request) { 116 err := r.ParseForm() 117 if err != nil { 118 s.httpError(w, fmt.Errorf("NewSongHandler|ParseForm|%w", err), http.StatusBadRequest) 119 return 120 } 121 s.logger.Info("NewSongHandler", log.Any("form", r.PostForm)) 122 123 url := r.PostForm.Get("url") 124 if url == "" { 125 s.httpError(w, fmt.Errorf("need url"), http.StatusBadRequest) 126 return 127 } 128 129 rfid := r.PostForm.Get("rfid") 130 if rfid == "" { 131 s.httpError(w, fmt.Errorf("need rfid"), http.StatusBadRequest) 132 return 133 } 134 135 rfid = strings.ReplaceAll(rfid, ":", "") 136 137 overwrite := true // TODO: make param, or config 138 if !overwrite { 139 // check for duplicates 140 exists, err := s.db.SongExists(rfid) 141 if err != nil { 142 s.httpError(w, fmt.Errorf("NewSongHandler|db.View|%w", err), http.StatusInternalServerError) 143 return 144 } 145 if exists { 146 // TODO: what to do here? 147 return 148 } 149 } 150 151 song := &model.Song{ 152 ID: rfid, 153 URL: url, 154 RFID: rfid, 155 } 156 157 // 1. Download song 158 file, video, err := s.downloader.DownloadVideo(url, s.logger) 159 if err != nil { 160 s.httpError(w, fmt.Errorf("NewSongHandler|downloadVideo|%w", err), http.StatusInternalServerError) 161 return 162 } 163 tmb, err := s.downloader.DownloadThumb(video) 164 if err != nil { 165 s.logger.Warn("NewSongHandler|downloadThumb", log.Error(err)) 166 // ignore err 167 } 168 169 song.Thumbnail = tmb 170 song.FilePath = file 171 song.Title = video.Title 172 173 // 2. Store 174 err = s.db.UpdateSong(song) 175 if err != nil { 176 s.httpError(w, fmt.Errorf("NewSongHandler|db.Update|%w", err), http.StatusInternalServerError) 177 return 178 } 179 180 http.Redirect(w, r, "/songs", 301) 181 } 182 183 func (s *Server) UpdateSongHandler(w http.ResponseWriter, r *http.Request) { 184 vars := mux.Vars(r) 185 key := vars["song_id"] 186 if key == "" { 187 s.httpError(w, fmt.Errorf("no key"), http.StatusBadRequest) 188 return 189 } 190 s.logger.Info("UpdateSongHandler", log.Any("form", r.PostForm)) 191 192 err := r.ParseForm() 193 if err != nil { 194 s.httpError(w, fmt.Errorf("UpdateSongHandler|ParseForm|%w", err), http.StatusBadRequest) 195 return 196 } 197 198 url := r.PostForm.Get("url") 199 rfid := r.PostForm.Get("rfid") 200 rfid = strings.ReplaceAll(rfid, ":", "") 201 202 // Delete if blank 203 if rfid == "" || url == "" { 204 err := s.db.DeleteSong(key) 205 if err != nil { 206 s.httpError(w, fmt.Errorf("UpdateSongHandler|db.Update|%w", err), http.StatusInternalServerError) 207 return 208 } 209 return 210 } 211 212 song := &model.Song{ 213 ID: rfid, 214 URL: url, 215 RFID: rfid, 216 } 217 218 // try to download file again 219 file, video, err := s.downloader.DownloadVideo(url, s.logger) 220 if err != nil { 221 s.httpError(w, fmt.Errorf("UpdateSongHandler|downloadVideo|%w", err), http.StatusInternalServerError) 222 return 223 } 224 tmb, err := s.downloader.DownloadThumb(video) 225 if err != nil { 226 s.logger.Warn("UpdateSongHandler|downloadThumb", log.Error(err)) 227 // ignore err 228 } 229 230 song.Thumbnail = tmb 231 song.FilePath = file 232 song.Title = video.Title 233 234 // delete old key if rfid id different then key 235 if key != rfid { 236 err := s.db.DeleteSong(key) 237 if err != nil { 238 s.httpError(w, fmt.Errorf("UpdateSongHandler|db.Update|%w", err), http.StatusInternalServerError) 239 return 240 } 241 } 242 243 // Update otherwise 244 err = s.db.UpdateSong(song) 245 if err != nil { 246 s.httpError(w, fmt.Errorf("UpdateSongHandler|db.Update|%w", err), http.StatusInternalServerError) 247 return 248 } 249 250 http.Redirect(w, r, "/songs", 301) 251 } 252 253 func (s *Server) DeleteSongHandler(w http.ResponseWriter, r *http.Request) { 254 vars := mux.Vars(r) 255 key := vars["song_id"] 256 if key == "" { 257 s.httpError(w, fmt.Errorf("no key"), http.StatusBadRequest) 258 return 259 } 260 err := s.db.DeleteSong(key) 261 if err != nil { 262 s.httpError(w, fmt.Errorf("DeleteSongHandler|db.Update|%w", err), http.StatusInternalServerError) 263 return 264 } 265 http.Redirect(w, r, "/songs", 301) 266 } 267 268 func (s *Server) PlayVideoHandler(w http.ResponseWriter, r *http.Request) { 269 s.logger.Info("PlayVideoHandler") 270 271 vars := mux.Vars(r) 272 key := vars["song_id"] 273 if key == "" { 274 s.httpError(w, fmt.Errorf("song_id required"), http.StatusBadRequest) 275 return 276 } 277 278 song, err := s.db.GetSong(key) 279 if err != nil { 280 s.httpError(w, fmt.Errorf("EditSongFormHandler|GetSong|%w", err), http.StatusBadRequest) 281 return 282 } 283 if song == nil { 284 s.httpError(w, fmt.Errorf("EditSongFormHandler|GetSong|%w", err), http.StatusBadRequest) 285 return 286 } 287 288 fullData := map[string]interface{}{ 289 "Song": song, 290 TemplateTag: s.GetToken(w, r), 291 } 292 293 files := []string{ 294 "templates/play_video.html", 295 "templates/layout.html", 296 } 297 tpl := template.Must(template.New("base").Funcs(template.FuncMap{}).ParseFiles(files...)) 298 s.render(w, r, tpl, fullData) 299 }