mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-07-19 01:25:06 +00:00
261 lines
9 KiB
Python
261 lines
9 KiB
Python
from rest_framework import viewsets, status
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
from apps.accounts.permissions import (
|
|
Authenticated,
|
|
permission_classes_by_action,
|
|
permission_classes_by_method,
|
|
)
|
|
from drf_yasg.utils import swagger_auto_schema
|
|
from drf_yasg import openapi
|
|
from django.shortcuts import get_object_or_404
|
|
from django.http import JsonResponse
|
|
from django.core.cache import cache
|
|
import os
|
|
from rest_framework.decorators import action
|
|
from django.conf import settings
|
|
from .tasks import refresh_m3u_groups
|
|
|
|
# Import all models, including UserAgent.
|
|
from .models import M3UAccount, M3UFilter, ServerGroup, M3UAccountProfile
|
|
from core.models import UserAgent
|
|
from apps.channels.models import ChannelGroupM3UAccount
|
|
from core.serializers import UserAgentSerializer
|
|
|
|
# Import all serializers, including the UserAgentSerializer.
|
|
from .serializers import (
|
|
M3UAccountSerializer,
|
|
M3UFilterSerializer,
|
|
ServerGroupSerializer,
|
|
M3UAccountProfileSerializer,
|
|
)
|
|
|
|
from .tasks import refresh_single_m3u_account, refresh_m3u_accounts
|
|
from django.core.files.storage import default_storage
|
|
from django.core.files.base import ContentFile
|
|
|
|
|
|
class M3UAccountViewSet(viewsets.ModelViewSet):
|
|
"""Handles CRUD operations for M3U accounts"""
|
|
|
|
queryset = M3UAccount.objects.prefetch_related("channel_group")
|
|
serializer_class = M3UAccountSerializer
|
|
|
|
def get_permissions(self):
|
|
try:
|
|
return [perm() for perm in permission_classes_by_action[self.action]]
|
|
except KeyError:
|
|
return [Authenticated()]
|
|
|
|
def create(self, request, *args, **kwargs):
|
|
# Handle file upload first, if any
|
|
file_path = None
|
|
if "file" in request.FILES:
|
|
file = request.FILES["file"]
|
|
file_name = file.name
|
|
file_path = os.path.join("/data/uploads/m3us", file_name)
|
|
|
|
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
|
with open(file_path, "wb+") as destination:
|
|
for chunk in file.chunks():
|
|
destination.write(chunk)
|
|
|
|
# Add file_path to the request data so it's available during creation
|
|
request.data._mutable = True # Allow modification of the request data
|
|
request.data["file_path"] = (
|
|
file_path # Include the file path if a file was uploaded
|
|
)
|
|
|
|
# Handle the user_agent field - convert "null" string to None
|
|
if "user_agent" in request.data and request.data["user_agent"] == "null":
|
|
request.data["user_agent"] = None
|
|
|
|
# Handle server_url appropriately
|
|
if "server_url" in request.data and not request.data["server_url"]:
|
|
request.data.pop("server_url")
|
|
|
|
request.data._mutable = False # Make the request data immutable again
|
|
|
|
# Now call super().create() to create the instance
|
|
response = super().create(request, *args, **kwargs)
|
|
|
|
print(response.data.get("account_type"))
|
|
if response.data.get("account_type") == M3UAccount.Types.XC:
|
|
refresh_m3u_groups(response.data.get("id"))
|
|
|
|
# After the instance is created, return the response
|
|
return response
|
|
|
|
def update(self, request, *args, **kwargs):
|
|
instance = self.get_object()
|
|
|
|
# Handle file upload first, if any
|
|
file_path = None
|
|
if "file" in request.FILES:
|
|
file = request.FILES["file"]
|
|
file_name = file.name
|
|
file_path = os.path.join("/data/uploads/m3us", file_name)
|
|
|
|
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
|
with open(file_path, "wb+") as destination:
|
|
for chunk in file.chunks():
|
|
destination.write(chunk)
|
|
|
|
# Add file_path to the request data so it's available during creation
|
|
request.data._mutable = True # Allow modification of the request data
|
|
request.data["file_path"] = (
|
|
file_path # Include the file path if a file was uploaded
|
|
)
|
|
|
|
# Handle the user_agent field - convert "null" string to None
|
|
if "user_agent" in request.data and request.data["user_agent"] == "null":
|
|
request.data["user_agent"] = None
|
|
|
|
# Handle server_url appropriately
|
|
if "server_url" in request.data and not request.data["server_url"]:
|
|
request.data.pop("server_url")
|
|
|
|
request.data._mutable = False # Make the request data immutable again
|
|
|
|
if instance.file_path and os.path.exists(instance.file_path):
|
|
os.remove(instance.file_path)
|
|
|
|
# Now call super().update() to update the instance
|
|
response = super().update(request, *args, **kwargs)
|
|
|
|
# After the instance is updated, return the response
|
|
return response
|
|
|
|
def partial_update(self, request, *args, **kwargs):
|
|
"""Handle partial updates with special logic for is_active field"""
|
|
instance = self.get_object()
|
|
|
|
# Check if we're toggling is_active
|
|
if (
|
|
"is_active" in request.data
|
|
and instance.is_active != request.data["is_active"]
|
|
):
|
|
# Set appropriate status based on new is_active value
|
|
if request.data["is_active"]:
|
|
request.data["status"] = M3UAccount.Status.IDLE
|
|
else:
|
|
request.data["status"] = M3UAccount.Status.DISABLED
|
|
|
|
# Continue with regular partial update
|
|
return super().partial_update(request, *args, **kwargs)
|
|
|
|
|
|
class M3UFilterViewSet(viewsets.ModelViewSet):
|
|
"""Handles CRUD operations for M3U filters"""
|
|
|
|
queryset = M3UFilter.objects.all()
|
|
serializer_class = M3UFilterSerializer
|
|
|
|
def get_permissions(self):
|
|
try:
|
|
return [perm() for perm in permission_classes_by_action[self.action]]
|
|
except KeyError:
|
|
return [Authenticated()]
|
|
|
|
|
|
class ServerGroupViewSet(viewsets.ModelViewSet):
|
|
"""Handles CRUD operations for Server Groups"""
|
|
|
|
queryset = ServerGroup.objects.all()
|
|
serializer_class = ServerGroupSerializer
|
|
|
|
def get_permissions(self):
|
|
try:
|
|
return [perm() for perm in permission_classes_by_action[self.action]]
|
|
except KeyError:
|
|
return [Authenticated()]
|
|
|
|
|
|
class RefreshM3UAPIView(APIView):
|
|
"""Triggers refresh for all active M3U accounts"""
|
|
|
|
def get_permissions(self):
|
|
try:
|
|
return [
|
|
perm() for perm in permission_classes_by_method[self.request.method]
|
|
]
|
|
except KeyError:
|
|
return [Authenticated()]
|
|
|
|
@swagger_auto_schema(
|
|
operation_description="Triggers a refresh of all active M3U accounts",
|
|
responses={202: "M3U refresh initiated"},
|
|
)
|
|
def post(self, request, format=None):
|
|
refresh_m3u_accounts.delay()
|
|
return Response(
|
|
{"success": True, "message": "M3U refresh initiated."},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
|
|
|
|
class RefreshSingleM3UAPIView(APIView):
|
|
"""Triggers refresh for a single M3U account"""
|
|
|
|
def get_permissions(self):
|
|
try:
|
|
return [
|
|
perm() for perm in permission_classes_by_method[self.request.method]
|
|
]
|
|
except KeyError:
|
|
return [Authenticated()]
|
|
|
|
@swagger_auto_schema(
|
|
operation_description="Triggers a refresh of a single M3U account",
|
|
responses={202: "M3U account refresh initiated"},
|
|
)
|
|
def post(self, request, account_id, format=None):
|
|
refresh_single_m3u_account.delay(account_id)
|
|
return Response(
|
|
{
|
|
"success": True,
|
|
"message": f"M3U account {account_id} refresh initiated.",
|
|
},
|
|
status=status.HTTP_202_ACCEPTED,
|
|
)
|
|
|
|
|
|
class UserAgentViewSet(viewsets.ModelViewSet):
|
|
"""Handles CRUD operations for User Agents"""
|
|
|
|
queryset = UserAgent.objects.all()
|
|
serializer_class = UserAgentSerializer
|
|
|
|
def get_permissions(self):
|
|
try:
|
|
return [perm() for perm in permission_classes_by_action[self.action]]
|
|
except KeyError:
|
|
return [Authenticated()]
|
|
|
|
|
|
class M3UAccountProfileViewSet(viewsets.ModelViewSet):
|
|
queryset = M3UAccountProfile.objects.all()
|
|
serializer_class = M3UAccountProfileSerializer
|
|
|
|
def get_permissions(self):
|
|
try:
|
|
return [perm() for perm in permission_classes_by_action[self.action]]
|
|
except KeyError:
|
|
return [Authenticated()]
|
|
|
|
def get_queryset(self):
|
|
m3u_account_id = self.kwargs["account_id"]
|
|
return M3UAccountProfile.objects.filter(m3u_account_id=m3u_account_id)
|
|
|
|
def perform_create(self, serializer):
|
|
# Get the account ID from the URL
|
|
account_id = self.kwargs["account_id"]
|
|
|
|
# Get the M3UAccount instance for the account_id
|
|
m3u_account = M3UAccount.objects.get(id=account_id)
|
|
|
|
# Save the 'm3u_account' in the serializer context
|
|
serializer.context["m3u_account"] = m3u_account
|
|
|
|
# Perform the actual save
|
|
serializer.save(m3u_account_id=m3u_account)
|