Preserve full release dates in audio tags
This commit is contained in:
parent
3e67ac6887
commit
54dbd150cb
2 changed files with 71 additions and 2 deletions
|
|
@ -183,6 +183,27 @@ def _names_match(a: str, b: str, threshold: float = 0.75) -> bool:
|
||||||
return SequenceMatcher(None, norm(a), norm(b)).ratio() >= threshold
|
return SequenceMatcher(None, norm(a), norm(b)).ratio() >= threshold
|
||||||
|
|
||||||
|
|
||||||
|
def _normalize_release_date_tag(value: Any) -> str:
|
||||||
|
"""Return a tag-safe release date without inventing missing precision."""
|
||||||
|
raw = str(value or "").strip()
|
||||||
|
if not raw:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# Source APIs commonly return ISO timestamps. Audio DATE/TDRC tags should
|
||||||
|
# receive only the date precision the source actually provided.
|
||||||
|
raw = raw.split("T", 1)[0].strip()
|
||||||
|
match = re.match(r"^(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?$", raw)
|
||||||
|
if not match:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
year, month, day = match.groups()
|
||||||
|
if day:
|
||||||
|
return f"{year}-{month}-{day}"
|
||||||
|
if month:
|
||||||
|
return f"{year}-{month}"
|
||||||
|
return year
|
||||||
|
|
||||||
|
|
||||||
def _collect_source_ids(metadata: dict, cfg) -> dict:
|
def _collect_source_ids(metadata: dict, cfg) -> dict:
|
||||||
source_ids = {}
|
source_ids = {}
|
||||||
source = (metadata.get("source") or "").strip().lower()
|
source = (metadata.get("source") or "").strip().lower()
|
||||||
|
|
@ -1058,7 +1079,9 @@ def extract_source_metadata(context: dict, artist: dict, album_info: dict) -> di
|
||||||
metadata["disc_number"] = disc_num if disc_num is not None else 1
|
metadata["disc_number"] = disc_num if disc_num is not None else 1
|
||||||
|
|
||||||
if album_ctx and album_ctx.get("release_date"):
|
if album_ctx and album_ctx.get("release_date"):
|
||||||
metadata["date"] = album_ctx["release_date"][:4]
|
release_date = _normalize_release_date_tag(album_ctx.get("release_date"))
|
||||||
|
if release_date:
|
||||||
|
metadata["date"] = release_date
|
||||||
|
|
||||||
genres = artist_dict.get("genres") or []
|
genres = artist_dict.get("genres") or []
|
||||||
if genres:
|
if genres:
|
||||||
|
|
@ -1077,11 +1100,12 @@ def extract_source_metadata(context: dict, artist: dict, album_info: dict) -> di
|
||||||
metadata["album_art_url"] = album_image
|
metadata["album_art_url"] = album_image
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"[Metadata Summary] title='%s' | artist='%s' | album_artist='%s' | album='%s' | track=%s/%s | disc=%s",
|
"[Metadata Summary] title='%s' | artist='%s' | album_artist='%s' | album='%s' | date=%s | track=%s/%s | disc=%s",
|
||||||
metadata.get("title"),
|
metadata.get("title"),
|
||||||
metadata.get("artist"),
|
metadata.get("artist"),
|
||||||
metadata.get("album_artist"),
|
metadata.get("album_artist"),
|
||||||
metadata.get("album"),
|
metadata.get("album"),
|
||||||
|
metadata.get("date", ""),
|
||||||
metadata.get("track_number"),
|
metadata.get("track_number"),
|
||||||
metadata.get("total_tracks"),
|
metadata.get("total_tracks"),
|
||||||
metadata.get("disc_number"),
|
metadata.get("disc_number"),
|
||||||
|
|
|
||||||
|
|
@ -188,9 +188,54 @@ def test_extract_source_metadata_keeps_neutral_fields_and_skips_itunes_fallback_
|
||||||
assert metadata["track_number"] == 3
|
assert metadata["track_number"] == 3
|
||||||
assert metadata["total_tracks"] == 12
|
assert metadata["total_tracks"] == 12
|
||||||
assert metadata["disc_number"] == 2
|
assert metadata["disc_number"] == 2
|
||||||
|
assert metadata["date"] == "2024-01-02"
|
||||||
assert metadata["album_art_url"] == "https://img.example/album.jpg"
|
assert metadata["album_art_url"] == "https://img.example/album.jpg"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("raw_release_date", "expected_tag_date"),
|
||||||
|
[
|
||||||
|
("2024-05-06", "2024-05-06"),
|
||||||
|
("2024-05", "2024-05"),
|
||||||
|
("2024", "2024"),
|
||||||
|
("2024-05-06T07:08:09Z", "2024-05-06"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_extract_source_metadata_preserves_available_release_date_precision(monkeypatch, raw_release_date, expected_tag_date):
|
||||||
|
monkeypatch.setattr(ms, "get_config_manager", lambda: _Config({"file_organization.collab_artist_mode": "first"}))
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"source": "spotify",
|
||||||
|
"artist": {"name": "Artist One", "id": "123", "genres": []},
|
||||||
|
"album": {
|
||||||
|
"name": "Album One",
|
||||||
|
"total_tracks": 12,
|
||||||
|
"release_date": raw_release_date,
|
||||||
|
},
|
||||||
|
"track_info": {
|
||||||
|
"artists": [{"name": "Artist One"}],
|
||||||
|
"_source": "spotify",
|
||||||
|
"track_number": 3,
|
||||||
|
"disc_number": 1,
|
||||||
|
},
|
||||||
|
"original_search_result": {
|
||||||
|
"title": "Song One",
|
||||||
|
"artists": [{"name": "Artist One"}],
|
||||||
|
"clean_title": "Song One",
|
||||||
|
"clean_album": "Album One",
|
||||||
|
"clean_artist": "Artist One",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata = me.extract_source_metadata(
|
||||||
|
context,
|
||||||
|
context["artist"],
|
||||||
|
{"is_album": True, "album_name": "Album One", "track_number": 3, "disc_number": 1},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert metadata["date"] == expected_tag_date
|
||||||
|
|
||||||
|
|
||||||
def test_embed_source_ids_uses_current_source_ids_and_legacy_fallback(monkeypatch):
|
def test_embed_source_ids_uses_current_source_ids_and_legacy_fallback(monkeypatch):
|
||||||
audio = _FakeAudio()
|
audio = _FakeAudio()
|
||||||
symbols = _fake_symbols(audio)
|
symbols = _fake_symbols(audio)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue