mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-25 19:14:00 +00:00
Added custom properties to programme
This commit is contained in:
parent
d2dbbcc136
commit
990a9ec7b7
2 changed files with 171 additions and 3 deletions
|
|
@ -177,15 +177,97 @@ def parse_programs_for_tvg_id(epg_id):
|
|||
end_time = parse_xmltv_time(prog.get('stop'))
|
||||
title = prog.findtext('title', default='No Title')
|
||||
desc = prog.findtext('desc', default='')
|
||||
sub_title = prog.findtext('sub-title', default='')
|
||||
|
||||
# Extract custom properties
|
||||
custom_props = {}
|
||||
|
||||
# Extract categories
|
||||
categories = []
|
||||
for cat_elem in prog.findall('category'):
|
||||
if cat_elem.text and cat_elem.text.strip():
|
||||
categories.append(cat_elem.text.strip())
|
||||
if categories:
|
||||
custom_props['categories'] = categories
|
||||
|
||||
# Extract episode numbers
|
||||
for ep_num in prog.findall('episode-num'):
|
||||
system = ep_num.get('system', '')
|
||||
if system == 'xmltv_ns' and ep_num.text:
|
||||
# Parse XMLTV episode-num format (season.episode.part)
|
||||
parts = ep_num.text.split('.')
|
||||
if len(parts) >= 2:
|
||||
if parts[0].strip() != '':
|
||||
try:
|
||||
season = int(parts[0]) + 1 # XMLTV format is zero-based
|
||||
custom_props['season'] = season
|
||||
except ValueError:
|
||||
pass
|
||||
if parts[1].strip() != '':
|
||||
try:
|
||||
episode = int(parts[1]) + 1 # XMLTV format is zero-based
|
||||
custom_props['episode'] = episode
|
||||
except ValueError:
|
||||
pass
|
||||
elif system == 'onscreen' and ep_num.text:
|
||||
# Just store the raw onscreen format
|
||||
custom_props['onscreen_episode'] = ep_num.text.strip()
|
||||
|
||||
# Extract ratings
|
||||
for rating_elem in prog.findall('rating'):
|
||||
if rating_elem.findtext('value'):
|
||||
custom_props['rating'] = rating_elem.findtext('value').strip()
|
||||
if rating_elem.get('system'):
|
||||
custom_props['rating_system'] = rating_elem.get('system')
|
||||
break # Just use the first rating
|
||||
|
||||
# Extract credits (actors, directors, etc.)
|
||||
credits_elem = prog.find('credits')
|
||||
if credits_elem is not None:
|
||||
credits = {}
|
||||
for credit_type in ['director', 'actor', 'writer', 'presenter', 'producer']:
|
||||
elements = credits_elem.findall(credit_type)
|
||||
if elements:
|
||||
names = [e.text.strip() for e in elements if e.text and e.text.strip()]
|
||||
if names:
|
||||
credits[credit_type] = names
|
||||
if credits:
|
||||
custom_props['credits'] = credits
|
||||
|
||||
# Extract other common program metadata
|
||||
if prog.findtext('date'):
|
||||
custom_props['year'] = prog.findtext('date').strip()[:4] # Just the year part
|
||||
|
||||
if prog.findtext('country'):
|
||||
custom_props['country'] = prog.findtext('country').strip()
|
||||
|
||||
for icon_elem in prog.findall('icon'):
|
||||
if icon_elem.get('src'):
|
||||
custom_props['icon'] = icon_elem.get('src')
|
||||
break # Just use the first icon
|
||||
|
||||
for kw in ['previously-shown', 'premiere', 'new']:
|
||||
if prog.find(kw) is not None:
|
||||
custom_props[kw.replace('-', '_')] = True
|
||||
|
||||
# Convert custom_props to JSON string if not empty
|
||||
custom_properties_json = None
|
||||
if custom_props:
|
||||
import json
|
||||
try:
|
||||
custom_properties_json = json.dumps(custom_props)
|
||||
except Exception as e:
|
||||
logger.error(f"Error serializing custom properties to JSON: {e}", exc_info=True)
|
||||
|
||||
programs_to_create.append(ProgramData(
|
||||
epg=epg,
|
||||
start_time=start_time,
|
||||
title=title,
|
||||
end_time=end_time,
|
||||
title=title,
|
||||
description=desc,
|
||||
sub_title='',
|
||||
sub_title=sub_title,
|
||||
tvg_id=epg.tvg_id,
|
||||
custom_properties=custom_properties_json
|
||||
))
|
||||
|
||||
ProgramData.objects.bulk_create(programs_to_create)
|
||||
|
|
|
|||
|
|
@ -105,7 +105,93 @@ def generate_epg(request, profile_name=None):
|
|||
stop_str = prog.end_time.strftime("%Y%m%d%H%M%S %z")
|
||||
xml_lines.append(f' <programme start="{start_str}" stop="{stop_str}" channel="{channel_id}">')
|
||||
xml_lines.append(f' <title>{prog.title}</title>')
|
||||
xml_lines.append(f' <desc>{prog.description}</desc>')
|
||||
|
||||
# Add subtitle if available
|
||||
if prog.sub_title:
|
||||
xml_lines.append(f' <sub-title>{prog.sub_title}</sub-title>')
|
||||
|
||||
# Add description if available
|
||||
if prog.description:
|
||||
xml_lines.append(f' <desc>{prog.description}</desc>')
|
||||
|
||||
# Process custom properties if available
|
||||
if prog.custom_properties:
|
||||
try:
|
||||
import json
|
||||
custom_data = json.loads(prog.custom_properties)
|
||||
|
||||
# Add categories if available
|
||||
if 'categories' in custom_data and custom_data['categories']:
|
||||
for category in custom_data['categories']:
|
||||
xml_lines.append(f' <category>{category}</category>')
|
||||
|
||||
# Handle episode numbering - multiple formats supported
|
||||
# Standard episode number if available
|
||||
if 'episode' in custom_data:
|
||||
xml_lines.append(f' <episode-num system="onscreen">E{custom_data["episode"]}</episode-num>')
|
||||
|
||||
# Handle onscreen episode format (like S06E128)
|
||||
if 'onscreen_episode' in custom_data:
|
||||
xml_lines.append(f' <episode-num system="onscreen">{custom_data["onscreen_episode"]}</episode-num>')
|
||||
|
||||
# Add season and episode numbers in xmltv_ns format if available
|
||||
if 'season' in custom_data and 'episode' in custom_data:
|
||||
season = int(custom_data['season']) - 1 if str(custom_data['season']).isdigit() else 0
|
||||
episode = int(custom_data['episode']) - 1 if str(custom_data['episode']).isdigit() else 0
|
||||
xml_lines.append(f' <episode-num system="xmltv_ns">{season}.{episode}.</episode-num>')
|
||||
|
||||
# Add rating if available
|
||||
if 'rating' in custom_data:
|
||||
rating_system = custom_data.get('rating_system', 'TV Parental Guidelines')
|
||||
xml_lines.append(f' <rating system="{rating_system}">')
|
||||
xml_lines.append(f' <value>{custom_data["rating"]}</value>')
|
||||
xml_lines.append(f' </rating>')
|
||||
|
||||
# Add actors/directors/writers if available
|
||||
if 'credits' in custom_data:
|
||||
xml_lines.append(f' <credits>')
|
||||
for role, people in custom_data['credits'].items():
|
||||
if isinstance(people, list):
|
||||
for person in people:
|
||||
xml_lines.append(f' <{role}>{person}</{role}>')
|
||||
else:
|
||||
xml_lines.append(f' <{role}>{people}</{role}>')
|
||||
xml_lines.append(f' </credits>')
|
||||
|
||||
# Add program date/year if available
|
||||
if 'year' in custom_data:
|
||||
xml_lines.append(f' <date>{custom_data["year"]}</date>')
|
||||
|
||||
# Add country if available
|
||||
if 'country' in custom_data:
|
||||
xml_lines.append(f' <country>{custom_data["country"]}</country>')
|
||||
|
||||
# Add icon if available
|
||||
if 'icon' in custom_data:
|
||||
xml_lines.append(f' <icon src="{custom_data["icon"]}" />')
|
||||
|
||||
# Add special flags as proper tags
|
||||
if custom_data.get('previously_shown', False):
|
||||
xml_lines.append(f' <previously-shown />')
|
||||
|
||||
if custom_data.get('premiere', False):
|
||||
xml_lines.append(f' <premiere />')
|
||||
|
||||
if custom_data.get('new', False):
|
||||
xml_lines.append(f' <new />')
|
||||
|
||||
# Define all properties we specifically handle to avoid adding them as comments
|
||||
skip_keys = [
|
||||
'categories', 'episode', 'season', 'rating', 'rating_system', 'credits',
|
||||
'year', 'country', 'icon', 'previously_shown', 'premiere', 'new',
|
||||
'onscreen_episode'
|
||||
]
|
||||
|
||||
# Don't add comments for standard properties - XMLTV clients don't need them
|
||||
# and they just clutter the output
|
||||
except Exception as e:
|
||||
xml_lines.append(f' <!-- Error parsing custom properties: {str(e)} -->')
|
||||
|
||||
xml_lines.append(' </programme>')
|
||||
|
||||
xml_lines.append('</tv>')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue