diff --git a/lib/clients/stremio/addon_client.py b/lib/clients/stremio/addon_client.py index 61b7deeb..3a7260e6 100644 --- a/lib/clients/stremio/addon_client.py +++ b/lib/clients/stremio/addon_client.py @@ -220,14 +220,14 @@ def parse_torrent_description(self, desc: str) -> Dict[str, Any]: "languages": [], } # Extract size - size_pattern = r"💾 ([\d.]+ (?:GB|MB))" - size_match = re.search(size_pattern, desc) + size_pattern = r"💾 ([\d.,]+ (?:GB|MB|Go|Mo))" + size_match = re.search(size_pattern, desc, re.IGNORECASE) size = size_match.group(1) if size_match else None if size: size = convert_size_to_bytes(size) # Extract seeders - seeders_pattern = r"👤 (\d+)" + seeders_pattern = r"[👥👤] (\d+)" seeders_match = re.search(seeders_pattern, desc) seeders = int(seeders_match.group(1)) if seeders_match else None diff --git a/lib/utils/kodi/utils.py b/lib/utils/kodi/utils.py index cede7be1..e495077d 100644 --- a/lib/utils/kodi/utils.py +++ b/lib/utils/kodi/utils.py @@ -518,18 +518,28 @@ def bytes_to_human_readable(size: int, unit: str = "B") -> str: def convert_size_to_bytes(size_str: str) -> int: - """Convert size string to bytes.""" - match = re.match(r"(\d+(?:\.\d+)?)\s*(GB|MB|KB|B)", size_str, re.IGNORECASE) + """Convert size string to bytes. + + Supports: + - Standard units: GB, MB, KB, B + - European units: Go, Mo, Ko (Gigaoctet, Megaoctet, Kilooctet) + - European decimal comma: 1,5 GB → treated as 1.5 GB + """ + # Normalize European decimal comma (only between digits, not a thousands separator) + size_str = re.sub(r"(\d),(\d)", r"\1.\2", size_str) + match = re.match( + r"(\d+(?:\.\d+)?)\s*(GB|MB|KB|B|Go|Mo|Ko)", size_str, re.IGNORECASE + ) if match: size, unit = match.groups() size = float(size) unit = unit.upper() - if unit == "GB": + if unit in ("GB", "GO"): return int(size * 1024**3) - if unit == "MB": + if unit in ("MB", "MO"): return int(size * 1024**2) - if unit == "KB": + if unit in ("KB", "KO"): return int(size * 1024) return int(size) return 0 diff --git a/tests/unit/test_kodi_utils.py b/tests/unit/test_kodi_utils.py index 49ec1caa..3fc1750d 100644 --- a/tests/unit/test_kodi_utils.py +++ b/tests/unit/test_kodi_utils.py @@ -1,3 +1,4 @@ +import pytest from unittest.mock import patch from lib.utils.kodi import utils @@ -42,3 +43,54 @@ def test_is_youtube_addon_enabled_returns_false_when_addon_is_disabled(): get_cond_visibility.assert_called_once_with(f"System.HasAddon({utils.YOUTUBE_ADDON_ID})") addon_cls.assert_called_once_with(utils.YOUTUBE_ADDON_ID) + + +@pytest.mark.parametrize( + ("input_str", "expected"), + [ + # Standard English units + ("1 GB", 1 * 1024**3), + ("2.5 GB", int(2.5 * 1024**3)), + ("500 MB", 500 * 1024**2), + ("100 KB", 100 * 1024), + ("42 B", 42), + # Case insensitivity + ("1.5 gb", int(1.5 * 1024**3)), + ("200 mb", 200 * 1024**2), + ("50 kb", 50 * 1024), + # European units (Go = GB, Mo = MB, Ko = KB) + ("1 Go", 1 * 1024**3), + ("1.5 Go", int(1.5 * 1024**3)), + ("500 Mo", 500 * 1024**2), + ("100 Ko", 100 * 1024), + # Case insensitivity for European units + ("2 go", 2 * 1024**3), + ("300 mo", 300 * 1024**2), + ("75 ko", 75 * 1024), + # European decimal comma → normalised to dot + ("1,5 GB", int(1.5 * 1024**3)), + ("2,5 Go", int(2.5 * 1024**3)), + ("500,5 MB", int(500.5 * 1024**2)), + # Edge cases + ("0 GB", 0), + ("0 MB", 0), + ("0 B", 0), + # Precision edge case – int truncation, not rounding + ("1.9 GB", int(1.9 * 1024**3)), + ], +) +def test_convert_size_to_bytes(input_str, expected): + assert utils.convert_size_to_bytes(input_str) == expected + + +@pytest.mark.parametrize( + ("input_str",), + [ + ("",), + ("not a size",), + ("ABC",), + ("1.5",), # missing unit + ], +) +def test_convert_size_to_bytes_invalid(input_str): + assert utils.convert_size_to_bytes(input_str) == 0