mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-01-24 03:05:13 +00:00
Merge branch 'main' of https://github.com/Dispatcharr/Dispatcharr
This commit is contained in:
commit
9c7bdfd2e9
10 changed files with 45 additions and 28 deletions
|
|
@ -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'),
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
]
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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'),
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue