downloads: fix file-finder collapsing on an unbalanced bracket (false "not found")
Discord (Shdjfgatdif): a downloaded .flac sat right there in the download folder but the import flow reported "File not found on disk after 5 search attempts" and failed it. root cause: slskd REPORTS the name as "[34 - You & Me (Flume Remix).flac" but SAVES it as "34 - You & Me (Flume Remix).flac" (it strips the leading '['). The finder's fuzzy-match normaliser used one combined bracket-strip — r'[\[\(].*?[\]\)]' — which allows MISMATCHED delimiters, so the lone '[' matched all the way to the next ')', ate the whole title, and collapsed the search target to just "flac". That scored 0.40 against the real filename (below the 0.85 floor) → "not found", despite the file being on disk. Confirmed by running the real code on his exact filename. fix: strip only BALANCED pairs (\[...\] and (...) separately). A stray unbalanced bracket now survives to the alphanumeric strip instead of devouring the title. '[34 - You & Me (Flume Remix)' → matches at 1.00. Balanced tags like "[FLAC]" / "(Remastered 2016)" are still stripped (no regression). Only used internally by the finder's fuzzy scorer — contained blast radius. 3 tests: his exact unbalanced-'[' filename, a stray-']' variant, and a balanced-tag no-regression guard. 1311 imports/downloads/quality tests green, ruff clean.
This commit is contained in:
parent
2fb142dded
commit
551df0c3ca
2 changed files with 63 additions and 1 deletions
|
|
@ -77,7 +77,16 @@ def _normalize_for_finding(text: str) -> str:
|
||||||
return ""
|
return ""
|
||||||
text = unidecode(text).lower()
|
text = unidecode(text).lower()
|
||||||
text = re.sub(r'[._/]', ' ', text)
|
text = re.sub(r'[._/]', ' ', text)
|
||||||
text = re.sub(r'[\[\(].*?[\]\)]', '', text)
|
# Strip ONLY balanced bracket pairs (tags like "[FLAC]", "(Remastered 2016)").
|
||||||
|
# The old combined pattern r'[\[\(].*?[\]\)]' allowed MISMATCHED delimiters, so a
|
||||||
|
# lone unbalanced '[' — slskd reports "[34 - You & Me (Flume Remix)" but saves the
|
||||||
|
# file as "34 - You & Me (Flume Remix)" — matched from that '[' all the way to the
|
||||||
|
# next ')', eating the entire title and collapsing the search target to "flac". The
|
||||||
|
# file then scored 0.40 against the real on-disk name and was reported "not found"
|
||||||
|
# despite sitting right there. Per-delimiter pairs can't over-consume; a stray
|
||||||
|
# unbalanced bracket simply survives to the alphanumeric strip below.
|
||||||
|
text = re.sub(r'\[[^\]]*\]', '', text)
|
||||||
|
text = re.sub(r'\([^)]*\)', '', text)
|
||||||
text = re.sub(r'[^a-z0-9\s-]', '', text)
|
text = re.sub(r'[^a-z0-9\s-]', '', text)
|
||||||
return ' '.join(text.split()).strip()
|
return ' '.join(text.split()).strip()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -396,3 +396,56 @@ def test_real_soulseek_path_still_basenamed(tmp_path):
|
||||||
str(downloads), r'shared\Billy Ocean\Very Best Of\01 - Suddenly.flac',
|
str(downloads), r'shared\Billy Ocean\Very Best Of\01 - Suddenly.flac',
|
||||||
)
|
)
|
||||||
assert found == str(target)
|
assert found == str(target)
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Unbalanced bracket — slskd REPORTS "[34 - Title.flac" but SAVES the file as
|
||||||
|
# "34 - Title.flac" (it sanitises the leading '['). The normaliser's old combined
|
||||||
|
# bracket-strip r'[\[\(].*?[\]\)]' matched from that lone '[' all the way to the
|
||||||
|
# next ')', eating the whole title and collapsing the search target to just "flac"
|
||||||
|
# → 0.40 fuzzy score → "File not found on disk" despite the file sitting right
|
||||||
|
# there. (Discord: Shdjfgatdif — "You & Me (Flume Remix)".)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def test_finds_file_when_slskd_strips_a_leading_bracket(tmp_path):
|
||||||
|
downloads = tmp_path / 'downloads'
|
||||||
|
# On disk: no leading '['. API filename (slskd-reported): has the '['.
|
||||||
|
target = downloads / 'Disclosure' / '34 - You & Me (Flume Remix).flac'
|
||||||
|
_touch(target)
|
||||||
|
|
||||||
|
found, location = find_completed_audio_file(
|
||||||
|
str(downloads), r'Music\Disclosure\[34 - You & Me (Flume Remix).flac',
|
||||||
|
)
|
||||||
|
|
||||||
|
assert found == str(target), \
|
||||||
|
'the lone "[" used to collapse the target to "flac" and miss the file'
|
||||||
|
assert location == 'downloads'
|
||||||
|
|
||||||
|
|
||||||
|
def test_balanced_bracket_tags_still_stripped(tmp_path):
|
||||||
|
"""No regression: balanced "[FLAC]" / "(Remastered 2016)" tags in a Soulseek
|
||||||
|
filename must still be stripped so it matches the clean saved file."""
|
||||||
|
downloads = tmp_path / 'downloads'
|
||||||
|
target = downloads / 'Song.mp3'
|
||||||
|
_touch(target)
|
||||||
|
|
||||||
|
found, _ = find_completed_audio_file(
|
||||||
|
str(downloads), r'shared\Artist\Album\Song [FLAC] (Remastered 2016).mp3',
|
||||||
|
)
|
||||||
|
|
||||||
|
assert found == str(target)
|
||||||
|
|
||||||
|
|
||||||
|
def test_stray_closing_bracket_does_not_break_match(tmp_path):
|
||||||
|
"""The other shape in the wild (Discord: "Abort, Retry, Fail_]1-01 …") — a
|
||||||
|
stray ']' must not wreck the match either."""
|
||||||
|
downloads = tmp_path / 'downloads'
|
||||||
|
target = downloads / 'White Town' / "Fail_]1-01 Your Woman.flac"
|
||||||
|
_touch(target)
|
||||||
|
|
||||||
|
found, _ = find_completed_audio_file(
|
||||||
|
str(downloads), r"@@digadom\Music\White Town\Fail_]1-01 Your Woman.flac",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert found == str(target)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue