Refactor: comprehensive cleanup and modularization

- Extracted common JSON parsing helpers into internal/jsonutil
- Removed duplicated helper functions from provider packages
- Removed dead code in internal/app/app.go and downloader.go
- Replaced deprecated strings.Title with jsonutil.TitleCase
- Added graceful shutdown with signal handling in main.go
- Split monolithic cmd/rip/main.go into args.go, helpers.go, lastfm.go, search.go
This commit is contained in:
2026-04-21 23:38:41 +02:00
parent d65dc182f8
commit 6bc4b3b319
15 changed files with 1763 additions and 1853 deletions

View File

@@ -553,31 +553,6 @@ const deezerBFChunkSize = 2048
var deezerBFIV = []byte{0, 1, 2, 3, 4, 5, 6, 7}
func decryptDeezerBFCBCStripe(in []byte, trackID string) ([]byte, error) {
block, err := blowfish.NewCipher(deriveDeezerBlowfishKey(trackID))
if err != nil {
return nil, err
}
out := make([]byte, len(in))
for i := 0; i*deezerBFChunkSize < len(in); i++ {
start := i * deezerBFChunkSize
end := start + deezerBFChunkSize
if end > len(in) {
end = len(in)
}
chunk := in[start:end]
if i%3 == 0 && len(chunk) == deezerBFChunkSize {
dec := make([]byte, len(chunk))
mode := cipher.NewCBCDecrypter(block, deezerBFIV)
mode.CryptBlocks(dec, chunk)
copy(out[start:end], dec)
} else {
copy(out[start:end], chunk)
}
}
return out, nil
}
func deriveDeezerBlowfishKey(trackID string) []byte {
sum := md5.Sum([]byte(trackID))
md5Hex := fmt.Sprintf("%x", sum)
@@ -588,20 +563,3 @@ func deriveDeezerBlowfishKey(trackID string) []byte {
}
return key
}
func normalizeDeezerTrackID(raw string) string {
trimmed := strings.TrimSpace(raw)
if trimmed == "" {
return ""
}
if _, err := strconv.Atoi(trimmed); err == nil {
return trimmed
}
parts := strings.Split(strings.Trim(trimmed, "/"), "/")
for i := len(parts) - 1; i >= 0; i-- {
if _, err := strconv.Atoi(parts[i]); err == nil {
return parts[i]
}
}
return trimmed
}

View File

@@ -66,36 +66,15 @@ func TestManifestDetection(t *testing.T) {
}
}
func TestNormalizeDeezerTrackID(t *testing.T) {
if got := normalizeDeezerTrackID("https://www.deezer.com/track/3135556"); got != "3135556" {
t.Fatalf("normalize track id = %q, want 3135556", got)
}
}
func TestDecryptDeezerBFCBCStripe(t *testing.T) {
func TestDeezerBlowfishKeyDerivation(t *testing.T) {
trackID := "3135556"
plain := make([]byte, deezerBFChunkSize*2)
for i := range plain {
plain[i] = byte(i % 251)
}
enc := make([]byte, len(plain))
copy(enc, plain)
block, err := blowfish.NewCipher(deriveDeezerBlowfishKey(trackID))
if err != nil {
t.Fatalf("cipher error: %v", err)
}
cbc := cipher.NewCBCEncrypter(block, deezerBFIV)
cbc.CryptBlocks(enc[:deezerBFChunkSize], enc[:deezerBFChunkSize])
dec, err := decryptDeezerBFCBCStripe(enc, trackID)
if err != nil {
t.Fatalf("decrypt error: %v", err)
}
if len(dec) != len(plain) || string(dec) != string(plain) {
t.Fatalf("decrypted data mismatch")
key := deriveDeezerBlowfishKey(trackID)
if len(key) != 16 {
t.Fatalf("blowfish key len = %d, want 16", len(key))
}
}
func TestFileDeezerEncrypted(t *testing.T) {
trackID := "3135556"
plain := make([]byte, deezerBFChunkSize+777)