Adds ability to reverse the sort order for auto channel sync.

This commit is contained in:
SergeantPanda 2025-08-01 16:42:42 -05:00
parent 7b5a617bf8
commit 1c47b7f84a
2 changed files with 77 additions and 36 deletions

View file

@ -884,6 +884,7 @@ def sync_auto_channels(account_id, scan_start_time=None):
name_match_regex = None
channel_profile_ids = None
channel_sort_order = None
channel_sort_reverse = False
if group_relation.custom_properties:
try:
group_custom_props = json.loads(group_relation.custom_properties)
@ -894,6 +895,7 @@ def sync_auto_channels(account_id, scan_start_time=None):
name_match_regex = group_custom_props.get("name_match_regex")
channel_profile_ids = group_custom_props.get("channel_profile_ids")
channel_sort_order = group_custom_props.get("channel_sort_order")
channel_sort_reverse = group_custom_props.get("channel_sort_reverse", False)
except Exception:
force_dummy_epg = False
override_group_id = None
@ -902,6 +904,7 @@ def sync_auto_channels(account_id, scan_start_time=None):
name_match_regex = None
channel_profile_ids = None
channel_sort_order = None
channel_sort_reverse = False
# Determine which group to use for created channels
target_group = channel_group
@ -936,18 +939,22 @@ def sync_auto_channels(account_id, scan_start_time=None):
if channel_sort_order == 'name':
# Use natural sorting for names to handle numbers correctly
current_streams = list(current_streams)
current_streams.sort(key=lambda stream: natural_sort_key(stream.name))
current_streams.sort(key=lambda stream: natural_sort_key(stream.name), reverse=channel_sort_reverse)
streams_is_list = True
elif channel_sort_order == 'tvg_id':
current_streams = current_streams.order_by('tvg_id')
order_prefix = '-' if channel_sort_reverse else ''
current_streams = current_streams.order_by(f'{order_prefix}tvg_id')
elif channel_sort_order == 'updated_at':
current_streams = current_streams.order_by('updated_at')
order_prefix = '-' if channel_sort_reverse else ''
current_streams = current_streams.order_by(f'{order_prefix}updated_at')
else:
logger.warning(f"Unknown channel_sort_order '{channel_sort_order}' for group '{channel_group.name}'. Using provider order.")
current_streams = current_streams.order_by('id')
order_prefix = '-' if channel_sort_reverse else ''
current_streams = current_streams.order_by(f'{order_prefix}id')
else:
current_streams = current_streams.order_by('id')
# If channel_sort_order is empty or None, use provider order (no additional sorting)
# Provider order (default) - can still be reversed
order_prefix = '-' if channel_sort_reverse else ''
current_streams = current_streams.order_by(f'{order_prefix}id')
# Get existing auto-created channels for this account (regardless of current group)
# We'll find them by their stream associations instead of just group location

View file

@ -410,8 +410,13 @@ const M3UGroupFilter = ({ playlist = null, isOpen, onClose }) => {
if (newCustomProps.channel_sort_order === undefined) {
newCustomProps.channel_sort_order = '';
}
// Keep channel_sort_reverse if it exists
if (newCustomProps.channel_sort_reverse === undefined) {
newCustomProps.channel_sort_reverse = false;
}
} else {
delete newCustomProps.channel_sort_order;
delete newCustomProps.channel_sort_reverse; // Remove reverse when sort is removed
}
return {
@ -428,36 +433,65 @@ const M3UGroupFilter = ({ playlist = null, isOpen, onClose }) => {
/>
{/* Show only channel_sort_order if selected */}
{group.custom_properties?.channel_sort_order !== undefined && (
<Select
label="Channel Sort Order"
placeholder="Select sort order..."
value={group.custom_properties?.channel_sort_order || ''}
onChange={(value) => {
setGroupStates(
groupStates.map((state) => {
if (state.channel_group === group.channel_group) {
return {
...state,
custom_properties: {
...state.custom_properties,
channel_sort_order: value || '',
},
};
}
return state;
})
);
}}
data={[
{ value: '', label: 'Provider Order (Default)' },
{ value: 'name', label: 'Name' },
{ value: 'tvg_id', label: 'TVG ID' },
{ value: 'updated_at', label: 'Updated At' },
]}
clearable
searchable
size="xs"
/>
<>
<Select
label="Channel Sort Order"
placeholder="Select sort order..."
value={group.custom_properties?.channel_sort_order || ''}
onChange={(value) => {
setGroupStates(
groupStates.map((state) => {
if (state.channel_group === group.channel_group) {
return {
...state,
custom_properties: {
...state.custom_properties,
channel_sort_order: value || '',
},
};
}
return state;
})
);
}}
data={[
{ value: '', label: 'Provider Order (Default)' },
{ value: 'name', label: 'Name' },
{ value: 'tvg_id', label: 'TVG ID' },
{ value: 'updated_at', label: 'Updated At' },
]}
clearable
searchable
size="xs"
/>
{/* Add reverse sort checkbox when sort order is selected (including default) */}
{group.custom_properties?.channel_sort_order !== undefined && (
<Flex align="center" gap="xs" mt="xs">
<Checkbox
label="Reverse Sort Order"
checked={group.custom_properties?.channel_sort_reverse || false}
onChange={(event) => {
setGroupStates(
groupStates.map((state) => {
if (state.channel_group === group.channel_group) {
return {
...state,
custom_properties: {
...state.custom_properties,
channel_sort_reverse: event.target.checked,
},
};
}
return state;
})
);
}}
size="xs"
/>
</Flex>
)}
</>
)}
{/* Show profile selection only if profile_assignment is selected */}