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  }