process groups to allow filtering before any stream ingestion, do this in background for better experience

This commit is contained in:
dekzter 2025-04-06 13:11:28 -04:00
parent 702c85e01b
commit e185fbcda6
5 changed files with 49 additions and 11 deletions

View file

@ -2,9 +2,9 @@
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from .models import M3UAccount
from .tasks import refresh_m3u_groups
from .tasks import refresh_single_m3u_account, refresh_m3u_groups
from django_celery_beat.models import PeriodicTask, IntervalSchedule
import json, gc
import json
@receiver(post_save, sender=M3UAccount)
def refresh_account_on_save(sender, instance, created, **kwargs):
@ -14,11 +14,7 @@ def refresh_account_on_save(sender, instance, created, **kwargs):
if it is active or newly created.
"""
if created:
extinf_data, groups = refresh_m3u_groups(instance.id)
# Aggresive GC since we pulled in the whole file
del extinf_data, groups
gc.collect()
refresh_m3u_groups.delay(instance.id)
@receiver(post_save, sender=M3UAccount)
def create_or_update_refresh_task(sender, instance, **kwargs):

View file

@ -273,7 +273,8 @@ def cleanup_streams(account_id):
logger.info(f"Cleanup complete")
def refresh_m3u_groups(account_id, use_cache=False):
@shared_task
def refresh_m3u_groups(account_id, use_cache=False, full_refresh=False):
if not acquire_task_lock('refresh_m3u_account_groups', account_id):
return f"Task already running for account_id={account_id}.", None
@ -311,6 +312,16 @@ def refresh_m3u_groups(account_id, use_cache=False):
release_task_lock('refresh_m3u_account_groups', account_id)
if not full_refresh:
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
'updates',
{
'type': 'update',
"data": {"success": True, "type": "m3u_group_refresh", "account": account_id}
}
)
return extinf_data, groups
@shared_task
@ -346,7 +357,7 @@ def refresh_single_m3u_account(account_id):
if not extinf_data:
try:
extinf_data, groups = refresh_m3u_groups(account_id)
extinf_data, groups = refresh_m3u_groups(account_id, full_refresh=True)
if not extinf_data or not groups:
release_task_lock('refresh_single_m3u_account', account_id)
return "Failed to update m3u account, task may already be running"

View file

@ -57,6 +57,17 @@ export const WebsocketProvider = ({ children }) => {
socket.onmessage = async (event) => {
event = JSON.parse(event.data);
switch (event.data.type) {
case 'm3u_group_refresh':
fetchChannelGroups();
fetchPlaylists();
notifications.show({
title: 'Group processing finished!',
message: 'Refresh M3U or filter out groups to pull in streams.',
color: 'green.5',
});
break;
case 'm3u_refresh':
if (event.data.success) {
fetchStreams();

View file

@ -23,6 +23,7 @@ import {
import M3UGroupFilter from './M3UGroupFilter';
import useChannelsStore from '../../store/channels';
import usePlaylistsStore from '../../store/playlists';
import { notifications } from '@mantine/notifications';
const M3U = ({ playlist = null, isOpen, onClose, playlistCreated = false }) => {
const theme = useMantineTheme();
@ -71,10 +72,15 @@ const M3U = ({ playlist = null, isOpen, onClose, playlistCreated = false }) => {
uploaded_file: file,
});
await fetchChannelGroups();
notifications.show({
title: 'Fetching M3U Groups',
message: 'Filter out groups or refresh M3U once complete.',
// color: 'green.5',
});
// Don't prompt for group filters, but keeping this here
// in case we want to revive it
newPlaylist = null;
}
resetForm();

View file

@ -26,6 +26,7 @@ import {
ScanEye,
EllipsisVertical,
CircleEllipsis,
CopyMinus,
} from 'lucide-react';
import ghostImage from '../../images/ghost.svg';
import {
@ -540,6 +541,9 @@ const ChannelsTable = ({}) => {
};
const deleteChannel = async (id) => {
if (channelsPageSelection.length > 0) {
return deleteChannels();
}
await API.deleteChannel(id);
};
@ -858,8 +862,18 @@ const ChannelsTable = ({}) => {
variant="transparent"
color={theme.tailwind.red[6]}
onClick={() => deleteChannel(row.original.id)}
disabled={
channelsPageSelection.length > 0 &&
!channelsPageSelection
.map((row) => row.id)
.includes(row.original.id)
}
>
<SquareMinus size="18" />
{channelsPageSelection.length === 0 ? (
<SquareMinus size="18" />
) : (
<CopyMinus size="18" />
)}
</ActionIcon>
</Tooltip>