完成Web ASM
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
//go:embed all:static/dist
|
||||
var staticFiles embed.FS
|
||||
|
||||
func main() {
|
||||
port := flag.Int("port", 8080, "server port")
|
||||
flag.Parse()
|
||||
|
||||
distFS, err := fs.Sub(staticFiles, "static/dist")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open embedded files: %v", err)
|
||||
}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
||||
stripped, err := fs.Sub(distFS, ".")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to sub: %v", err)
|
||||
}
|
||||
fileServer := http.FileServer(http.FS(stripped))
|
||||
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.HasSuffix(r.URL.Path, ".wasm") {
|
||||
w.Header().Set("Content-Type", "application/wasm")
|
||||
}
|
||||
fileServer.ServeHTTP(w, r)
|
||||
})
|
||||
|
||||
go func() {
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-quit
|
||||
log.Println("shutting down...")
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
log.Printf("ncmdump-web (WASM mode) starting on :%d", *port)
|
||||
addr := fmt.Sprintf(":%d", *port)
|
||||
if err := http.ListenAndServe(addr, mux); err != nil {
|
||||
log.Fatalf("server error: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
//go:build js && wasm
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"syscall/js"
|
||||
|
||||
"git.taurusxin.com/taurusxin/ncmdump-go/ncmcrypt"
|
||||
)
|
||||
|
||||
func convertNcm(this js.Value, args []js.Value) interface{} {
|
||||
if len(args) < 1 {
|
||||
return errorResult("no data provided")
|
||||
}
|
||||
|
||||
dataLen := args[0].Get("byteLength").Int()
|
||||
if dataLen == 0 {
|
||||
return errorResult("empty data")
|
||||
}
|
||||
|
||||
data := make([]byte, dataLen)
|
||||
js.CopyBytesToGo(data, args[0])
|
||||
|
||||
ncm, err := ncmcrypt.NewNeteaseCloudMusicFromBytes(data)
|
||||
if err != nil {
|
||||
return errorResult(err.Error())
|
||||
}
|
||||
defer ncm.Close()
|
||||
|
||||
var buf bytes.Buffer
|
||||
if err := ncm.DumpStream(&buf, nil); err != nil {
|
||||
return errorResult(err.Error())
|
||||
}
|
||||
|
||||
format := ncm.GetFormat()
|
||||
result := js.Global().Get("Uint8Array").New(js.ValueOf(buf.Len()))
|
||||
js.CopyBytesToJS(result, buf.Bytes())
|
||||
|
||||
meta := ncm.GetMetadata()
|
||||
|
||||
return js.ValueOf(map[string]interface{}{
|
||||
"data": result,
|
||||
"format": format,
|
||||
"title": meta["title"],
|
||||
"artist": meta["artist"],
|
||||
"album": meta["album"],
|
||||
"coverUrl": meta["coverUrl"],
|
||||
})
|
||||
}
|
||||
|
||||
func embedMetadata(this js.Value, args []js.Value) interface{} {
|
||||
if len(args) < 2 {
|
||||
return errorResult("insufficient arguments")
|
||||
}
|
||||
|
||||
audioLen := args[0].Get("byteLength").Int()
|
||||
audio := make([]byte, audioLen)
|
||||
js.CopyBytesToGo(audio, args[0])
|
||||
|
||||
format := args[1].String()
|
||||
title := ""
|
||||
artist := ""
|
||||
album := ""
|
||||
var coverData []byte
|
||||
|
||||
if len(args) > 2 && args[2].Type() == js.TypeObject {
|
||||
opts := args[2]
|
||||
if v := opts.Get("title"); v.Type() == js.TypeString {
|
||||
title = v.String()
|
||||
}
|
||||
if v := opts.Get("artist"); v.Type() == js.TypeString {
|
||||
artist = v.String()
|
||||
}
|
||||
if v := opts.Get("album"); v.Type() == js.TypeString {
|
||||
album = v.String()
|
||||
}
|
||||
if v := opts.Get("coverData"); v.Type() != js.TypeUndefined && v.Type() != js.TypeNull {
|
||||
coverLen := v.Get("byteLength").Int()
|
||||
coverData = make([]byte, coverLen)
|
||||
js.CopyBytesToGo(coverData, v)
|
||||
}
|
||||
}
|
||||
|
||||
result, err := ncmcrypt.EmbedMetadata(audio, format, title, artist, album, coverData)
|
||||
if err != nil {
|
||||
return errorResult(err.Error())
|
||||
}
|
||||
|
||||
out := js.Global().Get("Uint8Array").New(js.ValueOf(len(result)))
|
||||
js.CopyBytesToJS(out, result)
|
||||
return js.ValueOf(map[string]interface{}{
|
||||
"data": out,
|
||||
"format": format,
|
||||
})
|
||||
}
|
||||
|
||||
func errorResult(msg string) js.Value {
|
||||
return js.ValueOf(map[string]interface{}{
|
||||
"error": msg,
|
||||
})
|
||||
}
|
||||
|
||||
func main() {
|
||||
js.Global().Set("ncmdumpConvert", js.FuncOf(convertNcm))
|
||||
js.Global().Set("ncmdumpEmbed", js.FuncOf(embedMetadata))
|
||||
|
||||
ready := js.Global().Get("ncmdumpOnReady")
|
||||
if ready.Type() == js.TypeFunction {
|
||||
ready.Invoke()
|
||||
}
|
||||
|
||||
select {}
|
||||
}
|
||||
Reference in New Issue
Block a user