diff --git a/algo/common/common.go b/algo/common/common.go index c25f2f5..a248284 100644 --- a/algo/common/common.go +++ b/algo/common/common.go @@ -1,14 +1,19 @@ package common +import "context" + type Decoder interface { Validate() error Decode() error - GetCoverImage() []byte GetAudioData() []byte GetAudioExt() string GetMeta() Meta } +type CoverImageGetter interface { + GetCoverImage(ctx context.Context) ([]byte, error) +} + type Meta interface { GetArtists() []string GetTitle() string diff --git a/algo/common/raw.go b/algo/common/raw.go index 6f901b2..77bc043 100644 --- a/algo/common/raw.go +++ b/algo/common/raw.go @@ -28,10 +28,6 @@ func (d RawDecoder) Decode() error { return nil } -func (d RawDecoder) GetCoverImage() []byte { - return nil -} - func (d RawDecoder) GetAudioData() []byte { return d.file } diff --git a/algo/kgm/kgm.go b/algo/kgm/kgm.go index 9fa8e28..49a6967 100644 --- a/algo/kgm/kgm.go +++ b/algo/kgm/kgm.go @@ -31,10 +31,6 @@ func NewDecoder(file []byte) common.Decoder { } } -func (d *Decoder) GetCoverImage() []byte { - return nil -} - func (d *Decoder) GetAudioData() []byte { return d.audio } diff --git a/algo/kwm/kwm.go b/algo/kwm/kwm.go index a9fa2d6..836a9b0 100644 --- a/algo/kwm/kwm.go +++ b/algo/kwm/kwm.go @@ -4,10 +4,11 @@ import ( "bytes" "encoding/binary" "errors" - "github.com/unlock-music/cli/algo/common" "strconv" "strings" "unicode" + + "github.com/unlock-music/cli/algo/common" ) var ( @@ -31,10 +32,6 @@ type Decoder struct { audio []byte } -func (d *Decoder) GetCoverImage() []byte { - return nil -} - func (d *Decoder) GetAudioData() []byte { return d.audio } diff --git a/algo/ncm/ncm.go b/algo/ncm/ncm.go index 80da8b3..7713c9d 100644 --- a/algo/ncm/ncm.go +++ b/algo/ncm/ncm.go @@ -2,17 +2,18 @@ package ncm import ( "bytes" + "context" "encoding/base64" "encoding/binary" "encoding/json" "errors" - "github.com/unlock-music/cli/algo/common" - "github.com/unlock-music/cli/internal/logging" - "github.com/unlock-music/cli/internal/utils" - "go.uber.org/zap" - "io/ioutil" + "fmt" + "io" "net/http" "strings" + + "github.com/unlock-music/cli/algo/common" + "github.com/unlock-music/cli/internal/utils" ) var ( @@ -157,9 +158,9 @@ func (d *Decoder) readCoverData() error { iCoverLen := binary.LittleEndian.Uint32(bCoverLen) d.offsetAudio = coverLenStart + 4 + iCoverLen if iCoverLen == 0 { - return errors.New("no any cover file found") + return nil } - d.cover = d.file[coverLenStart+4 : 4+coverLenStart+iCoverLen] + d.cover = d.file[coverLenStart+4 : coverLenStart+4+iCoverLen] return nil } @@ -178,27 +179,25 @@ func (d *Decoder) readAudioData() error { func (d *Decoder) Decode() error { if err := d.readKeyData(); err != nil { - return err + return fmt.Errorf("read key data failed: %w", err) } d.buildKeyBox() - err := d.readMetaData() - if err == nil { - err = d.parseMeta() + if err := d.readMetaData(); err != nil { + return fmt.Errorf("read meta date failed: %w", err) } - if err != nil { - logging.Log().Warn("parse ncm meta file failed", zap.Error(err)) + if err := d.parseMeta(); err != nil { + return fmt.Errorf("parse meta failed: %w", err) } - err = d.readCoverData() - if err != nil { - logging.Log().Warn("parse ncm cover file failed", zap.Error(err)) + if err := d.readCoverData(); err != nil { + return fmt.Errorf("parse ncm cover file failed: %w", err) } return d.readAudioData() } -func (d Decoder) GetAudioExt() string { +func (d *Decoder) GetAudioExt() string { if d.meta != nil { if format := d.meta.GetFormat(); format != "" { return "." + d.meta.GetFormat() @@ -207,40 +206,38 @@ func (d Decoder) GetAudioExt() string { return "" } -func (d Decoder) GetAudioData() []byte { +func (d *Decoder) GetAudioData() []byte { return d.audio } -func (d Decoder) GetCoverImage() []byte { +func (d *Decoder) GetCoverImage(ctx context.Context) ([]byte, error) { if d.cover != nil { - return d.cover + return d.cover, nil } - { - imgURL := d.meta.GetAlbumImageURL() - if d.meta != nil && !strings.HasPrefix(imgURL, "http") { - return nil - } - resp, err := http.Get(imgURL) - if err != nil { - logging.Log().Warn("download image failed", zap.Error(err), zap.String("url", imgURL)) - return nil - } - defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - logging.Log().Warn("download image failed", zap.String("http", resp.Status), - zap.String("url", imgURL)) - return nil - } - data, err := ioutil.ReadAll(resp.Body) - if err != nil { - logging.Log().Warn("download image failed", zap.Error(err), zap.String("url", imgURL)) - return nil - } - return data + imgURL := d.meta.GetAlbumImageURL() + if d.meta != nil && !strings.HasPrefix(imgURL, "http") { + return nil, nil // no cover image + } + + // fetch cover image + req, err := http.NewRequestWithContext(ctx, http.MethodGet, imgURL, nil) + resp, err := http.DefaultClient.Do(req) + if err != nil { + return nil, fmt.Errorf("download image failed: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("download image failed: unexpected http status %s", resp.Status) + } + data, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("download image failed: %w", err) } + return data, nil } -func (d Decoder) GetMeta() common.Meta { +func (d *Decoder) GetMeta() common.Meta { return d.meta } diff --git a/algo/qmc/qmc.go b/algo/qmc/qmc.go index 6028e6e..948d04f 100644 --- a/algo/qmc/qmc.go +++ b/algo/qmc/qmc.go @@ -244,10 +244,6 @@ func (c *compactDecoder) Decode() error { return err } -func (c *compactDecoder) GetCoverImage() []byte { - return nil -} - func (c *compactDecoder) GetAudioData() []byte { return c.buf.Bytes() } diff --git a/algo/tm/tm.go b/algo/tm/tm.go index d1ccc18..a73b448 100644 --- a/algo/tm/tm.go +++ b/algo/tm/tm.go @@ -3,6 +3,7 @@ package tm import ( "bytes" "errors" + "github.com/unlock-music/cli/algo/common" ) @@ -16,10 +17,6 @@ type Decoder struct { audioExt string } -func (d *Decoder) GetCoverImage() []byte { - return nil -} - func (d *Decoder) GetAudioData() []byte { return d.audio } diff --git a/algo/xm/xm.go b/algo/xm/xm.go index 42a88ba..1268d0c 100644 --- a/algo/xm/xm.go +++ b/algo/xm/xm.go @@ -3,9 +3,8 @@ package xm import ( "bytes" "errors" + "github.com/unlock-music/cli/algo/common" - "github.com/unlock-music/cli/internal/logging" - "go.uber.org/zap" ) var ( @@ -29,10 +28,6 @@ type Decoder struct { audio []byte } -func (d *Decoder) GetCoverImage() []byte { - return nil -} - func (d *Decoder) GetAudioData() []byte { return d.audio } @@ -69,9 +64,6 @@ func (d *Decoder) Validate() error { return errors.New("detect unknown xm file type: " + string(d.file[4:8])) } - if d.file[14] != 0 { - logging.Log().Warn("not a simple xm file", zap.Uint8("b[14]", d.file[14])) - } d.headerLen = uint32(d.file[12]) | uint32(d.file[13])<<8 | uint32(d.file[14])<<16 // LittleEndian Unit24 if d.headerLen+16 > uint32(lenData) { return ErrFileSize