diff --git a/apps/m3u/tasks.py b/apps/m3u/tasks.py index 0061cde6..fd1a5f8d 100644 --- a/apps/m3u/tasks.py +++ b/apps/m3u/tasks.py @@ -18,7 +18,7 @@ from channels.layers import get_channel_layer from django.utils import timezone import time import json -from core.utils import RedisClient, acquire_task_lock, release_task_lock +from core.utils import RedisClient, acquire_task_lock, release_task_lock, natural_sort_key from core.models import CoreSettings, UserAgent from asgiref.sync import async_to_sync from core.xtream_codes import Client as XCClient @@ -933,7 +933,9 @@ def sync_auto_channels(account_id, scan_start_time=None): # --- APPLY CHANNEL SORT ORDER --- if channel_sort_order and channel_sort_order != '': if channel_sort_order == 'name': - current_streams = current_streams.order_by('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)) elif channel_sort_order == 'tvg_id': current_streams = current_streams.order_by('tvg_id') elif channel_sort_order == 'updated_at': diff --git a/core/utils.py b/core/utils.py index 9951ce26..932af979 100644 --- a/core/utils.py +++ b/core/utils.py @@ -3,6 +3,7 @@ import logging import time import os import threading +import re from django.conf import settings from redis.exceptions import ConnectionError, TimeoutError from django.core.cache import cache @@ -15,6 +16,29 @@ logger = logging.getLogger(__name__) # Import the command detector from .command_utils import is_management_command +def natural_sort_key(text): + """ + Convert a string into a list of string and number chunks for natural sorting. + "PPV 10" becomes ['PPV ', 10] so it sorts correctly with "PPV 2". + + This function enables natural/alphanumeric sorting where numbers within strings + are treated as actual numbers rather than strings. + + Args: + text (str): The text to convert for sorting + + Returns: + list: A list of strings and integers for proper sorting + + Example: + >>> sorted(['PPV 1', 'PPV 10', 'PPV 2'], key=natural_sort_key) + ['PPV 1', 'PPV 2', 'PPV 10'] + """ + def convert(chunk): + return int(chunk) if chunk.isdigit() else chunk.lower() + + return [convert(c) for c in re.split('([0-9]+)', text)] + class RedisClient: _client = None _pubsub_client = None