mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-01-23 02:35:14 +00:00
Enhancement: Add custom fallback templates for dummy EPG generation to handle unmatched patterns
This commit is contained in:
parent
4284955412
commit
0741e45ce6
2 changed files with 131 additions and 2 deletions
|
|
@ -187,6 +187,54 @@ def generate_m3u(request, profile_name=None, user=None):
|
|||
return response
|
||||
|
||||
|
||||
def generate_fallback_programs(channel_id, channel_name, now, num_days, program_length_hours, fallback_title, fallback_description):
|
||||
"""
|
||||
Generate dummy programs using custom fallback templates when patterns don't match.
|
||||
|
||||
Args:
|
||||
channel_id: Channel ID for the programs
|
||||
channel_name: Channel name to use as fallback in templates
|
||||
now: Current datetime (in UTC)
|
||||
num_days: Number of days to generate programs for
|
||||
program_length_hours: Length of each program in hours
|
||||
fallback_title: Custom fallback title template (empty string if not provided)
|
||||
fallback_description: Custom fallback description template (empty string if not provided)
|
||||
|
||||
Returns:
|
||||
List of program dictionaries
|
||||
"""
|
||||
programs = []
|
||||
|
||||
# Use custom fallback title or channel name as default
|
||||
title = fallback_title if fallback_title else channel_name
|
||||
|
||||
# Use custom fallback description or a simple default message
|
||||
if fallback_description:
|
||||
description = fallback_description
|
||||
else:
|
||||
description = f"EPG information is currently unavailable for {channel_name}"
|
||||
|
||||
# Create programs for each day
|
||||
for day in range(num_days):
|
||||
day_start = now + timedelta(days=day)
|
||||
|
||||
# Create programs with specified length throughout the day
|
||||
for hour_offset in range(0, 24, program_length_hours):
|
||||
# Calculate program start and end times
|
||||
start_time = day_start + timedelta(hours=hour_offset)
|
||||
end_time = start_time + timedelta(hours=program_length_hours)
|
||||
|
||||
programs.append({
|
||||
"channel_id": channel_id,
|
||||
"start_time": start_time,
|
||||
"end_time": end_time,
|
||||
"title": title,
|
||||
"description": description,
|
||||
})
|
||||
|
||||
return programs
|
||||
|
||||
|
||||
def generate_dummy_programs(channel_id, channel_name, num_days=1, program_length_hours=4, epg_source=None):
|
||||
"""
|
||||
Generate dummy EPG programs for channels.
|
||||
|
|
@ -216,11 +264,26 @@ def generate_dummy_programs(channel_id, channel_name, num_days=1, program_length
|
|||
epg_source.custom_properties
|
||||
)
|
||||
# If custom generation succeeded, return those programs
|
||||
# If it returned empty (pattern didn't match), fall through to default
|
||||
# If it returned empty (pattern didn't match), check for custom fallback templates
|
||||
if custom_programs:
|
||||
return custom_programs
|
||||
else:
|
||||
logger.info(f"Custom pattern didn't match for '{channel_name}', using default dummy EPG")
|
||||
logger.info(f"Custom pattern didn't match for '{channel_name}', checking for custom fallback templates")
|
||||
|
||||
# Check if custom fallback templates are provided
|
||||
custom_props = epg_source.custom_properties
|
||||
fallback_title = custom_props.get('fallback_title_template', '').strip()
|
||||
fallback_description = custom_props.get('fallback_description_template', '').strip()
|
||||
|
||||
# If custom fallback templates exist, use them instead of default
|
||||
if fallback_title or fallback_description:
|
||||
logger.info(f"Using custom fallback templates for '{channel_name}'")
|
||||
return generate_fallback_programs(
|
||||
channel_id, channel_name, now, num_days,
|
||||
program_length_hours, fallback_title, fallback_description
|
||||
)
|
||||
else:
|
||||
logger.info(f"No custom fallback templates found, using default dummy EPG")
|
||||
|
||||
# Default humorous program descriptions based on time of day
|
||||
time_descriptions = {
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ const DummyEPGForm = ({ epg, isOpen, onClose }) => {
|
|||
useState('');
|
||||
const [endedTitleTemplate, setEndedTitleTemplate] = useState('');
|
||||
const [endedDescriptionTemplate, setEndedDescriptionTemplate] = useState('');
|
||||
const [fallbackTitleTemplate, setFallbackTitleTemplate] = useState('');
|
||||
const [fallbackDescriptionTemplate, setFallbackDescriptionTemplate] =
|
||||
useState('');
|
||||
const [channelLogoUrl, setChannelLogoUrl] = useState('');
|
||||
const [programPosterUrl, setProgramPosterUrl] = useState('');
|
||||
const [timezoneOptions, setTimezoneOptions] = useState([]);
|
||||
|
|
@ -73,6 +76,8 @@ const DummyEPGForm = ({ epg, isOpen, onClose }) => {
|
|||
upcoming_description_template: '',
|
||||
ended_title_template: '',
|
||||
ended_description_template: '',
|
||||
fallback_title_template: '',
|
||||
fallback_description_template: '',
|
||||
channel_logo_url: '',
|
||||
program_poster_url: '',
|
||||
name_source: 'channel',
|
||||
|
|
@ -463,6 +468,9 @@ const DummyEPGForm = ({ epg, isOpen, onClose }) => {
|
|||
custom.upcoming_description_template || '',
|
||||
ended_title_template: custom.ended_title_template || '',
|
||||
ended_description_template: custom.ended_description_template || '',
|
||||
fallback_title_template: custom.fallback_title_template || '',
|
||||
fallback_description_template:
|
||||
custom.fallback_description_template || '',
|
||||
channel_logo_url: custom.channel_logo_url || '',
|
||||
program_poster_url: custom.program_poster_url || '',
|
||||
name_source: custom.name_source || 'channel',
|
||||
|
|
@ -487,6 +495,10 @@ const DummyEPGForm = ({ epg, isOpen, onClose }) => {
|
|||
);
|
||||
setEndedTitleTemplate(custom.ended_title_template || '');
|
||||
setEndedDescriptionTemplate(custom.ended_description_template || '');
|
||||
setFallbackTitleTemplate(custom.fallback_title_template || '');
|
||||
setFallbackDescriptionTemplate(
|
||||
custom.fallback_description_template || ''
|
||||
);
|
||||
setChannelLogoUrl(custom.channel_logo_url || '');
|
||||
setProgramPosterUrl(custom.program_poster_url || '');
|
||||
} else {
|
||||
|
|
@ -501,6 +513,8 @@ const DummyEPGForm = ({ epg, isOpen, onClose }) => {
|
|||
setUpcomingDescriptionTemplate('');
|
||||
setEndedTitleTemplate('');
|
||||
setEndedDescriptionTemplate('');
|
||||
setFallbackTitleTemplate('');
|
||||
setFallbackDescriptionTemplate('');
|
||||
setChannelLogoUrl('');
|
||||
setProgramPosterUrl('');
|
||||
}
|
||||
|
|
@ -571,6 +585,9 @@ const DummyEPGForm = ({ epg, isOpen, onClose }) => {
|
|||
custom.upcoming_description_template || '',
|
||||
ended_title_template: custom.ended_title_template || '',
|
||||
ended_description_template: custom.ended_description_template || '',
|
||||
fallback_title_template: custom.fallback_title_template || '',
|
||||
fallback_description_template:
|
||||
custom.fallback_description_template || '',
|
||||
channel_logo_url: custom.channel_logo_url || '',
|
||||
program_poster_url: custom.program_poster_url || '',
|
||||
name_source: custom.name_source || 'channel',
|
||||
|
|
@ -593,6 +610,8 @@ const DummyEPGForm = ({ epg, isOpen, onClose }) => {
|
|||
setUpcomingDescriptionTemplate(custom.upcoming_description_template || '');
|
||||
setEndedTitleTemplate(custom.ended_title_template || '');
|
||||
setEndedDescriptionTemplate(custom.ended_description_template || '');
|
||||
setFallbackTitleTemplate(custom.fallback_title_template || '');
|
||||
setFallbackDescriptionTemplate(custom.fallback_description_template || '');
|
||||
setChannelLogoUrl(custom.channel_logo_url || '');
|
||||
setProgramPosterUrl(custom.program_poster_url || '');
|
||||
|
||||
|
|
@ -872,6 +891,53 @@ const DummyEPGForm = ({ epg, isOpen, onClose }) => {
|
|||
}}
|
||||
/>
|
||||
|
||||
{/* Fallback Templates */}
|
||||
<Divider
|
||||
label="Fallback Templates (Optional)"
|
||||
labelPosition="center"
|
||||
/>
|
||||
|
||||
<Text size="sm" c="dimmed">
|
||||
When patterns don't match the channel/stream name, use these custom
|
||||
fallback templates instead of the default placeholder messages.
|
||||
Leave empty to use the built-in humorous fallback descriptions.
|
||||
</Text>
|
||||
|
||||
<TextInput
|
||||
id="fallback_title_template"
|
||||
name="fallback_title_template"
|
||||
label="Fallback Title Template"
|
||||
description="Custom title when patterns don't match. If empty, uses the channel/stream name."
|
||||
placeholder="No EPG data available"
|
||||
value={fallbackTitleTemplate}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
setFallbackTitleTemplate(value);
|
||||
form.setFieldValue(
|
||||
'custom_properties.fallback_title_template',
|
||||
value
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
||||
<Textarea
|
||||
id="fallback_description_template"
|
||||
name="fallback_description_template"
|
||||
label="Fallback Description Template"
|
||||
description="Custom description when patterns don't match. If empty, uses built-in placeholder messages."
|
||||
placeholder="EPG information is currently unavailable for this channel."
|
||||
minRows={2}
|
||||
value={fallbackDescriptionTemplate}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value;
|
||||
setFallbackDescriptionTemplate(value);
|
||||
form.setFieldValue(
|
||||
'custom_properties.fallback_description_template',
|
||||
value
|
||||
);
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* EPG Settings */}
|
||||
<Divider label="EPG Settings" labelPosition="center" />
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue