This commit is contained in:
SergeantPanda 2025-03-23 17:10:27 -05:00
commit 9c7bdfd2e9
10 changed files with 45 additions and 28 deletions

View file

@ -1,12 +1,13 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .api_views import EPGSourceViewSet, ProgramViewSet, EPGGridAPIView, EPGImportAPIView
from .api_views import EPGSourceViewSet, ProgramViewSet, EPGGridAPIView, EPGImportAPIView, EPGDataViewSet
app_name = 'epg'
router = DefaultRouter()
router.register(r'sources', EPGSourceViewSet, basename='epg-source')
router.register(r'programs', ProgramViewSet, basename='program')
router.register(r'epgdata', EPGDataViewSet, basename='epgdata')
urlpatterns = [
path('grid/', EPGGridAPIView.as_view(), name='epg_grid'),

View file

@ -7,8 +7,8 @@ from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from django.utils import timezone
from datetime import timedelta
from .models import EPGSource, ProgramData # Using ProgramData
from .serializers import ProgramDataSerializer, EPGSourceSerializer # Updated serializer
from .models import EPGSource, ProgramData, EPGData # Added ProgramData
from .serializers import ProgramDataSerializer, EPGSourceSerializer, EPGDataSerializer # Updated serializer
from .tasks import refresh_epg_data
logger = logging.getLogger(__name__)
@ -78,3 +78,16 @@ class EPGImportAPIView(APIView):
refresh_epg_data.delay() # Trigger Celery task
logger.info("EPGImportAPIView: Task dispatched to refresh EPG data.")
return Response({'success': True, 'message': 'EPG data import initiated.'}, status=status.HTTP_202_ACCEPTED)
# ─────────────────────────────
# 5) EPG Data View
# ─────────────────────────────
class EPGDataViewSet(viewsets.ReadOnlyModelViewSet):
"""
API endpoint that allows EPGData objects to be viewed.
"""
queryset = EPGData.objects.all()
serializer_class = EPGDataSerializer
permission_classes = [IsAuthenticated]

View file

@ -13,12 +13,14 @@ class ProgramDataSerializer(serializers.ModelSerializer):
fields = ['id', 'start_time', 'end_time', 'title', 'sub_title', 'description', 'tvg_id']
class EPGDataSerializer(serializers.ModelSerializer):
programs = ProgramDataSerializer(many=True, read_only=True)
channel = serializers.SerializerMethodField()
def get_channel(self, obj):
return {"id": obj.channel.id, "name": obj.channel.name} if obj.channel else None
"""
Only returns the tvg_id and the 'name' field from EPGData.
We assume 'name' is effectively the channel name.
"""
class Meta:
model = EPGData
fields = ['id', 'channel', 'name', 'programs']
fields = [
'id',
'tvg_id',
'name',
]

View file

@ -12,6 +12,8 @@ from celery import shared_task
from django.conf import settings
from django.db import transaction
from django.utils import timezone
from apps.channels.models import Channel
from .models import EPGSource, EPGData, ProgramData
@ -60,9 +62,11 @@ def fetch_xmltv(source):
source.file_path = file_path
source.save(update_fields=['file_path'])
# If you store the path on EPGSource, do so here:
# source.file_path = file_path
# source.save(update_fields=['file_path'])
epg_entries = EPGData.objects.exclude(tvg_id__isnull=True).exclude(tvg_id__exact='')
for epg in epg_entries:
if Channel.objects.filter(tvg_id=epg.tvg_id).exists():
logger.info(f"Refreshing program data for tvg_id: {epg.tvg_id}")
parse_programs_for_tvg_id(file_path, epg.tvg_id)
# Now parse <channel> blocks only
parse_channels_only(file_path)

View file

@ -39,7 +39,7 @@ class DiscoverAPIView(APIView):
responses={200: openapi.Response("HDHR Discovery JSON")}
)
def get(self, request):
base_url = request.build_absolute_uri('/').rstrip('/')
base_url = request.build_absolute_uri('/hdhr/').rstrip('/')
device = HDHRDevice.objects.first()
if not device:
@ -115,7 +115,7 @@ class HDHRDeviceXMLAPIView(APIView):
responses={200: openapi.Response("HDHR Device XML")}
)
def get(self, request):
base_url = request.build_absolute_uri('/').rstrip('/')
base_url = request.build_absolute_uri('/hdhr/').rstrip('/')
xml_response = f"""<?xml version="1.0" encoding="utf-8"?>
<root>

View file

@ -39,7 +39,7 @@ class DiscoverAPIView(APIView):
responses={200: openapi.Response("HDHR Discovery JSON")}
)
def get(self, request):
base_url = request.build_absolute_uri('/').rstrip('/')
base_url = request.build_absolute_uri('/hdhr/').rstrip('/')
device = HDHRDevice.objects.first()
if not device:
@ -115,7 +115,7 @@ class HDHRDeviceXMLAPIView(APIView):
responses={200: openapi.Response("HDHR Device XML")}
)
def get(self, request):
base_url = request.build_absolute_uri('/').rstrip('/')
base_url = request.build_absolute_uri('/hdhr/').rstrip('/')
xml_response = f"""<?xml version="1.0" encoding="utf-8"?>
<root>

View file

@ -117,7 +117,7 @@ def refresh_single_m3u_account(account_id):
return err_msg
headers = {"User-Agent": account.user_agent.user_agent}
response = requests.get(account.server_url, timeout=60, headers=headers)
response = requests.get(account.server_url, headers=headers)
response.raise_for_status()
lines = response.text.splitlines()
elif account.uploaded_file:

View file

@ -7,7 +7,6 @@ from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
from .routing import websocket_urlpatterns
from apps.hdhr.api_views import HDHRDeviceViewSet, DiscoverAPIView, LineupAPIView, LineupStatusAPIView, HDHRDeviceXMLAPIView, hdhr_dashboard_view
# Define schema_view for Swagger
@ -45,13 +44,6 @@ urlpatterns = [
path('proxy/', include(('apps.proxy.urls', 'proxy'), namespace='proxy')),
path('proxy', RedirectView.as_view(url='/proxy/', permanent=True)),
# HDHR API
path('discover.json', DiscoverAPIView.as_view(), name='discover'),
path('lineup.json', LineupAPIView.as_view(), name='lineup'),
path('lineup_status.json', LineupStatusAPIView.as_view(), name='lineup_status'),
path('device.xml', HDHRDeviceXMLAPIView.as_view(), name='device_xml'),
# Swagger UI
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),

View file

@ -22,6 +22,11 @@ server {
return 301 /login;
}
# Route HDHR request to Django
location /hdhr {
proxy_pass http://127.0.0.1:5656;
}
# Serve FFmpeg streams efficiently
location /output/stream/ {
proxy_pass http://127.0.0.1:5656;

View file

@ -175,7 +175,7 @@ const ChannelStreams = ({ channel, isExpanded }) => {
const m3uUrl = `${window.location.protocol}//${window.location.host}/output/m3u`;
const epgUrl = `${window.location.protocol}//${window.location.host}/output/epg`;
const hdhrUrl = `${window.location.protocol}//${window.location.host}/output/hdhr`;
const hdhrUrl = `${window.location.protocol}//${window.location.host}/hdhr/`;
const ChannelsTable = ({}) => {
const [channel, setChannel] = useState(null);
@ -441,7 +441,7 @@ const ChannelsTable = ({}) => {
};
const copyHDHRUrl = () => {
handleCopy(
`${window.location.protocol}//${window.location.host}/output/hdhr`,
`${window.location.protocol}//${window.location.host}/hdhr/`,
hdhrUrlRef
);
};