From cef46aa5f5b9cac5c43bd842ed64580357718e86 Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Sun, 21 May 2023 13:45:15 +0200 Subject: implement the upload backend --- .gitignore | 1 + TODO | 3 +++ player.go | 4 ++- upload.go | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ web/client.html | 19 +++++++++++++ 5 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 upload.go diff --git a/.gitignore b/.gitignore index 9490ce8..f816994 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ wrms +uploads diff --git a/TODO b/TODO index f9fc0b9..4e33df8 100644 --- a/TODO +++ b/TODO @@ -6,7 +6,10 @@ ## Backends +- [ ] Split paralyze search - [X] Implement local storage backend + - [X] Implement upload + - [ ] Remove uploaded songs after were played - [X] Fix youtube search ## Configuration diff --git a/player.go b/player.go index d5fe270..3cee6b4 100644 --- a/player.go +++ b/player.go @@ -28,7 +28,9 @@ func NewPlayer(wrms *Wrms, backends []string) Player { case "dummy": b = &DummyBackend{} case "local": - b = NewLocalBackend(wrms.Config.localMusicDir) + b = NewLocalBackend(wrms.Config.LocalMusicDir) + case "upload": + b = NewUploadBackend(wrms.Config.UploadDir) default: llog.Error("Not supported backend %s", backend) } diff --git a/upload.go b/upload.go new file mode 100644 index 0000000..d7bbd20 --- /dev/null +++ b/upload.go @@ -0,0 +1,83 @@ +package main + +import ( + "bytes" + "fmt" + "net/http" + "os" + "path" + // "path/filepath" + "io/ioutil" + + "github.com/dhowden/tag" + "muhq.space/go/wrms/llog" +) + +type UploadBackend struct { + uploadDir string +} + +func NewUploadBackend(uploadDir string) *UploadBackend { + b := UploadBackend{uploadDir: uploadDir} + + dirInfo, err := os.Stat(uploadDir) + + if os.IsNotExist(err) { + os.Mkdir(uploadDir, 0750) + } else if !dirInfo.IsDir() { + llog.Fatal("upload directory %s exists and is not a directory", uploadDir) + } + + b.setupUploadRoute() + + return &b +} + +func (b *UploadBackend) upload(w http.ResponseWriter, r *http.Request) { + data, err := ioutil.ReadAll(r.Body) + if err != nil { + llog.Warning("Failed to read request body: %s", string(data)) + http.Error(w, "Failed to read request body", http.StatusInternalServerError) + return + } + + fileName := r.URL.Query().Get("song") + + f, err := os.Create(path.Join(b.uploadDir, fileName)) + if err != nil { + llog.Fatal("Failed to create uploaded song on disk") + } + + _, err = f.Write(data) + if err != nil { + llog.Fatal("Failed to write uploaded song on disk") + } + + f.Close() + + var song Song + dataReader := bytes.NewReader(data) + m, err := tag.ReadFrom(dataReader) + if err != nil { + llog.Warning("error reading tags from %s: %v", fileName, err) + song = NewSong(fileName, "Unknown", "upload", fileName) + } else { + song = NewSong(m.Title(), m.Artist(), "upload", fileName) + } + + wrms.AddSong(song) + wrms.Broadcast(Event{"add", []Song{song}}) + fmt.Fprintf(w, "Added uploaded song %s", string(fileName)) +} + +func (b *UploadBackend) setupUploadRoute() { + http.HandleFunc("/upload", b.upload) +} + +func (b *UploadBackend) Play(song *Song, player *Player) { + player.PlayUri("file://" + path.Join(b.uploadDir, song.Uri)) +} + +func (b *UploadBackend) Search(keyword string) []Song { + return nil +} diff --git a/web/client.html b/web/client.html index 87ca51a..a330c00 100644 --- a/web/client.html +++ b/web/client.html @@ -237,6 +237,18 @@ return false; } + {{if .HasUpload}} + function submitUpload() { + const form = new FormData(document.getElementById("uploadForm")); + const file = form.get("song"); + const params = new URLSearchParams(); + params.append("song", file.name); + const song = params.toString(); + new HttpClient().post("/upload?" + song, file, console.log); + return false; + } + {{end}} + function addSong(song) { new HttpClient().post("/add", JSON.stringify(song), console.log); } @@ -282,6 +294,13 @@ + + {{if .HasUpload}} +
+ + +
+ {{end}}