mirror of
https://git.sr.ht/~joren/streamrip-go
synced 2026-06-17 15:05:39 +02:00
feat yandex desktop downloads
This commit is contained in:
@@ -3,8 +3,10 @@ package download
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -182,6 +184,120 @@ func (d *Downloader) FileDeezerEncrypted(ctx context.Context, sourceURL, outputP
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Downloader) FileYandexEncrypted(ctx context.Context, sourceURL, outputPath, key string) error {
|
||||
logDownloadStart(sourceURL, outputPath)
|
||||
if err := os.MkdirAll(filepath.Dir(outputPath), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
keyBytes, err := hex.DecodeString(strings.TrimSpace(key))
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid yandex key: %w", err)
|
||||
}
|
||||
if len(keyBytes) != 16 {
|
||||
return fmt.Errorf("invalid yandex key length: %d", len(keyBytes))
|
||||
}
|
||||
block, err := aes.NewCipher(keyBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, sourceURL, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp, err := d.http.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return fmt.Errorf("download failed: status=%d", resp.StatusCode)
|
||||
}
|
||||
out, err := os.Create(outputPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
success := false
|
||||
defer func() {
|
||||
_ = out.Close()
|
||||
if !success {
|
||||
_ = os.Remove(outputPath)
|
||||
}
|
||||
}()
|
||||
|
||||
var bar *mpb.Bar
|
||||
if d.ProgressEnabled() {
|
||||
d.barStarted.Store(1)
|
||||
desc := shortenName(filepath.Base(outputPath), 54)
|
||||
if resp.ContentLength > 0 {
|
||||
bar = d.progress.AddBar(
|
||||
resp.ContentLength,
|
||||
mpb.PrependDecorators(
|
||||
decor.Name(desc+" ", decor.WC{W: 56, C: decor.DSyncWidth | decor.DindentRight}),
|
||||
decor.Percentage(decor.WCSyncWidthR),
|
||||
),
|
||||
mpb.AppendDecorators(
|
||||
decor.CountersKibiByte("% .1f / % .1f", decor.WCSyncWidthR),
|
||||
decor.Name(" | ", decor.WCSyncWidth),
|
||||
decor.AverageSpeed(decor.SizeB1024(0), "% .1f", decor.WCSyncWidthR),
|
||||
decor.Name(" | ETA ", decor.WCSyncWidth),
|
||||
decor.AverageETA(decor.ET_STYLE_GO, decor.WCSyncWidthR),
|
||||
),
|
||||
mpb.BarRemoveOnComplete(),
|
||||
)
|
||||
} else {
|
||||
bar = d.progress.AddSpinner(
|
||||
0,
|
||||
mpb.PrependDecorators(
|
||||
decor.Name(desc+" ", decor.WC{W: 56, C: decor.DSyncWidth | decor.DindentRight}),
|
||||
),
|
||||
mpb.AppendDecorators(
|
||||
decor.CurrentKibiByte("% .1f", decor.WCSyncWidthR),
|
||||
decor.Name(" | ", decor.WCSyncWidth),
|
||||
decor.Elapsed(decor.ET_STYLE_GO, decor.WCSyncWidthR),
|
||||
),
|
||||
mpb.BarRemoveOnComplete(),
|
||||
)
|
||||
defer bar.SetTotal(-1, true)
|
||||
}
|
||||
defer func() {
|
||||
if !success && bar != nil {
|
||||
bar.Abort(true)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
stream := cipher.NewCTR(block, make([]byte, aes.BlockSize))
|
||||
reader := &cipher.StreamReader{S: stream, R: resp.Body}
|
||||
buf := make([]byte, downloadBufferSize)
|
||||
totalWritten := int64(0)
|
||||
for {
|
||||
n, readErr := reader.Read(buf)
|
||||
if n > 0 {
|
||||
if _, writeErr := out.Write(buf[:n]); writeErr != nil {
|
||||
return writeErr
|
||||
}
|
||||
totalWritten += int64(n)
|
||||
if bar != nil {
|
||||
bar.IncrBy(n)
|
||||
}
|
||||
}
|
||||
if readErr != nil {
|
||||
if readErr == io.EOF {
|
||||
break
|
||||
}
|
||||
return readErr
|
||||
}
|
||||
}
|
||||
if resp.ContentLength > 0 && totalWritten != resp.ContentLength {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if err = out.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
success = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Downloader) file(ctx context.Context, sourceURL, outputPath string, allowProgress bool, includeVideo bool) error {
|
||||
logDownloadStart(sourceURL, outputPath)
|
||||
if err := os.MkdirAll(filepath.Dir(outputPath), 0o755); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user