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.
|
||||
if hit:
|
||||
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:
|
||||
cmd += ["--parse-metadata", f"{hit.album}:%(album)s"]
|
||||
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)
|
||||
|
||||
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
|
||||
@@ -28,6 +28,17 @@ def test_done_message_mentions_title():
|
||||
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):
|
||||
calls = {}
|
||||
monkeypatch.setattr(mf, "act_youtube",
|
||||
|
||||
Reference in New Issue
Block a user