Bug Fix: M3UMovieRelation.get_stream_url() and M3UEpisodeRelation.get_stream_url() to use XC client's _normalize_url() method instead of simple rstrip('/'). This properly handles malformed M3U account URLs (e.g., containing /player_api.php or query parameters) before constructing VOD stream endpoints, matching behavior of live channel URL building. (Closes #722)

This commit is contained in:
SergeantPanda 2026-01-04 14:36:03 -06:00
parent 8ae1a98a3b
commit 6031885537
2 changed files with 10 additions and 4 deletions

View file

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Release workflow Docker tagging: Fixed issue where `latest` and version tags (e.g., `0.16.0`) were creating separate manifests instead of pointing to the same image digest, which caused old `latest` tags to become orphaned/untagged after new releases. Now creates a single multi-arch manifest with both tags, maintaining proper tag relationships and download statistics visibility on GitHub.
- Fixed onboarding message appearing in the Channels Table when filtered results are empty. The onboarding message now only displays when there are no channels created at all, not when channels exist but are filtered out by current filters.
- Fixed `M3UMovieRelation.get_stream_url()` and `M3UEpisodeRelation.get_stream_url()` to use XC client's `_normalize_url()` method instead of simple `rstrip('/')`. This properly handles malformed M3U account URLs (e.g., containing `/player_api.php` or query parameters) before constructing VOD stream endpoints, matching behavior of live channel URL building. (Closes #722)
## [0.16.0] - 2026-01-04

View file

@ -245,10 +245,13 @@ class M3UMovieRelation(models.Model):
"""Get the full stream URL for this movie from this provider"""
# Build URL dynamically for XtreamCodes accounts
if self.m3u_account.account_type == 'XC':
server_url = self.m3u_account.server_url.rstrip('/')
from core.xtream_codes import Client as XCClient
# Use XC client's URL normalization to handle malformed URLs
# (e.g., URLs with /player_api.php or query parameters)
normalized_url = XCClient(self.m3u_account.server_url, '', '')._normalize_url(self.m3u_account.server_url)
username = self.m3u_account.username
password = self.m3u_account.password
return f"{server_url}/movie/{username}/{password}/{self.stream_id}.{self.container_extension or 'mp4'}"
return f"{normalized_url}/movie/{username}/{password}/{self.stream_id}.{self.container_extension or 'mp4'}"
else:
# For other account types, we would need another way to build URLs
return None
@ -285,10 +288,12 @@ class M3UEpisodeRelation(models.Model):
if self.m3u_account.account_type == 'XC':
# For XtreamCodes accounts, build the URL dynamically
server_url = self.m3u_account.server_url.rstrip('/')
# Use XC client's URL normalization to handle malformed URLs
# (e.g., URLs with /player_api.php or query parameters)
normalized_url = XtreamCodesClient(self.m3u_account.server_url, '', '')._normalize_url(self.m3u_account.server_url)
username = self.m3u_account.username
password = self.m3u_account.password
return f"{server_url}/series/{username}/{password}/{self.stream_id}.{self.container_extension or 'mp4'}"
return f"{normalized_url}/series/{username}/{password}/{self.stream_id}.{self.container_extension or 'mp4'}"
else:
# We might support non XC accounts in the future
# For now, return None