diff --git a/algo/common/dispatch.go b/algo/common/dispatch.go index f37d35a..45d1804 100644 --- a/algo/common/dispatch.go +++ b/algo/common/dispatch.go @@ -29,6 +29,7 @@ func RegisterDecoder(ext string, noop bool, dispatchFunc NewDecoderFunc) { DecoderRegistry[ext] = append(DecoderRegistry[ext], decoderItem{noop: noop, decoder: dispatchFunc}) } + func GetDecoder(filename string, skipNoop bool) (rs []NewDecoderFunc) { ext := strings.ToLower(strings.TrimLeft(filepath.Ext(filename), ".")) for _, dec := range DecoderRegistry[ext] { diff --git a/algo/common/common.go b/algo/common/interface.go similarity index 73% rename from algo/common/common.go rename to algo/common/interface.go index 1bbb7a3..76ff53f 100644 --- a/algo/common/common.go +++ b/algo/common/interface.go @@ -5,6 +5,10 @@ import ( "io" ) +type StreamDecoder interface { + Decrypt(buf []byte, offset int) +} + type Decoder interface { Validate() error io.Reader @@ -14,12 +18,12 @@ type CoverImageGetter interface { GetCoverImage(ctx context.Context) ([]byte, error) } -type Meta interface { +type AudioMeta interface { GetArtists() []string GetTitle() string GetAlbum() string } -type StreamDecoder interface { - Decrypt(buf []byte, offset int) +type AudioMetaGetter interface { + GetAudioMeta(ctx context.Context) (AudioMeta, error) } diff --git a/algo/ncm/meta.go b/algo/ncm/meta.go index a75cfa9..530d23d 100644 --- a/algo/ncm/meta.go +++ b/algo/ncm/meta.go @@ -6,12 +6,17 @@ import ( "unlock-music.dev/cli/algo/common" ) -type RawMeta interface { - common.Meta +type ncmMeta interface { + common.AudioMeta + + // GetFormat return the audio format, e.g. mp3, flac GetFormat() string + + // GetAlbumImageURL return the album image url GetAlbumImageURL() string } -type RawMetaMusic struct { + +type ncmMetaMusic struct { Format string `json:"format"` MusicID int `json:"musicId"` MusicName string `json:"musicName"` @@ -28,10 +33,11 @@ type RawMetaMusic struct { TransNames []interface{} `json:"transNames"` } -func (m RawMetaMusic) GetAlbumImageURL() string { +func (m *ncmMetaMusic) GetAlbumImageURL() string { return m.AlbumPic } -func (m RawMetaMusic) GetArtists() (artists []string) { + +func (m *ncmMetaMusic) GetArtists() (artists []string) { for _, artist := range m.Artist { for _, item := range artist { name, ok := item.(string) @@ -43,22 +49,23 @@ func (m RawMetaMusic) GetArtists() (artists []string) { return } -func (m RawMetaMusic) GetTitle() string { +func (m *ncmMetaMusic) GetTitle() string { return m.MusicName } -func (m RawMetaMusic) GetAlbum() string { +func (m *ncmMetaMusic) GetAlbum() string { return m.Album } -func (m RawMetaMusic) GetFormat() string { + +func (m *ncmMetaMusic) GetFormat() string { return m.Format } //goland:noinspection SpellCheckingInspection -type RawMetaDJ struct { +type ncmMetaDJ struct { ProgramID int `json:"programId"` ProgramName string `json:"programName"` - MainMusic RawMetaMusic `json:"mainMusic"` + MainMusic ncmMetaMusic `json:"mainMusic"` DjID int `json:"djId"` DjName string `json:"djName"` DjAvatarURL string `json:"djAvatarUrl"` @@ -80,32 +87,32 @@ type RawMetaDJ struct { RadioPurchaseCount int `json:"radioPurchaseCount"` } -func (m RawMetaDJ) GetArtists() []string { +func (m *ncmMetaDJ) GetArtists() []string { if m.DjName != "" { return []string{m.DjName} } return m.MainMusic.GetArtists() } -func (m RawMetaDJ) GetTitle() string { +func (m *ncmMetaDJ) GetTitle() string { if m.ProgramName != "" { return m.ProgramName } return m.MainMusic.GetTitle() } -func (m RawMetaDJ) GetAlbum() string { +func (m *ncmMetaDJ) GetAlbum() string { if m.Brand != "" { return m.Brand } return m.MainMusic.GetAlbum() } -func (m RawMetaDJ) GetFormat() string { +func (m *ncmMetaDJ) GetFormat() string { return m.MainMusic.GetFormat() } -func (m RawMetaDJ) GetAlbumImageURL() string { +func (m *ncmMetaDJ) GetAlbumImageURL() string { if strings.HasPrefix(m.MainMusic.GetAlbumImageURL(), "http") { return m.MainMusic.GetAlbumImageURL() } diff --git a/algo/ncm/ncm.go b/algo/ncm/ncm.go index f54f1ba..afa572f 100644 --- a/algo/ncm/ncm.go +++ b/algo/ncm/ncm.go @@ -41,7 +41,7 @@ type Decoder struct { metaRaw []byte metaType string - meta RawMeta + meta ncmMeta cover []byte } @@ -172,10 +172,10 @@ func (d *Decoder) readCoverData() error { func (d *Decoder) parseMeta() error { switch d.metaType { case "music": - d.meta = new(RawMetaMusic) + d.meta = new(ncmMetaMusic) return json.Unmarshal(d.metaRaw, d.meta) case "dj": - d.meta = new(RawMetaDJ) + d.meta = new(ncmMetaDJ) return json.Unmarshal(d.metaRaw, d.meta) default: return errors.New("unknown ncm meta type: " + d.metaType) @@ -232,8 +232,8 @@ func (d *Decoder) GetCoverImage(ctx context.Context) ([]byte, error) { return d.cover, nil } -func (d *Decoder) GetMeta() common.Meta { - return d.meta +func (d *Decoder) GetAudioMeta(_ context.Context) (common.AudioMeta, error) { + return d.meta, nil } func init() { diff --git a/cmd/um/main.go b/cmd/um/main.go index 9673a83..51088c7 100644 --- a/cmd/um/main.go +++ b/cmd/um/main.go @@ -225,7 +225,22 @@ func tryDecFile(inputFile string, outputDir string, allDec []common.NewDecoderFu logger.Warn("write cover image failed", zap.Error(err)) } } + } + if audioMetaGetter, ok := dec.(common.AudioMetaGetter); ok { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + meta, err := audioMetaGetter.GetAudioMeta(ctx) + if err != nil { + logger.Warn("get audio meta failed", zap.Error(err)) + } else { + logger.Info("audio metadata", + zap.String("title", meta.GetTitle()), + zap.Strings("artists", meta.GetArtists()), + zap.String("album", meta.GetAlbum()), + ) + } } // if source file need to be removed