fix: write single first-artist tag, not doubled/multi-artist
Live end-to-end test surfaced two bugs in youtube tagging: - `--replace-in-metadata artist .* NAME` matched twice and doubled the artist tag (e.g. "SLVMLORDSLVMLORD"). Anchor with ^.*$ to match once. - Use only the first artist when several are present (SLVMLORD, not "SLVMLORD, Travis Bradley, ...") for both the embedded tag and the spoken/echoed API messages. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -474,7 +474,10 @@ def yt_download(url_or_query: str, target_folder: str, quality: str, dry_run: bo
|
|||||||
# Override tags from the chosen hit so they don't rely on scraped titles.
|
# Override tags from the chosen hit so they don't rely on scraped titles.
|
||||||
if hit:
|
if hit:
|
||||||
if hit.artist:
|
if hit.artist:
|
||||||
cmd += ["--replace-in-metadata", "artist", ".*", hit.artist]
|
# First artist only; anchored ^.*$ replaces the whole field exactly once
|
||||||
|
# (a bare .* matches twice and doubles the value).
|
||||||
|
primary_artist = hit.artist.split(",")[0].strip()
|
||||||
|
cmd += ["--replace-in-metadata", "artist", "^.*$", primary_artist]
|
||||||
if hit.album:
|
if hit.album:
|
||||||
cmd += ["--parse-metadata", f"{hit.album}:%(album)s"]
|
cmd += ["--parse-metadata", f"{hit.album}:%(album)s"]
|
||||||
if hit.title:
|
if hit.title:
|
||||||
|
|||||||
@@ -13,16 +13,21 @@ def _title(hit) -> str:
|
|||||||
return hit.album if hit.kind == "album" else (hit.title or hit.album or hit.artist)
|
return hit.album if hit.kind == "album" else (hit.title or hit.album or hit.artist)
|
||||||
|
|
||||||
|
|
||||||
|
def _primary_artist(hit) -> str:
|
||||||
|
"""First artist only — ignore featured/secondary artists."""
|
||||||
|
return (hit.artist.split(",")[0].strip() if hit.artist else "") or "unknown artist"
|
||||||
|
|
||||||
|
|
||||||
def started_message(hit) -> str:
|
def started_message(hit) -> str:
|
||||||
return f"Found '{_title(hit)}' by {hit.artist or 'unknown artist'} on {_source_label(hit)}. Downloading now."
|
return f"Found '{_title(hit)}' by {_primary_artist(hit)} on {_source_label(hit)}. Downloading now."
|
||||||
|
|
||||||
|
|
||||||
def done_message(hit) -> str:
|
def done_message(hit) -> str:
|
||||||
return f"Finished downloading '{_title(hit)}' by {hit.artist or 'unknown artist'}."
|
return f"Finished downloading '{_title(hit)}' by {_primary_artist(hit)}."
|
||||||
|
|
||||||
|
|
||||||
def failed_message(hit) -> str:
|
def failed_message(hit) -> str:
|
||||||
return f"Failed to download '{_title(hit)}' by {hit.artist or 'unknown artist'}."
|
return f"Failed to download '{_title(hit)}' by {_primary_artist(hit)}."
|
||||||
|
|
||||||
|
|
||||||
def _yt_path(hit, root: str) -> str:
|
def _yt_path(hit, root: str) -> str:
|
||||||
|
|||||||
@@ -28,6 +28,17 @@ def test_done_message_mentions_title():
|
|||||||
assert "Avril Lavigne" in msg
|
assert "Avril Lavigne" in msg
|
||||||
|
|
||||||
|
|
||||||
|
def test_messages_use_only_first_artist():
|
||||||
|
hit = mf.Hit(source="youtube", kind="track", title="Under My Skin",
|
||||||
|
artist="SLVMLORD, James John, BobbyGee", album="X", year="",
|
||||||
|
payload={"videoId": "abc"})
|
||||||
|
for msg in (actions.started_message(hit), actions.done_message(hit),
|
||||||
|
actions.failed_message(hit)):
|
||||||
|
assert "SLVMLORD" in msg
|
||||||
|
assert "James John" not in msg
|
||||||
|
assert "BobbyGee" not in msg
|
||||||
|
|
||||||
|
|
||||||
def test_perform_youtube_calls_act_youtube(monkeypatch):
|
def test_perform_youtube_calls_act_youtube(monkeypatch):
|
||||||
calls = {}
|
calls = {}
|
||||||
monkeypatch.setattr(mf, "act_youtube",
|
monkeypatch.setattr(mf, "act_youtube",
|
||||||
|
|||||||
Reference in New Issue
Block a user