mirror of
https://git.um-react.app/um/cli.git
synced 2025-11-28 03:33:02 +00:00
109 lines
2.8 KiB
Go
109 lines
2.8 KiB
Go
package qmc
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
go_mmkv "github.com/unlock-music/go-mmkv"
|
|
"go.uber.org/zap"
|
|
"unlock-music.dev/cli/algo/common"
|
|
"unlock-music.dev/cli/internal/utils"
|
|
)
|
|
|
|
func mergeMMKVKeys(keys ...common.QMCKeys) common.QMCKeys {
|
|
result := make(common.QMCKeys)
|
|
for _, k := range keys {
|
|
for key, value := range k {
|
|
result[utils.NormalizeUnicode(key)] = utils.NormalizeUnicode(value)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func LoadMMKV(path string, key string, logger *zap.Logger) (result common.QMCKeys, err error) {
|
|
mmkv_path := path
|
|
mmkv_crc := path + ".crc"
|
|
|
|
mr, err := os.Open(mmkv_path)
|
|
if err != nil {
|
|
logger.Error("LoadMMKV: Could not open mmkv file", zap.Error(err))
|
|
return nil, fmt.Errorf("LoadMMKV: open error: %w", err)
|
|
}
|
|
defer mr.Close()
|
|
|
|
cr, err := os.Open(mmkv_crc)
|
|
if err == nil {
|
|
// crc is optional
|
|
cr = nil
|
|
defer cr.Close()
|
|
}
|
|
|
|
var password []byte = nil
|
|
if key != "" {
|
|
password = make([]byte, 16)
|
|
copy(password, []byte(key))
|
|
}
|
|
mmkv, err := go_mmkv.NewMMKVReader(mr, password, cr)
|
|
if err != nil {
|
|
logger.Error("LoadMMKV: failed to create reader", zap.Error(err))
|
|
return nil, fmt.Errorf("LoadMMKV: NewMMKVReader error: %w", err)
|
|
}
|
|
|
|
result = make(common.QMCKeys)
|
|
for !mmkv.IsEOF() {
|
|
key, err := mmkv.ReadKey()
|
|
if err != nil {
|
|
logger.Error("LoadMMKV: read key error", zap.Error(err))
|
|
return nil, fmt.Errorf("LoadMMKV: read key error: %w", err)
|
|
}
|
|
value, err := mmkv.ReadStringValue()
|
|
if err != nil {
|
|
logger.Error("LoadMMKV: read value error", zap.Error(err))
|
|
return nil, fmt.Errorf("LoadMMKV: read value error: %w", err)
|
|
}
|
|
logger.Debug("LoadMMKV: read", zap.String("key", key), zap.String("value", value))
|
|
result[utils.NormalizeUnicode(key)] = utils.NormalizeUnicode(value)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// getRelativeMMKVDir get mmkv dir relative to file (legacy QQMusic for macOS behaviour)
|
|
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",
|
|
"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
|
|
}
|