summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathéo Gevraise <82399666+FunWarry@users.noreply.github.com>2026-01-23 11:33:03 +0100
committerGitHub <noreply@github.com>2026-01-23 11:33:03 +0100
commit651daa9ca9cae9a3809837bbed41cb6fb9002d70 (patch)
tree9704bdb8c2c14bf4042ff45557459e17d63bb0fa
parent81f3995aff1336ac7a3b84de43c8c2eafa65047d (diff)
parent173b40bef20ae4d0d9b2b06b8c06701c892b298e (diff)
downloadtidal-dl-ng-651daa9ca9cae9a3809837bbed41cb6fb9002d70.tar.gz
Merge pull request #17 from musicalmusicalmusical/master
fix: Handle non-integer AdaptationSet id/group in TIDAL manifests
-rw-r--r--tidal_dl_ng/__init__.py6
-rw-r--r--tidal_dl_ng/helper/mpegdash_patch.py88
2 files changed, 94 insertions, 0 deletions
diff --git a/tidal_dl_ng/__init__.py b/tidal_dl_ng/__init__.py
index b7a692c..17739c7 100644
--- a/tidal_dl_ng/__init__.py
+++ b/tidal_dl_ng/__init__.py
@@ -1,4 +1,10 @@
#!/usr/bin/env python
+# Apply mpegdash patch before any tidalapi imports to fix TIDAL manifest parsing
+# See: https://github.com/FunWarry/tidal-dl-ng-For-DJ/issues/15
+from tidal_dl_ng.helper.mpegdash_patch import apply_mpegdash_patch
+
+apply_mpegdash_patch()
+
import importlib.metadata
from pathlib import Path
from urllib.parse import urlparse
diff --git a/tidal_dl_ng/helper/mpegdash_patch.py b/tidal_dl_ng/helper/mpegdash_patch.py
new file mode 100644
index 0000000..3645436
--- /dev/null
+++ b/tidal_dl_ng/helper/mpegdash_patch.py
@@ -0,0 +1,88 @@
+"""
+Monkey-patch for mpegdash to handle non-integer AdaptationSet id/group attributes.
+
+TIDAL recently started returning MPD manifests with string values like "main"
+for the AdaptationSet `id` and `group` attributes, which mpegdash expects to be integers.
+This causes a ValueError: invalid literal for int() with base 10: 'main'
+
+This patch modifies the parse_attr_value function to gracefully handle
+non-integer values for attributes that are expected to be integers.
+"""
+
+import logging
+
+logger = logging.getLogger(__name__)
+
+_patched = False
+
+
+def _safe_int(value: str) -> int | None:
+ """Safely convert a value to int, returning None if conversion fails."""
+ try:
+ return int(value)
+ except (ValueError, TypeError):
+ return None
+
+
+def apply_mpegdash_patch() -> None:
+ """
+ Apply a monkey-patch to mpegdash to handle string values in integer fields.
+
+ This patches the parse_attr_value function in mpegdash.utils to gracefully
+ handle non-integer values (like "main") for attributes expected to be integers.
+ """
+ global _patched
+
+ if _patched:
+ return
+
+ try:
+ from mpegdash import utils as mpegdash_utils
+ import re
+
+ # Store the original function
+ original_parse_attr_value = mpegdash_utils.parse_attr_value
+
+ def patched_parse_attr_value(xmlnode, attr_name, value_type):
+ """
+ Patched version of parse_attr_value that handles non-integer values gracefully.
+ """
+ if attr_name not in xmlnode.attributes.keys():
+ return None
+
+ attr_val = xmlnode.attributes[attr_name].nodeValue
+
+ if isinstance(value_type, list):
+ attr_type = value_type[0] if len(value_type) > 0 else str
+ try:
+ return [attr_type(elem) for elem in re.split(r"[, ]", attr_val)]
+ except (ValueError, TypeError):
+ # If conversion fails, return as strings
+ return [str(elem) for elem in re.split(r"[, ]", attr_val)]
+
+ # Handle integer conversion failures gracefully
+ if value_type == int:
+ result = _safe_int(attr_val)
+ if result is None:
+ logger.debug(
+ f"mpegdash: Could not convert '{attr_name}'='{attr_val}' to int, using None"
+ )
+ return result
+
+ try:
+ return value_type(attr_val)
+ except (ValueError, TypeError):
+ logger.debug(
+ f"mpegdash: Could not convert '{attr_name}'='{attr_val}' to {value_type.__name__}, using None"
+ )
+ return None
+
+ # Apply the patch
+ mpegdash_utils.parse_attr_value = patched_parse_attr_value
+ _patched = True
+ logger.debug("mpegdash patch applied successfully")
+
+ except ImportError:
+ logger.warning("Could not import mpegdash, patch not applied")
+ except Exception as e:
+ logger.warning(f"Failed to apply mpegdash patch: {e}")