diff --git a/api/gongs.go b/api/gongs.go index b160292..23cc900 100644 --- a/api/gongs.go +++ b/api/gongs.go @@ -3,6 +3,9 @@ package api import ( "fmt" "net/http" + "os" + "path" + "strings" "github.com/gin-gonic/gin" @@ -21,7 +24,43 @@ func declareGongsRoutes(cfg *config.Config, router *gin.RouterGroup) { c.JSON(http.StatusOK, gongs) }) router.POST("/gongs", func(c *gin.Context) { - c.AbortWithStatusJSON(http.StatusNotImplemented, gin.H{"errmsg": "TODO"}) + fgong, err := c.FormFile("gongfile") + if err != nil { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "No gong found"}) + return + } + + // Check file extension + if path.Ext(fgong.Filename) != ".mp3" && path.Ext(fgong.Filename) != ".flac" && path.Ext(fgong.Filename) != ".wav" { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Bad file type. You should only upload .mp3, .wav or .flac files."}) + return + } + + if strings.Contains(fgong.Filename, "/") { + c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"errmsg": "Bad file name."}) + return + } + + dst := path.Join(cfg.GongsDir, fgong.Filename) + err = c.SaveUploadedFile(fgong, dst) + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Something goes wrong when saving the gong: %s", err.Error())}) + return + } + + d, err := os.Stat(dst) + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Something goes wrong when saving the gong: %s", err.Error())}) + return + } + + gong, err := reveil.LoadGong(cfg, dst, d) + if err != nil { + c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": fmt.Sprintf("Unable to load gong: %s", err.Error())}) + return + } + + c.JSON(http.StatusOK, gong) }) gongsRoutes := router.Group("/gongs/:tid") diff --git a/model/gong.go b/model/gong.go index aec1de5..5f23f45 100644 --- a/model/gong.go +++ b/model/gong.go @@ -23,6 +23,23 @@ func CurrentGongPath(cfg *config.Config) string { return filepath.Join(cfg.GongsDir, CURRENT_GONG) } +func LoadGong(cfg *config.Config, path string, d fs.FileInfo) (gong *Gong, err error) { + // Retrieve the path of the current gong + current_gong, err := os.Readlink(CurrentGongPath(cfg)) + if err == nil { + current_gong, _ = filepath.Abs(filepath.Join(cfg.GongsDir, current_gong)) + } + + hash := sha512.Sum512([]byte(path)) + pabs, _ := filepath.Abs(path) + return &Gong{ + Id: hash[:], + Name: strings.TrimSuffix(d.Name(), filepath.Ext(d.Name())), + Path: path, + Enabled: current_gong == pabs, + }, nil +} + func LoadGongs(cfg *config.Config) (gongs []*Gong, err error) { // Retrieve the path of the current gong current_gong, err := os.Readlink(CurrentGongPath(cfg)) diff --git a/ui/src/lib/gong.js b/ui/src/lib/gong.js index 71128ce..43fd1fb 100644 --- a/ui/src/lib/gong.js +++ b/ui/src/lib/gong.js @@ -45,6 +45,25 @@ export class Gong { } } +export async function uploadGong(files, meta) { + for (const file of files) { + const formData = new FormData(); + formData.append("gongfile", file); + formData.append("meta", JSON.stringify(meta)); + + const res = await fetch('/api/gongs', { + method: 'POST', + body: formData, + }); + if (res.ok) { + const data = await res.json(); + return new Gong(data) + } else { + throw new Error((await res.json()).errmsg); + } + } +} + export async function getGongs() { const res = await fetch(`api/gongs`, {headers: {'Accept': 'application/json'}}) if (res.status == 200) { diff --git a/ui/src/routes/musiks/gongs/new/+page.svelte b/ui/src/routes/musiks/gongs/new/+page.svelte index fe74ecb..f5a5ec1 100644 --- a/ui/src/routes/musiks/gongs/new/+page.svelte +++ b/ui/src/routes/musiks/gongs/new/+page.svelte @@ -1,3 +1,45 @@ -

- Nouveau gong -

+ + + +

+ Nouveau gong +

+ +
+ + + +
+