mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-04-21 19:16:01 +02:00
feat: carry extension download metadata through host pipeline and avoid FLAC-only genre/label pre-embed on non-FLAC files
This commit is contained in:
@@ -168,7 +168,7 @@ Interested in contributing? Check out the [Contributing Guide](CONTRIBUTING.md)
|
||||
|---|---|---|---|---|
|
||||
| [hifi-api](https://github.com/binimum/hifi-api) | [music.binimum.org](https://music.binimum.org) | [qqdl.site](https://qqdl.site) | [squid.wtf](https://squid.wtf) | [spotisaver.net](https://spotisaver.net) |
|
||||
| [dabmusic.xyz](https://dabmusic.xyz) | [AfkarXYZ](https://github.com/afkarxyz) | [LRCLib](https://lrclib.net) | [Paxsenix](https://lyrics.paxsenix.org) | [Cobalt](https://cobalt.tools) |
|
||||
| [qwkuns.me](https://qwkuns.me) | [SpotubeDL](https://spotubedl.com) | [Song.link](https://song.link) | [IDHS](https://github.com/sjdonado/idonthavespotify) | |
|
||||
| [qwkuns.me](https://qwkuns.me) | [SpotubeDL](https://spotubedl.com) | [Song.link](https://song.link) | [IDHS](https://github.com/sjdonado/idonthavespotify) | [Monochrome](https://monochrome.tf) |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -118,9 +118,16 @@ type ExtDownloadResult struct {
|
||||
AlbumArtist string `json:"album_artist,omitempty"`
|
||||
TrackNumber int `json:"track_number,omitempty"`
|
||||
DiscNumber int `json:"disc_number,omitempty"`
|
||||
TotalTracks int `json:"total_tracks,omitempty"`
|
||||
TotalDiscs int `json:"total_discs,omitempty"`
|
||||
ReleaseDate string `json:"release_date,omitempty"`
|
||||
CoverURL string `json:"cover_url,omitempty"`
|
||||
ISRC string `json:"isrc,omitempty"`
|
||||
Genre string `json:"genre,omitempty"`
|
||||
Label string `json:"label,omitempty"`
|
||||
Copyright string `json:"copyright,omitempty"`
|
||||
Composer string `json:"composer,omitempty"`
|
||||
LyricsLRC string `json:"lyrics_lrc,omitempty"`
|
||||
DecryptionKey string `json:"decryption_key,omitempty"`
|
||||
Decryption *DownloadDecryptionInfo `json:"decryption,omitempty"`
|
||||
}
|
||||
@@ -1415,6 +1422,12 @@ func DownloadWithExtensionFallback(req DownloadRequest) (*DownloadResponse, erro
|
||||
if result.DiscNumber > 0 {
|
||||
resp.DiscNumber = result.DiscNumber
|
||||
}
|
||||
if result.TotalTracks > 0 {
|
||||
resp.TotalTracks = result.TotalTracks
|
||||
}
|
||||
if result.TotalDiscs > 0 {
|
||||
resp.TotalDiscs = result.TotalDiscs
|
||||
}
|
||||
if result.ReleaseDate != "" {
|
||||
resp.ReleaseDate = result.ReleaseDate
|
||||
}
|
||||
@@ -1424,8 +1437,29 @@ func DownloadWithExtensionFallback(req DownloadRequest) (*DownloadResponse, erro
|
||||
if result.ISRC != "" {
|
||||
resp.ISRC = result.ISRC
|
||||
}
|
||||
if result.Genre != "" {
|
||||
resp.Genre = result.Genre
|
||||
}
|
||||
if result.Label != "" {
|
||||
resp.Label = result.Label
|
||||
}
|
||||
if result.Copyright != "" {
|
||||
resp.Copyright = result.Copyright
|
||||
}
|
||||
if result.Composer != "" {
|
||||
resp.Composer = result.Composer
|
||||
}
|
||||
if result.LyricsLRC != "" {
|
||||
resp.LyricsLRC = result.LyricsLRC
|
||||
}
|
||||
}
|
||||
|
||||
if req.TrackName != "" && resp.Title == "" {
|
||||
resp.Title = req.TrackName
|
||||
}
|
||||
if req.ArtistName != "" && resp.Artist == "" {
|
||||
resp.Artist = req.ArtistName
|
||||
}
|
||||
if req.AlbumName != "" && resp.Album == "" {
|
||||
resp.Album = req.AlbumName
|
||||
}
|
||||
@@ -1444,9 +1478,18 @@ func DownloadWithExtensionFallback(req DownloadRequest) (*DownloadResponse, erro
|
||||
if req.DiscNumber > 0 && resp.DiscNumber == 0 {
|
||||
resp.DiscNumber = req.DiscNumber
|
||||
}
|
||||
if req.TotalTracks > 0 && resp.TotalTracks == 0 {
|
||||
resp.TotalTracks = req.TotalTracks
|
||||
}
|
||||
if req.TotalDiscs > 0 && resp.TotalDiscs == 0 {
|
||||
resp.TotalDiscs = req.TotalDiscs
|
||||
}
|
||||
if req.CoverURL != "" && resp.CoverURL == "" {
|
||||
resp.CoverURL = req.CoverURL
|
||||
}
|
||||
if req.Composer != "" && resp.Composer == "" {
|
||||
resp.Composer = req.Composer
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
@@ -1877,6 +1920,9 @@ func canEmbedGenreLabel(filePath string) bool {
|
||||
if path == "" || strings.HasPrefix(path, "content://") || strings.HasPrefix(path, "/proc/self/fd/") {
|
||||
return false
|
||||
}
|
||||
if strings.ToLower(filepath.Ext(path)) != ".flac" {
|
||||
return false
|
||||
}
|
||||
if !filepath.IsAbs(path) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -185,6 +185,10 @@ func TestCanEmbedGenreLabelRequiresExistingAbsoluteLocalFile(t *testing.T) {
|
||||
if err := os.WriteFile(tempFile, []byte("fLaC"), 0644); err != nil {
|
||||
t.Fatalf("failed to create temp file: %v", err)
|
||||
}
|
||||
tempM4A := filepath.Join(t.TempDir(), "track.m4a")
|
||||
if err := os.WriteFile(tempM4A, []byte("not-flac"), 0644); err != nil {
|
||||
t.Fatalf("failed to create temp m4a file: %v", err)
|
||||
}
|
||||
|
||||
if canEmbedGenreLabel("relative.flac") {
|
||||
t.Fatal("expected relative path to be rejected")
|
||||
@@ -195,6 +199,9 @@ func TestCanEmbedGenreLabelRequiresExistingAbsoluteLocalFile(t *testing.T) {
|
||||
if canEmbedGenreLabel(filepath.Join(t.TempDir(), "missing.flac")) {
|
||||
t.Fatal("expected missing file to be rejected")
|
||||
}
|
||||
if canEmbedGenreLabel(tempM4A) {
|
||||
t.Fatalf("expected non-FLAC file %q to be rejected", tempM4A)
|
||||
}
|
||||
if !canEmbedGenreLabel(tempFile) {
|
||||
t.Fatalf("expected existing absolute file %q to be accepted", tempFile)
|
||||
}
|
||||
|
||||
@@ -3704,6 +3704,8 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
) {
|
||||
final backendTrackNum = _parsePositiveInt(backendResult['track_number']);
|
||||
final backendDiscNum = _parsePositiveInt(backendResult['disc_number']);
|
||||
final backendTotalTracks = _parsePositiveInt(backendResult['total_tracks']);
|
||||
final backendTotalDiscs = _parsePositiveInt(backendResult['total_discs']);
|
||||
final backendYear = normalizeOptionalString(
|
||||
backendResult['release_date'] as String?,
|
||||
);
|
||||
@@ -3731,7 +3733,9 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
backendIsrc != null ||
|
||||
backendCoverUrl != null ||
|
||||
backendAlbumArtist != null ||
|
||||
backendComposer != null;
|
||||
backendComposer != null ||
|
||||
backendTotalTracks != null ||
|
||||
backendTotalDiscs != null;
|
||||
|
||||
if (!hasOverrides) {
|
||||
return baseTrack;
|
||||
@@ -3750,12 +3754,12 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
isrc: backendIsrc ?? baseTrack.isrc,
|
||||
trackNumber: backendTrackNum ?? baseTrack.trackNumber,
|
||||
discNumber: backendDiscNum ?? baseTrack.discNumber,
|
||||
totalDiscs: baseTrack.totalDiscs,
|
||||
totalDiscs: backendTotalDiscs ?? baseTrack.totalDiscs,
|
||||
releaseDate: backendYear ?? baseTrack.releaseDate,
|
||||
deezerId: baseTrack.deezerId,
|
||||
availability: baseTrack.availability,
|
||||
albumType: baseTrack.albumType,
|
||||
totalTracks: baseTrack.totalTracks,
|
||||
totalTracks: backendTotalTracks ?? baseTrack.totalTracks,
|
||||
composer: backendComposer ?? baseTrack.composer,
|
||||
source: baseTrack.source,
|
||||
);
|
||||
@@ -5808,12 +5812,15 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
final backendYear = result['release_date'] as String?;
|
||||
final backendTrackNum = result['track_number'] as int?;
|
||||
final backendDiscNum = result['disc_number'] as int?;
|
||||
final backendTotalTracks = result['total_tracks'] as int?;
|
||||
final backendTotalDiscs = result['total_discs'] as int?;
|
||||
final backendBitDepth = result['actual_bit_depth'] as int?;
|
||||
final backendSampleRate = result['actual_sample_rate'] as int?;
|
||||
final backendISRC = result['isrc'] as String?;
|
||||
final backendGenre = result['genre'] as String?;
|
||||
final backendLabel = result['label'] as String?;
|
||||
final backendCopyright = result['copyright'] as String?;
|
||||
final backendComposer = result['composer'] as String?;
|
||||
final effectiveGenre =
|
||||
normalizeOptionalString(backendGenre) ??
|
||||
normalizeOptionalString(genre) ??
|
||||
@@ -5921,11 +5928,17 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
trackNumber: (backendTrackNum != null && backendTrackNum > 0)
|
||||
? backendTrackNum
|
||||
: trackToDownload.trackNumber,
|
||||
totalTracks: trackToDownload.totalTracks,
|
||||
totalTracks:
|
||||
(backendTotalTracks != null && backendTotalTracks > 0)
|
||||
? backendTotalTracks
|
||||
: trackToDownload.totalTracks,
|
||||
discNumber: (backendDiscNum != null && backendDiscNum > 0)
|
||||
? backendDiscNum
|
||||
: trackToDownload.discNumber,
|
||||
totalDiscs: trackToDownload.totalDiscs,
|
||||
totalDiscs:
|
||||
(backendTotalDiscs != null && backendTotalDiscs > 0)
|
||||
? backendTotalDiscs
|
||||
: trackToDownload.totalDiscs,
|
||||
duration: trackToDownload.duration,
|
||||
releaseDate: (backendYear != null && backendYear.isNotEmpty)
|
||||
? backendYear
|
||||
@@ -5934,7 +5947,10 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
bitDepth: historyBitDepth,
|
||||
sampleRate: historySampleRate,
|
||||
genre: effectiveGenre,
|
||||
composer: trackToDownload.composer,
|
||||
composer:
|
||||
(backendComposer != null && backendComposer.isNotEmpty)
|
||||
? backendComposer
|
||||
: trackToDownload.composer,
|
||||
label: effectiveLabel,
|
||||
copyright: effectiveCopyright,
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user