diff --git a/apps/epg/models.py b/apps/epg/models.py index 09986bfe..f026c558 100644 --- a/apps/epg/models.py +++ b/apps/epg/models.py @@ -1,6 +1,7 @@ from django.db import models from django.utils import timezone from django_celery_beat.models import PeriodicTask +from django.conf import settings class EPGSource(models.Model): SOURCE_TYPE_CHOICES = [ @@ -29,6 +30,15 @@ class EPGSource(models.Model): def __str__(self): return self.name + def get_cache_file(self): + # Decide on file extension + file_ext = ".gz" if self.url.lower().endswith('.gz') else ".xml" + filename = f"{self.id}{file_ext}" + + # Build full path in MEDIA_ROOT/cached_epg + cache_dir = os.path.join(settings.MEDIA_ROOT, "cached_epg") + cache = os.path.join(cache_dir, filename) + class EPGData(models.Model): # Removed the Channel foreign key. We now just store the original tvg_id # and a name (which might simply be the tvg_id if no real channel exists). diff --git a/apps/epg/tasks.py b/apps/epg/tasks.py index 2b6852ac..a28db282 100644 --- a/apps/epg/tasks.py +++ b/apps/epg/tasks.py @@ -68,23 +68,12 @@ def fetch_xmltv(source): response.raise_for_status() logger.debug("XMLTV data fetched successfully.") - # Decide on file extension - file_ext = ".gz" if source.url.lower().endswith('.gz') else ".xml" - filename = f"{source.name}_{uuid.uuid4().hex[:8]}{file_ext}" - - # Build full path in MEDIA_ROOT/cached_epg - epg_dir = os.path.join(settings.MEDIA_ROOT, "cached_epg") - os.makedirs(epg_dir, exist_ok=True) - file_path = os.path.join(epg_dir, filename) + cache_file = source.get_cache_file() # Save raw data - with open(file_path, 'wb') as f: + with open(cache_file, 'wb') as f: f.write(response.content) - logger.info(f"Cached EPG file saved to {file_path}") - - # Save the file_path on the EPGSource instance so it can be retrieved later. - source.file_path = file_path - source.save(update_fields=['file_path']) + logger.info(f"Cached EPG file saved to {cache_file}") except Exception as e: logger.error(f"Error fetching XMLTV from {source.name}: {e}", exc_info=True) @@ -92,6 +81,9 @@ def fetch_xmltv(source): def parse_channels_only(source): file_path = source.file_path + if not file_path: + file_path = source.get_cache_file() + logger.info(f"Parsing channels from EPG file: {file_path}") existing_epgs = {e.tvg_id: e for e in EPGData.objects.filter(epg_source=source)} @@ -165,13 +157,19 @@ def parse_programs_for_tvg_id(epg_id): # First, remove all existing programs ProgramData.objects.filter(epg=epg).delete() + file_path = epg_source.file_path + if not file_path: + file_path = epg_source.get_cache_file() + if not os.exists(file_path): + fetch_xmltv(epg_source) + # Read entire file (decompress if .gz) - if epg_source.file_path.endswith('.gz'): - with open(epg_source.file_path, 'rb') as gz_file: + if file_path.endswith('.gz'): + with open(file_path, 'rb') as gz_file: decompressed = gzip.decompress(gz_file.read()) xml_data = decompressed.decode('utf-8') else: - with open(epg_source.file_path, 'r', encoding='utf-8') as xml_file: + with open(file_path, 'r', encoding='utf-8') as xml_file: xml_data = xml_file.read() root = ET.fromstring(xml_data)