From ea3236e14bc9a4dcf8b5920802dbec5c78044280 Mon Sep 17 00:00:00 2001 From: Unlock Music Dev Date: Sun, 4 Dec 2022 23:05:38 +0800 Subject: [PATCH 1/9] refactor: change decoder init parameter --- algo/common/dispatch.go | 8 +++++++- algo/common/raw.go | 4 ++-- algo/kgm/kgm.go | 4 ++-- algo/kwm/kwm.go | 4 ++-- algo/ncm/ncm.go | 6 ++---- algo/qmc/qmc.go | 6 ++++-- algo/tm/tm.go | 4 ++-- algo/xiami/xm.go | 4 ++-- algo/ximalaya/ximalaya.go | 4 ++-- cmd/um/main.go | 8 +++++++- 10 files changed, 32 insertions(+), 20 deletions(-) diff --git a/algo/common/dispatch.go b/algo/common/dispatch.go index 07b110c..263ad64 100644 --- a/algo/common/dispatch.go +++ b/algo/common/dispatch.go @@ -6,7 +6,13 @@ import ( "strings" ) -type NewDecoderFunc func(rd io.ReadSeeker) Decoder +type DecoderParams struct { + Reader io.ReadSeeker // required + Extension string // required, source extension, eg. ".mp3" + + FilePath string // optional, source file path +} +type NewDecoderFunc func(p *DecoderParams) Decoder type decoderItem struct { noop bool diff --git a/algo/common/raw.go b/algo/common/raw.go index c145e25..dd74886 100644 --- a/algo/common/raw.go +++ b/algo/common/raw.go @@ -14,8 +14,8 @@ type RawDecoder struct { audioExt string } -func NewRawDecoder(rd io.ReadSeeker) Decoder { - return &RawDecoder{rd: rd} +func NewRawDecoder(p *DecoderParams) Decoder { + return &RawDecoder{rd: p.Reader} } func (d *RawDecoder) Validate() error { diff --git a/algo/kgm/kgm.go b/algo/kgm/kgm.go index 7b5330e..a02508d 100644 --- a/algo/kgm/kgm.go +++ b/algo/kgm/kgm.go @@ -16,8 +16,8 @@ type Decoder struct { header header } -func NewDecoder(rd io.ReadSeeker) common.Decoder { - return &Decoder{rd: rd} +func NewDecoder(p *common.DecoderParams) common.Decoder { + return &Decoder{rd: p.Reader} } // Validate checks if the file is a valid Kugou (.kgm, .vpr, .kgma) file. diff --git a/algo/kwm/kwm.go b/algo/kwm/kwm.go index 166e732..1bbc604 100644 --- a/algo/kwm/kwm.go +++ b/algo/kwm/kwm.go @@ -30,8 +30,8 @@ func (d *Decoder) GetAudioExt() string { return "." + d.outputExt } -func NewDecoder(rd io.ReadSeeker) common.Decoder { - return &Decoder{rd: rd} +func NewDecoder(p *common.DecoderParams) common.Decoder { + return &Decoder{rd: p.Reader} } // Validate checks if the file is a valid Kuwo .kw file. diff --git a/algo/ncm/ncm.go b/algo/ncm/ncm.go index 5e20093..f54f1ba 100644 --- a/algo/ncm/ncm.go +++ b/algo/ncm/ncm.go @@ -29,10 +29,8 @@ var ( } ) -func NewDecoder(rd io.ReadSeeker) common.Decoder { - return &Decoder{ - rd: rd, - } +func NewDecoder(p *common.DecoderParams) common.Decoder { + return &Decoder{rd: p.Reader} } type Decoder struct { diff --git a/algo/qmc/qmc.go b/algo/qmc/qmc.go index 24f94e8..96e56c7 100644 --- a/algo/qmc/qmc.go +++ b/algo/qmc/qmc.go @@ -38,8 +38,8 @@ func (d *Decoder) Read(p []byte) (int, error) { return n, err } -func NewDecoder(r io.ReadSeeker) common.Decoder { - return &Decoder{raw: r} +func NewDecoder(p *common.DecoderParams) common.Decoder { + return &Decoder{raw: p.Reader} } func (d *Decoder) Validate() error { @@ -214,6 +214,8 @@ func init() { "mgg", "mgg1", "mggl", //QQ Music New Ogg "mflac", "mflac0", //QQ Music New Flac + + "mflach", // QQ Music Flac (storing key in dedicate MMKV) } for _, ext := range supportedExts { common.RegisterDecoder(ext, false, NewDecoder) diff --git a/algo/tm/tm.go b/algo/tm/tm.go index d29326a..d11ecbc 100644 --- a/algo/tm/tm.go +++ b/algo/tm/tm.go @@ -43,8 +43,8 @@ func (d *Decoder) Read(buf []byte) (int, error) { return d.audio.Read(buf) } -func NewTmDecoder(rd io.ReadSeeker) common.Decoder { - return &Decoder{raw: rd} +func NewTmDecoder(p *common.DecoderParams) common.Decoder { + return &Decoder{raw: p.Reader} } func init() { diff --git a/algo/xiami/xm.go b/algo/xiami/xm.go index f878175..83d94e4 100644 --- a/algo/xiami/xm.go +++ b/algo/xiami/xm.go @@ -37,8 +37,8 @@ func (d *Decoder) GetAudioExt() string { return "" } -func NewDecoder(rd io.ReadSeeker) common.Decoder { - return &Decoder{rd: rd} +func NewDecoder(p *common.DecoderParams) common.Decoder { + return &Decoder{rd: p.Reader} } // Validate checks if the file is a valid xiami .xm file. diff --git a/algo/ximalaya/ximalaya.go b/algo/ximalaya/ximalaya.go index fc92528..885693b 100644 --- a/algo/ximalaya/ximalaya.go +++ b/algo/ximalaya/ximalaya.go @@ -16,8 +16,8 @@ type Decoder struct { audio io.Reader } -func NewDecoder(rd io.ReadSeeker) common.Decoder { - return &Decoder{rd: rd} +func NewDecoder(p *common.DecoderParams) common.Decoder { + return &Decoder{rd: p.Reader} } func (d *Decoder) Validate() error { diff --git a/cmd/um/main.go b/cmd/um/main.go index dceea7b..01cf963 100644 --- a/cmd/um/main.go +++ b/cmd/um/main.go @@ -163,9 +163,15 @@ func tryDecFile(inputFile string, outputDir string, allDec []common.NewDecoderFu } defer file.Close() + decParams := &common.DecoderParams{ + Reader: file, + Extension: filepath.Ext(inputFile), + FilePath: inputFile, + } + var dec common.Decoder for _, decFunc := range allDec { - dec = decFunc(file) + dec = decFunc(decParams) if err := dec.Validate(); err == nil { break } else { From d2019b04ec89ce8c836e7b0feb3c558cc19d5fc5 Mon Sep 17 00:00:00 2001 From: Unlock Music Dev Date: Sun, 4 Dec 2022 23:14:06 +0800 Subject: [PATCH 2/9] fix: qmc test --- algo/qmc/qmc_test.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/algo/qmc/qmc_test.go b/algo/qmc/qmc_test.go index 7078ed2..0f1a557 100644 --- a/algo/qmc/qmc_test.go +++ b/algo/qmc/qmc_test.go @@ -7,6 +7,8 @@ import ( "os" "reflect" "testing" + + "unlock-music.dev/cli/algo/common" ) func loadTestDataQmcDecoder(filename string) ([]byte, []byte, error) { @@ -29,13 +31,14 @@ func loadTestDataQmcDecoder(filename string) ([]byte, []byte, error) { func TestMflac0Decoder_Read(t *testing.T) { tests := []struct { name string + fileExt string wantErr bool }{ - {"mflac0_rc4", false}, - {"mflac_rc4", false}, - {"mflac_map", false}, - {"mgg_map", false}, - {"qmc0_static", false}, + {"mflac0_rc4", ".mflac0", false}, + {"mflac_rc4", ".mflac", false}, + {"mflac_map", ".mflac", false}, + {"mgg_map", ".mgg", false}, + {"qmc0_static", ".qmc0", false}, } for _, tt := range tests { @@ -45,7 +48,10 @@ func TestMflac0Decoder_Read(t *testing.T) { t.Fatal(err) } - d := NewDecoder(bytes.NewReader(raw)) + d := NewDecoder(&common.DecoderParams{ + Reader: bytes.NewReader(raw), + Extension: tt.fileExt, + }) if err := d.Validate(); err != nil { t.Errorf("validate file error = %v", err) } @@ -81,7 +87,10 @@ func TestMflac0Decoder_Validate(t *testing.T) { if err != nil { t.Fatal(err) } - d := NewDecoder(bytes.NewReader(raw)) + d := NewDecoder(&common.DecoderParams{ + Reader: bytes.NewReader(raw), + Extension: tt.fileExt, + }) if err := d.Validate(); err != nil { t.Errorf("read bytes from decoder error = %v", err) From 52e986e644bfb6661aaf6e0a7d729dad95e18b8e Mon Sep 17 00:00:00 2001 From: Unlock Music Dev Date: Mon, 5 Dec 2022 00:06:38 +0800 Subject: [PATCH 3/9] feat(qmc): support .mflach on darwin --- algo/qmc/key_mmkv.go | 92 ++++++++++++++++++++++++++++++++++++++++++++ algo/qmc/qmc.go | 12 ++++-- 2 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 algo/qmc/key_mmkv.go diff --git a/algo/qmc/key_mmkv.go b/algo/qmc/key_mmkv.go new file mode 100644 index 0000000..b7f89d8 --- /dev/null +++ b/algo/qmc/key_mmkv.go @@ -0,0 +1,92 @@ +package qmc + +import ( + "errors" + "fmt" + "os" + "path/filepath" + "runtime" + "strings" + + "unlock-music.dev/mmkv" +) + +var streamKeyVault mmkv.MMKV + +func readKeyFromMMKV(file string) ([]byte, error) { + if file == "" { + return nil, errors.New("file path is required while reading key from mmkv") + } + + //goland:noinspection GoBoolExpressions + if runtime.GOOS != "darwin" { + return nil, errors.New("mmkv vault not supported on this platform") + } + + if streamKeyVault == nil { + mmkvDir, err := getRelativeMMKVDir(file) + if err != nil { + mmkvDir, err = getDefaultMMKVDir() + if err != nil { + return nil, fmt.Errorf("mmkv key valut not found: %w", err) + } + } + mmkv.InitializeMMKV(mmkvDir) + streamKeyVault = mmkv.MMKVWithID("MMKVStreamEncryptId") + } + + buf := streamKeyVault.GetBytes(file) + if len(buf) == 0 { + _, partName := filepath.Split(file) + keys := streamKeyVault.AllKeys() + for _, key := range keys { + if strings.HasSuffix(key, partName) { + buf = streamKeyVault.GetBytes(key) + break + } + } + } + + if len(buf) == 0 { + return nil, errors.New("key not found in mmkv vault") + } + + return deriveKey(buf) +} + +func getRelativeMMKVDir(file string) (string, error) { + mmkvDir := filepath.Join(filepath.Dir(file), "../mmkv") + if _, err := os.Stat(mmkvDir); err != nil { + return "", fmt.Errorf("stat default mmkv dir: %w", err) + } + + keyFile := filepath.Join(mmkvDir, "MMKVStreamEncryptId") + if _, err := os.Stat(keyFile); err != nil { + return "", fmt.Errorf("stat default mmkv file: %w", err) + } + + return mmkvDir, nil +} + +func getDefaultMMKVDir() (string, error) { + homeDir, err := os.UserHomeDir() + if err != nil { + return "", fmt.Errorf("get user home dir: %w", err) + } + + mmkvDir := filepath.Join( + homeDir, + "Library/Containers/com.tencent.QQMusicMac/Data", // todo: make configurable + "Library/Application Support/QQMusicMac/mmkv", + ) + if _, err := os.Stat(mmkvDir); err != nil { + return "", fmt.Errorf("stat default mmkv dir: %w", err) + } + + keyFile := filepath.Join(mmkvDir, "MMKVStreamEncryptId") + if _, err := os.Stat(keyFile); err != nil { + return "", fmt.Errorf("stat default mmkv file: %w", err) + } + + return mmkvDir, nil +} diff --git a/algo/qmc/qmc.go b/algo/qmc/qmc.go index 96e56c7..987d01a 100644 --- a/algo/qmc/qmc.go +++ b/algo/qmc/qmc.go @@ -14,7 +14,8 @@ import ( ) type Decoder struct { - raw io.ReadSeeker // raw is the original file reader + raw io.ReadSeeker // raw is the original file reader + params *common.DecoderParams audio io.Reader // audio is the encrypted audio data audioLen int // audioLen is the audio data length @@ -39,7 +40,7 @@ func (d *Decoder) Read(p []byte) (int, error) { } func NewDecoder(p *common.DecoderParams) common.Decoder { - return &Decoder{raw: p.Reader} + return &Decoder{raw: p.Reader, params: p} } func (d *Decoder) Validate() error { @@ -97,7 +98,12 @@ func (d *Decoder) validateDecode() error { return nil } -func (d *Decoder) searchKey() error { +func (d *Decoder) searchKey() (err error) { + if d.params.Extension == ".mflach" { + d.decodedKey, err = readKeyFromMMKV(d.params.FilePath) + return err + } + fileSizeM4, err := d.raw.Seek(-4, io.SeekEnd) if err != nil { return err From 9241512f2d9befc0676d1cc9653752006d6fd52c Mon Sep 17 00:00:00 2001 From: Unlock Music Dev Date: Mon, 5 Dec 2022 00:09:48 +0800 Subject: [PATCH 4/9] feat(qmc): update go.mod --- go.mod | 1 + go.sum | 2 ++ 2 files changed, 3 insertions(+) diff --git a/go.mod b/go.mod index 332442c..8fe2523 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/urfave/cli/v2 v2.23.5 go.uber.org/zap v1.23.0 golang.org/x/crypto v0.3.0 + unlock-music.dev/mmkv v0.0.0-20221204144229-a40e4e5b9eca ) require ( diff --git a/go.sum b/go.sum index 9905ee6..635369a 100644 --- a/go.sum +++ b/go.sum @@ -86,3 +86,5 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +unlock-music.dev/mmkv v0.0.0-20221204144229-a40e4e5b9eca h1:21+n7CN+qrUiWbvHhIiewlUibXBldKREPXjQILyw5lE= +unlock-music.dev/mmkv v0.0.0-20221204144229-a40e4e5b9eca/go.mod h1:N+XdSYGbQs3PIt8k/kzFuTUO5YIal9da1mpK3ul6zJE= From 743c672c449344f02f90dd19cf0e3859b721034f Mon Sep 17 00:00:00 2001 From: Unlock Music Dev Date: Mon, 5 Dec 2022 01:00:00 +0800 Subject: [PATCH 5/9] fix(ci): add zlib for cgo --- .drone.jsonnet | 5 ++++- .drone.yml | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.drone.jsonnet b/.drone.jsonnet index 4c97a33..1b45004 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -69,7 +69,10 @@ local PipelineBuild(GOOS, GOARCH, RUN_TEST) = { if RUN_TEST then [{ name: 'go test', image: 'golang:1.19', - commands: ['go test -v ./...'], + commands: [ + 'apt-get update && apt-get -y install zlib1g-dev', + 'go test -v ./...' + ], }] else [] ) + diff --git a/.drone.yml b/.drone.yml index f0ffa1a..508115c 100644 --- a/.drone.yml +++ b/.drone.yml @@ -7,6 +7,7 @@ steps: image: alpine/git name: fetch tags - commands: + - apt-get update && apt-get -y install zlib1g-dev - go test -v ./... image: golang:1.19 name: go test From 5fbcdb77d49b9a2997c0dfa9c648f75a883bf26d Mon Sep 17 00:00:00 2001 From: Unlock Music Dev Date: Mon, 5 Dec 2022 07:24:03 +0800 Subject: [PATCH 6/9] fix(qmc): use pure go mmkv --- algo/qmc/key_mmkv.go | 28 ++++++++++++------ go.mod | 5 +++- go.sum | 68 +++++++++----------------------------------- 3 files changed, 36 insertions(+), 65 deletions(-) diff --git a/algo/qmc/key_mmkv.go b/algo/qmc/key_mmkv.go index b7f89d8..062ba52 100644 --- a/algo/qmc/key_mmkv.go +++ b/algo/qmc/key_mmkv.go @@ -11,7 +11,7 @@ import ( "unlock-music.dev/mmkv" ) -var streamKeyVault mmkv.MMKV +var streamKeyVault mmkv.Vault func readKeyFromMMKV(file string) ([]byte, error) { if file == "" { @@ -31,18 +31,28 @@ func readKeyFromMMKV(file string) ([]byte, error) { return nil, fmt.Errorf("mmkv key valut not found: %w", err) } } - mmkv.InitializeMMKV(mmkvDir) - streamKeyVault = mmkv.MMKVWithID("MMKVStreamEncryptId") + mgr, err := mmkv.NewManager(mmkvDir) + if err != nil { + return nil, fmt.Errorf("init mmkv manager: %w", err) + } + + streamKeyVault, err = mgr.OpenVault("MMKVStreamEncryptId") + if err != nil { + return nil, fmt.Errorf("open mmkv vault: %w", err) + } } - buf := streamKeyVault.GetBytes(file) - if len(buf) == 0 { + buf, err := streamKeyVault.GetBytes(file) + if err != nil { // fallback match filename only _, partName := filepath.Split(file) - keys := streamKeyVault.AllKeys() + keys := streamKeyVault.Keys() for _, key := range keys { - if strings.HasSuffix(key, partName) { - buf = streamKeyVault.GetBytes(key) - break + if !strings.HasSuffix(key, partName) { + continue + } + buf, err = streamKeyVault.GetBytes(key) + if err != nil { + // TODO: logger } } } diff --git a/go.mod b/go.mod index 8fe2523..9726bea 100644 --- a/go.mod +++ b/go.mod @@ -6,13 +6,16 @@ require ( github.com/urfave/cli/v2 v2.23.5 go.uber.org/zap v1.23.0 golang.org/x/crypto v0.3.0 - unlock-music.dev/mmkv v0.0.0-20221204144229-a40e4e5b9eca + google.golang.org/protobuf v1.28.1 + unlock-music.dev/mmkv v0.0.0-20221204231432-41a75bd29939 ) require ( github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/golang/protobuf v1.5.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.8.0 // indirect + golang.org/x/exp v0.0.0-20221204150635-6dcec336b2bb // indirect ) diff --git a/go.sum b/go.sum index 635369a..7d99469 100644 --- a/go.sum +++ b/go.sum @@ -1,90 +1,48 @@ -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/urfave/cli/v2 v2.23.5 h1:xbrU7tAYviSpqeR3X4nEFWUdB/uDZ6DE+HxmRU7Xtyw= github.com/urfave/cli/v2 v2.23.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY= go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/exp v0.0.0-20221204150635-6dcec336b2bb h1:QIsP/NmClBICkqnJ4rSIhnrGiGR7Yv9ZORGGnmmLTPk= +golang.org/x/exp v0.0.0-20221204150635-6dcec336b2bb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= unlock-music.dev/mmkv v0.0.0-20221204144229-a40e4e5b9eca h1:21+n7CN+qrUiWbvHhIiewlUibXBldKREPXjQILyw5lE= unlock-music.dev/mmkv v0.0.0-20221204144229-a40e4e5b9eca/go.mod h1:N+XdSYGbQs3PIt8k/kzFuTUO5YIal9da1mpK3ul6zJE= +unlock-music.dev/mmkv v0.0.0-20221204231432-41a75bd29939 h1:qWv734RbYjIHtHhZSRbdSyAEJ5K1rWcPSuUOen86tvI= +unlock-music.dev/mmkv v0.0.0-20221204231432-41a75bd29939/go.mod h1:1+Hdsrk8gl1i4/oxOnAhx6y51DAcUfi2CDni6Qhk8Kw= From a9c976f47dde9f74f0242fdf7343f4408fed090e Mon Sep 17 00:00:00 2001 From: Unlock Music Dev Date: Mon, 5 Dec 2022 07:24:21 +0800 Subject: [PATCH 7/9] Revert "fix(ci): add zlib for cgo" This reverts commit 743c672c449344f02f90dd19cf0e3859b721034f. --- .drone.jsonnet | 5 +---- .drone.yml | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/.drone.jsonnet b/.drone.jsonnet index 1b45004..4c97a33 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -69,10 +69,7 @@ local PipelineBuild(GOOS, GOARCH, RUN_TEST) = { if RUN_TEST then [{ name: 'go test', image: 'golang:1.19', - commands: [ - 'apt-get update && apt-get -y install zlib1g-dev', - 'go test -v ./...' - ], + commands: ['go test -v ./...'], }] else [] ) + diff --git a/.drone.yml b/.drone.yml index 508115c..f0ffa1a 100644 --- a/.drone.yml +++ b/.drone.yml @@ -7,7 +7,6 @@ steps: image: alpine/git name: fetch tags - commands: - - apt-get update && apt-get -y install zlib1g-dev - go test -v ./... image: golang:1.19 name: go test From 423767ba63645974fc11f924fa5af5907c345ed8 Mon Sep 17 00:00:00 2001 From: Unlock Music Dev Date: Mon, 5 Dec 2022 08:54:40 +0800 Subject: [PATCH 8/9] fix(qmc): fix key from mmkv --- algo/common/dispatch.go | 4 ++++ algo/qmc/key_mmkv.go | 12 ++++++++++-- algo/qmc/qmc.go | 25 ++++++++++++++++++------- cmd/um/main.go | 6 ++++-- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/algo/common/dispatch.go b/algo/common/dispatch.go index 263ad64..f37d35a 100644 --- a/algo/common/dispatch.go +++ b/algo/common/dispatch.go @@ -4,6 +4,8 @@ import ( "io" "path/filepath" "strings" + + "go.uber.org/zap" ) type DecoderParams struct { @@ -11,6 +13,8 @@ type DecoderParams struct { Extension string // required, source extension, eg. ".mp3" FilePath string // optional, source file path + + Logger *zap.Logger // required } type NewDecoderFunc func(p *DecoderParams) Decoder diff --git a/algo/qmc/key_mmkv.go b/algo/qmc/key_mmkv.go index 062ba52..72b3815 100644 --- a/algo/qmc/key_mmkv.go +++ b/algo/qmc/key_mmkv.go @@ -8,12 +8,14 @@ import ( "runtime" "strings" + "go.uber.org/zap" "unlock-music.dev/mmkv" ) var streamKeyVault mmkv.Vault -func readKeyFromMMKV(file string) ([]byte, error) { +// TODO: move to factory +func readKeyFromMMKV(file string, logger *zap.Logger) ([]byte, error) { if file == "" { return nil, errors.New("file path is required while reading key from mmkv") } @@ -31,6 +33,7 @@ func readKeyFromMMKV(file string) ([]byte, error) { return nil, fmt.Errorf("mmkv key valut not found: %w", err) } } + mgr, err := mmkv.NewManager(mmkvDir) if err != nil { return nil, fmt.Errorf("init mmkv manager: %w", err) @@ -40,6 +43,8 @@ func readKeyFromMMKV(file string) ([]byte, error) { if err != nil { return nil, fmt.Errorf("open mmkv vault: %w", err) } + + logger.Debug("mmkv vault opened", zap.Strings("keys", streamKeyVault.Keys())) } buf, err := streamKeyVault.GetBytes(file) @@ -52,9 +57,12 @@ func readKeyFromMMKV(file string) ([]byte, error) { } buf, err = streamKeyVault.GetBytes(key) if err != nil { - // TODO: logger + logger.Warn("read key from mmkv", zap.String("key", key), zap.Error(err)) } } + // TODO: use editorial judgement to select the best match + // since MacOS may change some characters in the file name. + // eg. "ぜ" -> "ぜ" } if len(buf) == 0 { diff --git a/algo/qmc/qmc.go b/algo/qmc/qmc.go index 987d01a..a775069 100644 --- a/algo/qmc/qmc.go +++ b/algo/qmc/qmc.go @@ -6,9 +6,12 @@ import ( "errors" "fmt" "io" + "runtime" "strconv" "strings" + "go.uber.org/zap" + "unlock-music.dev/cli/algo/common" "unlock-music.dev/cli/internal/sniff" ) @@ -26,6 +29,8 @@ type Decoder struct { rawMetaExtra1 int rawMetaExtra2 int + + logger *zap.Logger } // Read implements io.Reader, offer the decrypted audio data. @@ -40,7 +45,7 @@ func (d *Decoder) Read(p []byte) (int, error) { } func NewDecoder(p *common.DecoderParams) common.Decoder { - return &Decoder{raw: p.Reader, params: p} + return &Decoder{raw: p.Reader, params: p, logger: p.Logger} } func (d *Decoder) Validate() error { @@ -99,15 +104,21 @@ func (d *Decoder) validateDecode() error { } func (d *Decoder) searchKey() (err error) { - if d.params.Extension == ".mflach" { - d.decodedKey, err = readKeyFromMMKV(d.params.FilePath) - return err - } - fileSizeM4, err := d.raw.Seek(-4, io.SeekEnd) if err != nil { return err } + fileSize := int(fileSizeM4) + 4 + + //goland:noinspection GoBoolExpressions + if runtime.GOOS == "darwin" { + d.decodedKey, err = readKeyFromMMKV(d.params.FilePath, d.logger) + if err == nil { + d.audioLen = fileSize + return + } + d.logger.Warn("read key from mmkv failed", zap.Error(err)) + } suffixBuf := make([]byte, 4) if _, err := io.ReadFull(d.raw, suffixBuf); err != nil { @@ -127,7 +138,7 @@ func (d *Decoder) searchKey() (err error) { } // try to use default static cipher - d.audioLen = int(fileSizeM4 + 4) + d.audioLen = fileSize return nil } diff --git a/cmd/um/main.go b/cmd/um/main.go index 01cf963..4eae5e8 100644 --- a/cmd/um/main.go +++ b/cmd/um/main.go @@ -148,9 +148,10 @@ func dealDirectory(inputDir string, outputDir string, skipNoop bool, removeSourc continue } - err := tryDecFile(filepath.Join(inputDir, item.Name()), outputDir, allDec, removeSource) + filePath := filepath.Join(inputDir, item.Name()) + err := tryDecFile(filePath, outputDir, allDec, removeSource) if err != nil { - logger.Error("conversion failed", zap.String("source", item.Name()), zap.Error(err)) + logger.Error("conversion failed", zap.String("source", filePath), zap.Error(err)) } } return nil @@ -167,6 +168,7 @@ func tryDecFile(inputFile string, outputDir string, allDec []common.NewDecoderFu Reader: file, Extension: filepath.Ext(inputFile), FilePath: inputFile, + Logger: logger.With(zap.String("source", inputFile)), } var dec common.Decoder From 3739638ddf8c6c1fcc22360aded951929fe202c3 Mon Sep 17 00:00:00 2001 From: Unlock Music Dev Date: Mon, 5 Dec 2022 09:43:33 +0800 Subject: [PATCH 9/9] feat(qmc): use editorial distance to find the key --- algo/qmc/key_mmkv.go | 41 ++++++++++++++++++++++++++++++++++------- algo/qmc/qmc.go | 2 +- go.mod | 14 ++++++++------ go.sum | 19 ++++++++++++++----- 4 files changed, 57 insertions(+), 19 deletions(-) diff --git a/algo/qmc/key_mmkv.go b/algo/qmc/key_mmkv.go index 72b3815..81f891a 100644 --- a/algo/qmc/key_mmkv.go +++ b/algo/qmc/key_mmkv.go @@ -8,7 +8,10 @@ import ( "runtime" "strings" + "github.com/hbollon/go-edlib" + "github.com/samber/lo" "go.uber.org/zap" + "golang.org/x/exp/slices" "unlock-music.dev/mmkv" ) @@ -47,11 +50,13 @@ func readKeyFromMMKV(file string, logger *zap.Logger) ([]byte, error) { logger.Debug("mmkv vault opened", zap.Strings("keys", streamKeyVault.Keys())) } + _, partName := filepath.Split(file) buf, err := streamKeyVault.GetBytes(file) - if err != nil { // fallback match filename only - _, partName := filepath.Split(file) - keys := streamKeyVault.Keys() - for _, key := range keys { + + if buf == nil { + filePaths := streamKeyVault.Keys() + + for _, key := range filePaths { // fallback 1: match filename only if !strings.HasSuffix(key, partName) { continue } @@ -60,9 +65,31 @@ func readKeyFromMMKV(file string, logger *zap.Logger) ([]byte, error) { logger.Warn("read key from mmkv", zap.String("key", key), zap.Error(err)) } } - // TODO: use editorial judgement to select the best match - // since MacOS may change some characters in the file name. - // eg. "ぜ" -> "ぜ" + + if buf == nil { // fallback 2: match filename with edit distance + // use editorial judgement to select the best match + // since macOS may change some characters in the file name. + // e.g. "ぜ"(e3 81 9c) -> "ぜ"(e3 81 9b e3 82 99) + fileNames := lo.Map(filePaths, func(filePath string, _ int) string { + _, name := filepath.Split(filePath) + return name + }) + + minDisStr, err := edlib.FuzzySearch(partName, fileNames, edlib.Levenshtein) + if err != nil { + logger.Warn("fuzzy search failed", zap.Error(err)) + } + + // TODO: make distance configurable + // for now, assume only 1 character changed to 2 characters + if edlib.LevenshteinDistance(partName, minDisStr) < 3 { + idx := slices.Index(fileNames, minDisStr) + buf, err = streamKeyVault.GetBytes(filePaths[idx]) + if err != nil { + logger.Warn("read key from mmkv", zap.String("key", minDisStr), zap.Error(err)) + } + } + } } if len(buf) == 0 { diff --git a/algo/qmc/qmc.go b/algo/qmc/qmc.go index a775069..9d4002e 100644 --- a/algo/qmc/qmc.go +++ b/algo/qmc/qmc.go @@ -111,7 +111,7 @@ func (d *Decoder) searchKey() (err error) { fileSize := int(fileSizeM4) + 4 //goland:noinspection GoBoolExpressions - if runtime.GOOS == "darwin" { + if runtime.GOOS == "darwin" && !strings.HasPrefix(d.params.Extension, ".qmc") { d.decodedKey, err = readKeyFromMMKV(d.params.FilePath, d.logger) if err == nil { d.audioLen = fileSize diff --git a/go.mod b/go.mod index 9726bea..cbd1ab6 100644 --- a/go.mod +++ b/go.mod @@ -1,21 +1,23 @@ module unlock-music.dev/cli -go 1.17 +go 1.19 require ( - github.com/urfave/cli/v2 v2.23.5 - go.uber.org/zap v1.23.0 + github.com/hbollon/go-edlib v1.6.0 + github.com/samber/lo v1.36.0 + github.com/urfave/cli/v2 v2.23.6 + go.uber.org/zap v1.24.0 golang.org/x/crypto v0.3.0 - google.golang.org/protobuf v1.28.1 + golang.org/x/exp v0.0.0-20221204150635-6dcec336b2bb unlock-music.dev/mmkv v0.0.0-20221204231432-41a75bd29939 ) require ( github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/golang/protobuf v1.5.0 // indirect + github.com/golang/protobuf v1.5.2 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/multierr v1.8.0 // indirect - golang.org/x/exp v0.0.0-20221204150635-6dcec336b2bb // indirect + google.golang.org/protobuf v1.28.1 // indirect ) diff --git a/go.sum b/go.sum index 7d99469..4a019ce 100644 --- a/go.sum +++ b/go.sum @@ -6,19 +6,28 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/hbollon/go-edlib v1.6.0 h1:ga7AwwVIvP8mHm9GsPueC0d71cfRU/52hmPJ7Tprv4E= +github.com/hbollon/go-edlib v1.6.0/go.mod h1:wnt6o6EIVEzUfgbUZY7BerzQ2uvzp354qmS2xaLkrhM= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/samber/lo v1.36.0 h1:4LaOxH1mHnbDGhTVE0i1z8v/lWaQW8AIfOD3HU4mSaw= +github.com/samber/lo v1.36.0/go.mod h1:HLeWcJRRyLKp3+/XBJvOrerCQn9mhdKMHyd7IRlgeQ8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= github.com/urfave/cli/v2 v2.23.5 h1:xbrU7tAYviSpqeR3X4nEFWUdB/uDZ6DE+HxmRU7Xtyw= github.com/urfave/cli/v2 v2.23.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= +github.com/urfave/cli/v2 v2.23.6 h1:iWmtKD+prGo1nKUtLO0Wg4z9esfBM4rAV4QRLQiEmJ4= +github.com/urfave/cli/v2 v2.23.6/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -29,20 +38,20 @@ go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY= go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/exp v0.0.0-20221204150635-6dcec336b2bb h1:QIsP/NmClBICkqnJ4rSIhnrGiGR7Yv9ZORGGnmmLTPk= golang.org/x/exp v0.0.0-20221204150635-6dcec336b2bb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -unlock-music.dev/mmkv v0.0.0-20221204144229-a40e4e5b9eca h1:21+n7CN+qrUiWbvHhIiewlUibXBldKREPXjQILyw5lE= -unlock-music.dev/mmkv v0.0.0-20221204144229-a40e4e5b9eca/go.mod h1:N+XdSYGbQs3PIt8k/kzFuTUO5YIal9da1mpK3ul6zJE= unlock-music.dev/mmkv v0.0.0-20221204231432-41a75bd29939 h1:qWv734RbYjIHtHhZSRbdSyAEJ5K1rWcPSuUOen86tvI= unlock-music.dev/mmkv v0.0.0-20221204231432-41a75bd29939/go.mod h1:1+Hdsrk8gl1i4/oxOnAhx6y51DAcUfi2CDni6Qhk8Kw=