feat yandex desktop downloads

This commit is contained in:
2026-06-10 12:58:04 +02:00
parent fa39582849
commit 0ae8c7e008
15 changed files with 1543 additions and 8 deletions

View File

@@ -2,8 +2,10 @@ package download
import (
"context"
"crypto/aes"
"crypto/cipher"
"errors"
"encoding/hex"
"io"
"net/http"
"net/http/httptest"
@@ -110,6 +112,45 @@ func TestFileDeezerEncrypted(t *testing.T) {
}
}
func TestFileYandexEncrypted(t *testing.T) {
plain := make([]byte, 8192+333)
for i := range plain {
plain[i] = byte((i * 11) % 251)
}
keyHex := "00112233445566778899aabbccddeeff"
key, err := hex.DecodeString(keyHex)
if err != nil {
t.Fatalf("DecodeString() error = %v", err)
}
block, err := aes.NewCipher(key)
if err != nil {
t.Fatalf("NewCipher() error = %v", err)
}
enc := make([]byte, len(plain))
copy(enc, plain)
stream := cipher.NewCTR(block, make([]byte, aes.BlockSize))
stream.XORKeyStream(enc, enc)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
_, _ = w.Write(enc)
}))
defer ts.Close()
d := NewWithOptions(true, false, 0)
out := filepath.Join(t.TempDir(), "x", "a.m4a")
if err = d.FileYandexEncrypted(context.Background(), ts.URL, out, keyHex); err != nil {
t.Fatalf("FileYandexEncrypted() error = %v", err)
}
got, err := os.ReadFile(out)
if err != nil {
t.Fatalf("ReadFile() error = %v", err)
}
if string(got) != string(plain) {
t.Fatalf("decrypted file mismatch")
}
}
func TestDownloaderFileTruncatedResponseRemovesPartialFile(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Length", "10")
@@ -160,6 +201,15 @@ func TestFileDeezerEncryptedBadStatus(t *testing.T) {
}
}
func TestFileYandexEncryptedBadKey(t *testing.T) {
d := NewWithOptions(true, false, 0)
out := filepath.Join(t.TempDir(), "x", "a.m4a")
err := d.FileYandexEncrypted(context.Background(), "https://example.com/file", out, "abcd")
if err == nil || !strings.Contains(err.Error(), "invalid yandex key length") {
t.Fatalf("expected key length error, got %v", err)
}
}
func TestDownloaderFileContextCancellationRemovesPartialFile(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/octet-stream")