Merge pull request #22 from PiratesIRC/claude/debug-stream-api-json-017BZwHDvFFpCCSU2kgBu595
Debug invalid JSON response from stream API
This commit is contained in:
@@ -118,8 +118,8 @@ class Plugin:
|
|||||||
"id": "fuzzy_match_threshold",
|
"id": "fuzzy_match_threshold",
|
||||||
"label": "🎯 Fuzzy Match Threshold",
|
"label": "🎯 Fuzzy Match Threshold",
|
||||||
"type": "number",
|
"type": "number",
|
||||||
"default": 85,
|
"default": 65,
|
||||||
"help_text": "Minimum similarity score (0-100) for fuzzy matching. Higher values require closer matches. Default: 85",
|
"help_text": "Minimum similarity score (0-100) for fuzzy matching. Higher values require closer matches. Default: 65",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "dispatcharr_url",
|
"id": "dispatcharr_url",
|
||||||
@@ -227,7 +227,7 @@ class Plugin:
|
|||||||
{"label": "Medium (Standard)", "value": "medium"},
|
{"label": "Medium (Standard)", "value": "medium"},
|
||||||
{"label": "High (Slow)", "value": "high"},
|
{"label": "High (Slow)", "value": "high"},
|
||||||
],
|
],
|
||||||
"default": "medium",
|
"default": "none",
|
||||||
"help_text": "Controls delay between API calls. None=No delays, Low=Fast/Aggressive, Medium=Standard, High=Slow/Safe.",
|
"help_text": "Controls delay between API calls. None=No delays, Low=Fast/Aggressive, Medium=Standard, High=Slow/Safe.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1619,7 +1619,7 @@ class Plugin:
|
|||||||
settings = context['settings']
|
settings = context['settings']
|
||||||
|
|
||||||
# Initialize fuzzy matcher with configured threshold
|
# Initialize fuzzy matcher with configured threshold
|
||||||
match_threshold = settings.get("fuzzy_match_threshold", 85)
|
match_threshold = settings.get("fuzzy_match_threshold", 65)
|
||||||
try:
|
try:
|
||||||
match_threshold = int(match_threshold)
|
match_threshold = int(match_threshold)
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
@@ -2008,7 +2008,7 @@ class Plugin:
|
|||||||
"""Load and process channels from specified profile and groups."""
|
"""Load and process channels from specified profile and groups."""
|
||||||
try:
|
try:
|
||||||
# Create the rate limiter instance once
|
# Create the rate limiter instance once
|
||||||
limiter = SmartRateLimiter(settings.get("rate_limiting", "medium"), logger)
|
limiter = SmartRateLimiter(settings.get("rate_limiting", "none"), logger)
|
||||||
|
|
||||||
self._send_progress_update("load_process_channels", 'running', 5, 'Validating settings...', context)
|
self._send_progress_update("load_process_channels", 'running', 5, 'Validating settings...', context)
|
||||||
logger.debug("[Stream-Mapparr] Validating settings before loading channels...")
|
logger.debug("[Stream-Mapparr] Validating settings before loading channels...")
|
||||||
@@ -2102,81 +2102,35 @@ class Plugin:
|
|||||||
|
|
||||||
group_name_to_id = {g['name']: g['id'] for g in all_groups if 'name' in g and 'id' in g}
|
group_name_to_id = {g['name']: g['id'] for g in all_groups if 'name' in g and 'id' in g}
|
||||||
|
|
||||||
# Fetch stream groups with rate limiting
|
# Fetch stream groups with rate limiting (returns array of group name strings)
|
||||||
self._send_progress_update("load_process_channels", 'running', 35, 'Fetching stream groups...', context)
|
self._send_progress_update("load_process_channels", 'running', 35, 'Fetching stream groups...', context)
|
||||||
all_stream_groups = []
|
all_stream_groups = []
|
||||||
page = 1
|
|
||||||
while True:
|
|
||||||
try:
|
try:
|
||||||
api_stream_groups = self._get_api_data(f"/api/channels/stream-groups/?page={page}", token, settings, logger, limiter=limiter)
|
api_stream_groups = self._get_api_data("/api/channels/streams/groups/", token, settings, logger, limiter=limiter)
|
||||||
except Exception as e:
|
if isinstance(api_stream_groups, list):
|
||||||
# If we get an error (e.g., 404 for non-existent page), we've reached the end
|
all_stream_groups = api_stream_groups
|
||||||
if page > 1:
|
|
||||||
logger.debug(f"[Stream-Mapparr] No more stream group pages available (attempted page {page})")
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# If error on first page, stream groups might not be available in this API version
|
|
||||||
logger.warning(f"[Stream-Mapparr] Could not fetch stream groups (API may not support this endpoint): {e}")
|
|
||||||
break
|
|
||||||
|
|
||||||
if isinstance(api_stream_groups, dict) and 'results' in api_stream_groups:
|
|
||||||
results = api_stream_groups['results']
|
|
||||||
if not results:
|
|
||||||
logger.debug("[Stream-Mapparr] Reached last page of stream groups (empty results)")
|
|
||||||
break
|
|
||||||
all_stream_groups.extend(results)
|
|
||||||
if not api_stream_groups.get('next'):
|
|
||||||
break
|
|
||||||
page += 1
|
|
||||||
elif isinstance(api_stream_groups, list):
|
|
||||||
if not api_stream_groups:
|
|
||||||
logger.debug("[Stream-Mapparr] Reached last page of stream groups (empty results)")
|
|
||||||
break
|
|
||||||
all_stream_groups.extend(api_stream_groups)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
|
||||||
stream_group_name_to_id = {g['name']: g['id'] for g in all_stream_groups if 'name' in g and 'id' in g}
|
|
||||||
logger.info(f"[Stream-Mapparr] Found {len(all_stream_groups)} stream groups")
|
logger.info(f"[Stream-Mapparr] Found {len(all_stream_groups)} stream groups")
|
||||||
|
else:
|
||||||
|
logger.warning(f"[Stream-Mapparr] Unexpected stream groups response format: {type(api_stream_groups)}")
|
||||||
|
except Exception as e:
|
||||||
|
# Stream groups might not be available in this API version
|
||||||
|
logger.warning(f"[Stream-Mapparr] Could not fetch stream groups (API may not support this endpoint): {e}")
|
||||||
|
|
||||||
# Fetch M3U sources with rate limiting
|
# Fetch M3U sources with rate limiting (returns array of M3U account objects)
|
||||||
self._send_progress_update("load_process_channels", 'running', 37, 'Fetching M3U sources...', context)
|
self._send_progress_update("load_process_channels", 'running', 37, 'Fetching M3U sources...', context)
|
||||||
all_m3us = []
|
all_m3us = []
|
||||||
page = 1
|
|
||||||
while True:
|
|
||||||
try:
|
try:
|
||||||
api_m3us = self._get_api_data(f"/api/channels/m3us/?page={page}", token, settings, logger, limiter=limiter)
|
api_m3us = self._get_api_data("/api/m3u/accounts/", token, settings, logger, limiter=limiter)
|
||||||
|
if isinstance(api_m3us, list):
|
||||||
|
all_m3us = api_m3us
|
||||||
|
logger.info(f"[Stream-Mapparr] Found {len(all_m3us)} M3U sources")
|
||||||
|
else:
|
||||||
|
logger.warning(f"[Stream-Mapparr] Unexpected M3U sources response format: {type(api_m3us)}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# If we get an error (e.g., 404 for non-existent page), we've reached the end
|
# M3U sources might not be available in this API version
|
||||||
if page > 1:
|
|
||||||
logger.debug(f"[Stream-Mapparr] No more M3U pages available (attempted page {page})")
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
# If error on first page, M3Us might not be available in this API version
|
|
||||||
logger.warning(f"[Stream-Mapparr] Could not fetch M3U sources (API may not support this endpoint): {e}")
|
logger.warning(f"[Stream-Mapparr] Could not fetch M3U sources (API may not support this endpoint): {e}")
|
||||||
break
|
|
||||||
|
|
||||||
if isinstance(api_m3us, dict) and 'results' in api_m3us:
|
|
||||||
results = api_m3us['results']
|
|
||||||
if not results:
|
|
||||||
logger.debug("[Stream-Mapparr] Reached last page of M3Us (empty results)")
|
|
||||||
break
|
|
||||||
all_m3us.extend(results)
|
|
||||||
if not api_m3us.get('next'):
|
|
||||||
break
|
|
||||||
page += 1
|
|
||||||
elif isinstance(api_m3us, list):
|
|
||||||
if not api_m3us:
|
|
||||||
logger.debug("[Stream-Mapparr] Reached last page of M3Us (empty results)")
|
|
||||||
break
|
|
||||||
all_m3us.extend(api_m3us)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
|
||||||
m3u_name_to_id = {m['name']: m['id'] for m in all_m3us if 'name' in m and 'id' in m}
|
m3u_name_to_id = {m['name']: m['id'] for m in all_m3us if 'name' in m and 'id' in m}
|
||||||
logger.info(f"[Stream-Mapparr] Found {len(all_m3us)} M3U sources")
|
|
||||||
|
|
||||||
# Fetch channels with rate limiting
|
# Fetch channels with rate limiting
|
||||||
self._send_progress_update("load_process_channels", 'running', 40, 'Fetching channels...', context)
|
self._send_progress_update("load_process_channels", 'running', 40, 'Fetching channels...', context)
|
||||||
@@ -2268,17 +2222,17 @@ class Plugin:
|
|||||||
logger.warning("[Stream-Mapparr] Unexpected streams response format")
|
logger.warning("[Stream-Mapparr] Unexpected streams response format")
|
||||||
break
|
break
|
||||||
|
|
||||||
# Filter streams by selected stream groups
|
# Filter streams by selected stream groups (uses channel_group field)
|
||||||
if selected_stream_groups_str:
|
if selected_stream_groups_str:
|
||||||
selected_stream_groups = [g.strip() for g in selected_stream_groups_str.split(',') if g.strip()]
|
selected_stream_groups = [g.strip() for g in selected_stream_groups_str.split(',') if g.strip()]
|
||||||
valid_stream_group_ids = [stream_group_name_to_id[name] for name in selected_stream_groups if name in stream_group_name_to_id]
|
valid_stream_group_ids = [group_name_to_id[name] for name in selected_stream_groups if name in group_name_to_id]
|
||||||
if not valid_stream_group_ids:
|
if not valid_stream_group_ids:
|
||||||
logger.warning("[Stream-Mapparr] None of the specified stream groups were found. Using all streams.")
|
logger.warning("[Stream-Mapparr] None of the specified stream groups were found. Using all streams.")
|
||||||
selected_stream_groups = []
|
selected_stream_groups = []
|
||||||
stream_group_filter_info = " (all stream groups - specified groups not found)"
|
stream_group_filter_info = " (all stream groups - specified groups not found)"
|
||||||
else:
|
else:
|
||||||
# Filter streams by stream_group_id
|
# Filter streams by channel_group (which is the group ID)
|
||||||
filtered_streams = [s for s in all_streams_data if s.get('stream_group_id') in valid_stream_group_ids]
|
filtered_streams = [s for s in all_streams_data if s.get('channel_group') in valid_stream_group_ids]
|
||||||
logger.info(f"[Stream-Mapparr] Filtered streams from {len(all_streams_data)} to {len(filtered_streams)} based on stream groups: {', '.join(selected_stream_groups)}")
|
logger.info(f"[Stream-Mapparr] Filtered streams from {len(all_streams_data)} to {len(filtered_streams)} based on stream groups: {', '.join(selected_stream_groups)}")
|
||||||
all_streams_data = filtered_streams
|
all_streams_data = filtered_streams
|
||||||
stream_group_filter_info = f" in stream groups: {', '.join(selected_stream_groups)}"
|
stream_group_filter_info = f" in stream groups: {', '.join(selected_stream_groups)}"
|
||||||
@@ -2295,8 +2249,8 @@ class Plugin:
|
|||||||
selected_m3us = []
|
selected_m3us = []
|
||||||
m3u_filter_info = " (all M3U sources - specified M3Us not found)"
|
m3u_filter_info = " (all M3U sources - specified M3Us not found)"
|
||||||
else:
|
else:
|
||||||
# Filter streams by m3u_id
|
# Filter streams by m3u_account (which is the M3U account ID)
|
||||||
filtered_streams = [s for s in all_streams_data if s.get('m3u_id') in valid_m3u_ids]
|
filtered_streams = [s for s in all_streams_data if s.get('m3u_account') in valid_m3u_ids]
|
||||||
logger.info(f"[Stream-Mapparr] Filtered streams from {len(all_streams_data)} to {len(filtered_streams)} based on M3U sources: {', '.join(selected_m3us)}")
|
logger.info(f"[Stream-Mapparr] Filtered streams from {len(all_streams_data)} to {len(filtered_streams)} based on M3U sources: {', '.join(selected_m3us)}")
|
||||||
all_streams_data = filtered_streams
|
all_streams_data = filtered_streams
|
||||||
m3u_filter_info = f" in M3U sources: {', '.join(selected_m3us)}"
|
m3u_filter_info = f" in M3U sources: {', '.join(selected_m3us)}"
|
||||||
@@ -2351,7 +2305,7 @@ class Plugin:
|
|||||||
selected_groups = processed_data.get('selected_groups', [])
|
selected_groups = processed_data.get('selected_groups', [])
|
||||||
selected_stream_groups = processed_data.get('selected_stream_groups', [])
|
selected_stream_groups = processed_data.get('selected_stream_groups', [])
|
||||||
selected_m3us = processed_data.get('selected_m3us', [])
|
selected_m3us = processed_data.get('selected_m3us', [])
|
||||||
current_threshold = settings.get('fuzzy_match_threshold', 85)
|
current_threshold = settings.get('fuzzy_match_threshold', 65)
|
||||||
|
|
||||||
# Build header with all settings except login credentials
|
# Build header with all settings except login credentials
|
||||||
header_lines = [
|
header_lines = [
|
||||||
@@ -2409,7 +2363,7 @@ class Plugin:
|
|||||||
f"# Enable Scheduled CSV Export: {settings.get('enable_scheduled_csv_export', False)}",
|
f"# Enable Scheduled CSV Export: {settings.get('enable_scheduled_csv_export', False)}",
|
||||||
"#",
|
"#",
|
||||||
"# === API Settings ===",
|
"# === API Settings ===",
|
||||||
f"# Rate Limiting: {settings.get('rate_limiting', 'medium')}",
|
f"# Rate Limiting: {settings.get('rate_limiting', 'none')}",
|
||||||
"#",
|
"#",
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -2602,7 +2556,7 @@ class Plugin:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
self._send_progress_update("preview_changes", 'running', 5, 'Initializing preview...', context)
|
self._send_progress_update("preview_changes", 'running', 5, 'Initializing preview...', context)
|
||||||
limiter = SmartRateLimiter(settings.get("rate_limiting", "medium"), logger)
|
limiter = SmartRateLimiter(settings.get("rate_limiting", "none"), logger)
|
||||||
|
|
||||||
self._send_progress_update("preview_changes", 'running', 10, 'Validating settings...', context)
|
self._send_progress_update("preview_changes", 'running', 10, 'Validating settings...', context)
|
||||||
has_errors, validation_results, token = self._validate_plugin_settings(settings, logger)
|
has_errors, validation_results, token = self._validate_plugin_settings(settings, logger)
|
||||||
@@ -2638,7 +2592,7 @@ class Plugin:
|
|||||||
total_channels_to_update = 0
|
total_channels_to_update = 0
|
||||||
low_match_channels = [] # Track channels with few matches for recommendations
|
low_match_channels = [] # Track channels with few matches for recommendations
|
||||||
threshold_data = {} # Track threshold analysis for recommendations
|
threshold_data = {} # Track threshold analysis for recommendations
|
||||||
current_threshold = settings.get('fuzzy_match_threshold', 85)
|
current_threshold = settings.get('fuzzy_match_threshold', 65)
|
||||||
try:
|
try:
|
||||||
current_threshold = int(current_threshold)
|
current_threshold = int(current_threshold)
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
@@ -2790,7 +2744,7 @@ class Plugin:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
self._send_progress_update("add_streams_to_channels", 'running', 5, 'Initializing stream assignment...', context)
|
self._send_progress_update("add_streams_to_channels", 'running', 5, 'Initializing stream assignment...', context)
|
||||||
limiter = SmartRateLimiter(settings.get("rate_limiting", "medium"), logger)
|
limiter = SmartRateLimiter(settings.get("rate_limiting", "none"), logger)
|
||||||
|
|
||||||
self._send_progress_update("add_streams_to_channels", 'running', 10, 'Authenticating...', context)
|
self._send_progress_update("add_streams_to_channels", 'running', 10, 'Authenticating...', context)
|
||||||
token, error = self._get_api_token(settings, logger)
|
token, error = self._get_api_token(settings, logger)
|
||||||
@@ -2911,7 +2865,7 @@ class Plugin:
|
|||||||
csv_data = []
|
csv_data = []
|
||||||
low_match_channels = [] # Track channels with few matches for recommendations
|
low_match_channels = [] # Track channels with few matches for recommendations
|
||||||
threshold_data = {} # Track threshold analysis for recommendations
|
threshold_data = {} # Track threshold analysis for recommendations
|
||||||
current_threshold = settings.get('fuzzy_match_threshold', 85)
|
current_threshold = settings.get('fuzzy_match_threshold', 65)
|
||||||
try:
|
try:
|
||||||
current_threshold = int(current_threshold)
|
current_threshold = int(current_threshold)
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
|
|||||||
Reference in New Issue
Block a user