Add priority for providers so VOD's can be auto selected based on the priority.

This commit is contained in:
SergeantPanda 2025-08-20 17:38:21 -05:00
parent fa2b3fbe3e
commit 24f876d09f
8 changed files with 72 additions and 14 deletions

View file

@ -18,6 +18,7 @@ class M3UAccountAdmin(admin.ModelAdmin):
"server_url",
"server_group",
"max_streams",
"priority",
"is_active",
"user_agent_display",
"uploaded_file_link",

View file

@ -0,0 +1,18 @@
# Generated by Django 5.2.4 on 2025-08-20 22:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('m3u', '0015_alter_m3ufilter_options_m3ufilter_custom_properties'),
]
operations = [
migrations.AddField(
model_name='m3uaccount',
name='priority',
field=models.PositiveIntegerField(default=0, help_text='Priority for VOD provider selection (higher numbers = higher priority). Used when multiple providers offer the same content.'),
),
]

View file

@ -94,6 +94,10 @@ class M3UAccount(models.Model):
default=7,
help_text="Number of days after which a stream will be removed if not seen in the M3U source.",
)
priority = models.PositiveIntegerField(
default=0,
help_text="Priority for VOD provider selection (higher numbers = higher priority). Used when multiple providers offer the same content.",
)
def __str__(self):
return self.name

View file

@ -1,5 +1,5 @@
from core.utils import validate_flexible_url
from rest_framework import serializers
from rest_framework import serializers, status
from rest_framework.response import Response
from .models import M3UAccount, M3UFilter, ServerGroup, M3UAccountProfile
from core.models import UserAgent
@ -113,6 +113,7 @@ class M3UAccountSerializer(serializers.ModelSerializer):
"username",
"password",
"stale_stream_days",
"priority",
"status",
"last_message",
"enable_vod",

View file

@ -1077,10 +1077,10 @@ def xc_get_vod_streams(request, user, category_id=None):
movies = Movie.objects.filter(**filters).select_related('logo').distinct()
for movie in movies:
# Get the first relation for this movie (for metadata like container_extension)
# Get the highest priority relation for this movie (for metadata like container_extension)
relation = movie.m3u_relations.filter(
m3u_account__is_active=True
).first()
).select_related('m3u_account').order_by('-m3u_account__priority', 'id').first()
if relation:
relation_custom = relation.custom_properties or {}
@ -1282,9 +1282,11 @@ def xc_get_series_info(request, user, series_id):
if season_num not in seasons:
seasons[season_num] = []
# Try to get the first related M3UEpisodeRelation for this episode (for video/audio/bitrate)
# Try to get the highest priority related M3UEpisodeRelation for this episode (for video/audio/bitrate)
from apps.vod.models import M3UEpisodeRelation
first_relation = M3UEpisodeRelation.objects.filter(episode=episode).order_by('id').first()
first_relation = M3UEpisodeRelation.objects.filter(
episode=episode
).select_related('m3u_account').order_by('-m3u_account__priority', 'id').first()
video = audio = bitrate = None
if first_relation and first_relation.custom_properties:
info = first_relation.custom_properties.get('info')

View file

@ -345,16 +345,28 @@ class VODStreamView(View):
content_obj = get_object_or_404(Movie, uuid=content_id)
logger.info(f"[CONTENT-FOUND] Movie: {content_obj.name} (ID: {content_obj.id})")
# Get the first active relation
relation = content_obj.m3u_relations.filter(m3u_account__is_active=True).first()
# Get the highest priority active relation
relation = content_obj.m3u_relations.filter(
m3u_account__is_active=True
).select_related('m3u_account').order_by('-m3u_account__priority', 'id').first()
if relation:
logger.info(f"[PROVIDER-SELECTED] Using provider: {relation.m3u_account.name} (priority: {relation.m3u_account.priority})")
return content_obj, relation
elif content_type == 'episode':
content_obj = get_object_or_404(Episode, uuid=content_id)
logger.info(f"[CONTENT-FOUND] Episode: {content_obj.name} (ID: {content_obj.id}, Series: {content_obj.series.name})")
# Get the first active relation
relation = content_obj.m3u_relations.filter(m3u_account__is_active=True).first()
# Get the highest priority active relation
relation = content_obj.m3u_relations.filter(
m3u_account__is_active=True
).select_related('m3u_account').order_by('-m3u_account__priority', 'id').first()
if relation:
logger.info(f"[PROVIDER-SELECTED] Using provider: {relation.m3u_account.name} (priority: {relation.m3u_account.priority})")
return content_obj, relation
elif content_type == 'series':
@ -367,7 +379,14 @@ class VODStreamView(View):
return None, None
logger.info(f"[CONTENT-FOUND] First episode: {episode.name} (ID: {episode.id})")
relation = episode.m3u_relations.filter(m3u_account__is_active=True).first()
# Get the highest priority active relation
relation = episode.m3u_relations.filter(
m3u_account__is_active=True
).select_related('m3u_account').order_by('-m3u_account__priority', 'id').first()
if relation:
logger.info(f"[PROVIDER-SELECTED] Using provider: {relation.m3u_account.name} (priority: {relation.m3u_account.priority})")
return episode, relation
else:
logger.error(f"[CONTENT-ERROR] Invalid content type: {content_type}")

View file

@ -108,11 +108,11 @@ class MovieViewSet(viewsets.ReadOnlyModelViewSet):
"""Get detailed movie information from the original provider, throttled to 24h."""
movie = self.get_object()
# Get the first active relation
# Get the highest priority active relation
relation = M3UMovieRelation.objects.filter(
movie=movie,
m3u_account__is_active=True
).select_related('m3u_account').first()
).select_related('m3u_account').order_by('-m3u_account__priority', 'id').first()
if not relation:
return Response(
@ -314,11 +314,11 @@ class SeriesViewSet(viewsets.ReadOnlyModelViewSet):
series = self.get_object()
logger.debug(f"Retrieved series: {series.name} (ID: {series.id})")
# Get the first active relation
# Get the highest priority active relation
relation = M3USeriesRelation.objects.filter(
series=series,
m3u_account__is_active=True
).select_related('m3u_account').first()
).select_related('m3u_account').order_by('-m3u_account__priority', 'id').first()
if not relation:
return Response(

View file

@ -64,6 +64,7 @@ const M3U = ({
username: '',
password: '',
stale_stream_days: 7,
priority: 0,
enable_vod: false,
},
@ -93,6 +94,9 @@ const M3U = ({
m3uAccount.stale_stream_days !== null
? m3uAccount.stale_stream_days
: 7,
priority: m3uAccount.priority !== undefined && m3uAccount.priority !== null
? m3uAccount.priority
: 0,
enable_vod: m3uAccount.enable_vod || false,
});
@ -366,6 +370,15 @@ const M3U = ({
{...form.getInputProps('stale_stream_days')}
/>
<NumberInput
min={0}
max={999}
label="VOD Priority"
description="Priority for VOD provider selection (higher numbers = higher priority). Used when multiple providers offer the same content."
{...form.getInputProps('priority')}
key={form.key('priority')}
/>
<Checkbox
label="Is Active"
description="Enable or disable this M3U account"