build spotify-to-navidrome migrator with recovery flow

This commit is contained in:
2026-04-09 03:10:58 +02:00
parent 650a0c6a87
commit c1360a6423
23 changed files with 3383 additions and 0 deletions

101
internal/qobuz/signer.go Normal file
View File

@@ -0,0 +1,101 @@
package qobuz
import (
"crypto/md5"
"encoding/hex"
"net/url"
"sort"
"strings"
"time"
)
func signGet(path, appSecret string, query url.Values) (requestTS, requestSig string) {
ts := nowTS()
method := methodName(path)
keys := make([]string, 0, len(query))
for k := range query {
if k == "app_id" || k == "request_ts" || k == "request_sig" {
continue
}
keys = append(keys, k)
}
sort.Strings(keys)
b := strings.Builder{}
b.WriteString(method)
for _, k := range keys {
vals := query[k]
if len(vals) == 0 {
continue
}
b.WriteString(k)
b.WriteString(vals[0])
}
b.WriteString(ts)
b.WriteString(appSecret)
h := md5.Sum([]byte(b.String()))
return ts, hex.EncodeToString(h[:])
}
func signPost(path, appSecret string, form url.Values, includeValues bool) (requestTS, requestSig string) {
ts := nowTS()
method := methodName(path)
keys := make([]string, 0, len(form))
for k := range form {
if k == "app_id" || k == "request_ts" || k == "request_sig" {
continue
}
keys = append(keys, k)
}
sort.Strings(keys)
b := strings.Builder{}
b.WriteString(method)
for _, k := range keys {
b.WriteString(k)
if includeValues {
vals := form[k]
if len(vals) > 0 {
b.WriteString(vals[0])
}
}
}
b.WriteString(ts)
b.WriteString(appSecret)
h := md5.Sum([]byte(b.String()))
return ts, hex.EncodeToString(h[:])
}
func methodName(path string) string {
return strings.ReplaceAll(strings.Trim(path, "/"), "/", "")
}
func nowTS() string {
return strconvI64(time.Now().Unix())
}
func strconvI64(v int64) string {
if v == 0 {
return "0"
}
neg := v < 0
if neg {
v = -v
}
buf := [20]byte{}
i := len(buf)
for v > 0 {
i--
buf[i] = byte('0' + v%10)
v /= 10
}
if neg {
i--
buf[i] = '-'
}
return string(buf[i:])
}