Fix version parsing in track matching logic (#261)
authorMarcel van der Veldt <m.vanderveldt@outlook.com>
Thu, 21 Apr 2022 17:15:45 +0000 (19:15 +0200)
committerGitHub <noreply@github.com>
Thu, 21 Apr 2022 17:15:45 +0000 (19:15 +0200)
music_assistant/helpers/compare.py
music_assistant/helpers/util.py
tests/utils.py [new file with mode: 0644]

index 553b5ccb20a8643c29b9e7dc7eddf786246145c8..91287fd05f87f8730733e674657db5d4b7ef3594 100644 (file)
@@ -40,6 +40,15 @@ def compare_version(left_version: str, right_version: str):
     return left_versions == right_versions
 
 
+def compare_explicit(left_metadata: dict, right_metadata: dict):
+    """Compare if explicit is same in metadata."""
+    left = left_metadata.get("explicit")
+    right = right_metadata.get("explicit")
+    if left is None and right is None:
+        return True
+    return left == right
+
+
 def compare_artists(left_artists: List["Artist"], right_artists: List["Artist"]):
     """Compare two lists of artist and return True if both lists match."""
     matches = 0
@@ -101,6 +110,9 @@ def compare_track(left_track: "Track", right_track: "Track"):
     # track artist(s) must match
     if not compare_artists(left_track.artists, right_track.artists):
         return False
+    # track if both tracks are (not) explicit
+    if not compare_explicit(left_track.metadata, right_track.metadata):
+        return False
     # album match OR near exact duration match
     if (
         compare_album(left_track.album, right_track.album)
index b45cdab03d1ea121317bf626f822cacb139ce626..926ff3d461bcdee428ac633e71352be109d43201 100755 (executable)
@@ -83,9 +83,8 @@ def create_sort_name(name):
     return sort_name.lower()
 
 
-def parse_title_and_version(track_title, track_version=None):
+def parse_title_and_version(title: str, track_version: str = None):
     """Try to parse clean track title and version from the title."""
-    title = track_title.lower()
     version = ""
     for splitter in [" (", " [", " - ", " (", " [", "-"]:
         if splitter in title:
@@ -95,16 +94,6 @@ def parse_title_and_version(track_title, track_version=None):
                 for end_splitter in [")", "]"]:
                     if end_splitter in title_part:
                         title_part = title_part.split(end_splitter)[0]
-                for ignore_str in [
-                    "feat.",
-                    "featuring",
-                    "ft.",
-                    "with ",
-                    " & ",
-                    "explicit",
-                ]:
-                    if ignore_str in title_part:
-                        title = title.split(splitter + title_part)[0]
                 for version_str in [
                     "version",
                     "live",
@@ -122,10 +111,10 @@ def parse_title_and_version(track_title, track_version=None):
                     "akoestisch",
                     "deluxe",
                 ]:
-                    if version_str in title_part:
+                    if version_str in title_part.lower():
                         version = title_part
                         title = title.split(splitter + version)[0]
-    title = title.strip().title()
+    title = clean_title(title)
     if not version and track_version:
         version = track_version
     version = get_version_substitute(version).title()
@@ -134,7 +123,23 @@ def parse_title_and_version(track_title, track_version=None):
     return title, version
 
 
-def get_version_substitute(version_str):
+def clean_title(title: str) -> str:
+    """Strip unwanted additional text from title."""
+    for splitter in [" (", " [", " - ", " (", " [", "-"]:
+        if splitter in title:
+            title_parts = title.split(splitter)
+            for title_part in title_parts:
+                # look for the end splitter
+                for end_splitter in [")", "]"]:
+                    if end_splitter in title_part:
+                        title_part = title_part.split(end_splitter)[0]
+                for ignore_str in ["feat.", "featuring", "ft.", "with ", "explicit"]:
+                    if ignore_str in title_part.lower():
+                        return title.split(splitter + title_part)[0].strip()
+    return title.strip()
+
+
+def get_version_substitute(version_str: str):
     """Transform provider version str to universal version type."""
     version_str = version_str.lower()
     # substitute edit and edition with version
diff --git a/tests/utils.py b/tests/utils.py
new file mode 100644 (file)
index 0000000..6f21487
--- /dev/null
@@ -0,0 +1,12 @@
+"""Tests for utility functions."""
+
+from music_assistant.helpers import util
+
+
+def test_version_extract():
+    """Test the extraction of version from title."""
+
+    test_str = "Bam Bam (feat. Ed Sheeran) - Karaoke Version"
+    title, version = util.parse_title_and_version(test_str)
+    assert title == "Bam Bam"
+    assert version == "Karaoke Version"