diff --git a/apps/vod/tasks.py b/apps/vod/tasks.py index 6cd793c2..1484294b 100644 --- a/apps/vod/tasks.py +++ b/apps/vod/tasks.py @@ -20,6 +20,9 @@ logger = logging.getLogger(__name__) @shared_task def refresh_vod_content(account_id): """Refresh VOD content for an M3U account with batch processing for improved performance""" + # Import here to avoid circular import + from apps.m3u.tasks import send_m3u_update + try: account = M3UAccount.objects.get(id=account_id, is_active=True) @@ -30,6 +33,9 @@ def refresh_vod_content(account_id): logger.info(f"Starting batch VOD refresh for account {account.name}") start_time = timezone.now() + # Send start notification + send_m3u_update(account_id, "vod_refresh", 0, status="processing") + with XtreamCodesClient( account.server_url, account.username, @@ -55,10 +61,20 @@ def refresh_vod_content(account_id): duration = (end_time - start_time).total_seconds() logger.info(f"Batch VOD refresh completed for account {account.name} in {duration:.2f} seconds") + + # Send completion notification + send_m3u_update(account_id, "vod_refresh", 100, status="success", + message=f"VOD refresh completed in {duration:.2f} seconds") + return f"Batch VOD refresh completed for account {account.name} in {duration:.2f} seconds" except Exception as e: logger.error(f"Error refreshing VOD for account {account_id}: {str(e)}") + + # Send error notification + send_m3u_update(account_id, "vod_refresh", 100, status="error", + message=f"VOD refresh failed: {str(e)}") + return f"VOD refresh failed: {str(e)}" def refresh_categories(account_id, client=None): diff --git a/frontend/src/components/ConfirmationDialog.jsx b/frontend/src/components/ConfirmationDialog.jsx index 1cfbe84d..73805513 100644 --- a/frontend/src/components/ConfirmationDialog.jsx +++ b/frontend/src/components/ConfirmationDialog.jsx @@ -30,7 +30,7 @@ const ConfirmationDialog = ({ size = 'md', zIndex = 1000, showDeleteFileOption = false, - deleteFileLabel = "Also delete files from disk", + deleteFileLabel = 'Also delete files from disk', }) => { const suppressWarning = useWarningsStore((s) => s.suppressWarning); const isWarningSuppressed = useWarningsStore((s) => s.isWarningSuppressed); diff --git a/frontend/src/components/M3URefreshNotification.jsx b/frontend/src/components/M3URefreshNotification.jsx index 4420f13e..b9819b4e 100644 --- a/frontend/src/components/M3URefreshNotification.jsx +++ b/frontend/src/components/M3URefreshNotification.jsx @@ -5,6 +5,7 @@ import { notifications } from '@mantine/notifications'; import useStreamsStore from '../store/streams'; import useChannelsStore from '../store/channels'; import useEPGsStore from '../store/epgs'; +import useVODStore from '../store/useVODStore'; import { Stack, Button, Group } from '@mantine/core'; import API from '../api'; import { useNavigate } from 'react-router-dom'; @@ -18,6 +19,7 @@ export default function M3URefreshNotification() { const fetchChannels = useChannelsStore((s) => s.fetchChannels); const fetchPlaylists = usePlaylistsStore((s) => s.fetchPlaylists); const fetchEPGData = useEPGsStore((s) => s.fetchEPGData); + const fetchCategories = useVODStore((s) => s.fetchCategories); const [notificationStatus, setNotificationStatus] = useState({}); const navigate = useNavigate(); @@ -126,7 +128,7 @@ export default function M3URefreshNotification() { case 'processing_groups': message = 'Group parsing'; break; - + case 'vod_refresh': message = 'VOD content refresh'; break; @@ -148,8 +150,9 @@ export default function M3URefreshNotification() { fetchEPGData(); fetchPlaylists(); } else if (data.action == 'vod_refresh') { - // VOD refresh completed, could trigger additional UI updates if needed + // VOD refresh completed, trigger VOD categories refresh fetchPlaylists(); // Refresh playlist data to show updated VOD info + fetchCategories(); // Refresh VOD categories to make them visible } } diff --git a/frontend/src/components/forms/M3U.jsx b/frontend/src/components/forms/M3U.jsx index ff25ed92..8bd245b6 100644 --- a/frontend/src/components/forms/M3U.jsx +++ b/frontend/src/components/forms/M3U.jsx @@ -27,6 +27,7 @@ import usePlaylistsStore from '../../store/playlists'; import { notifications } from '@mantine/notifications'; import { isNotEmpty, useForm } from '@mantine/form'; import useEPGsStore from '../../store/epgs'; +import useVODStore from '../../store/useVODStore'; import M3UFilters from './M3UFilters'; const M3U = ({ @@ -41,6 +42,7 @@ const M3U = ({ const fetchChannelGroups = useChannelsStore((s) => s.fetchChannelGroups); const fetchPlaylists = usePlaylistsStore((s) => s.fetchPlaylists); const fetchEPGs = useEPGsStore((s) => s.fetchEPGs); + const fetchCategories = useVODStore((s) => s.fetchCategories); const [playlist, setPlaylist] = useState(null); const [file, setFile] = useState(null); @@ -91,12 +93,13 @@ const M3U = ({ password: '', stale_stream_days: m3uAccount.stale_stream_days !== undefined && - m3uAccount.stale_stream_days !== null + m3uAccount.stale_stream_days !== null ? m3uAccount.stale_stream_days : 7, - priority: m3uAccount.priority !== undefined && m3uAccount.priority !== null - ? m3uAccount.priority - : 0, + priority: + m3uAccount.priority !== undefined && m3uAccount.priority !== null + ? m3uAccount.priority + : 0, enable_vod: m3uAccount.enable_vod || false, }); @@ -170,6 +173,12 @@ const M3U = ({ const updatedPlaylist = await API.getPlaylist(newPlaylist.id); await Promise.all([fetchChannelGroups(), fetchPlaylists(), fetchEPGs()]); + + // If this is an XC account with VOD enabled, also fetch VOD categories + if (values.account_type === 'XC' && values.enable_vod) { + fetchCategories(); + } + console.log('opening group options'); setPlaylist(updatedPlaylist); setGroupFilterModalOpen(true); @@ -402,7 +411,13 @@ const M3U = ({ variant="filled" // color={theme.custom.colors.buttonPrimary} size="sm" - onClick={() => setGroupFilterModalOpen(true)} + onClick={() => { + // If this is an XC account with VOD enabled, fetch VOD categories + if (m3uAccount?.account_type === 'XC' && m3uAccount?.enable_vod) { + fetchCategories(); + } + setGroupFilterModalOpen(true); + }} > Groups diff --git a/frontend/src/components/forms/M3UGroupFilter.jsx b/frontend/src/components/forms/M3UGroupFilter.jsx index 48f3e011..cb70ae86 100644 --- a/frontend/src/components/forms/M3UGroupFilter.jsx +++ b/frontend/src/components/forms/M3UGroupFilter.jsx @@ -31,6 +31,7 @@ import { } from '@mantine/core'; import { Info } from 'lucide-react'; import useChannelsStore from '../../store/channels'; +import useVODStore from '../../store/useVODStore'; import { CircleCheck, CircleX } from 'lucide-react'; import { notifications } from '@mantine/notifications'; import LiveGroupFilter from './LiveGroupFilter'; @@ -49,6 +50,7 @@ const OptionWithTooltip = forwardRef( const M3UGroupFilter = ({ playlist = null, isOpen, onClose }) => { const channelGroups = useChannelsStore((s) => s.channelGroups); + const fetchCategories = useVODStore((s) => s.fetchCategories); const [groupStates, setGroupStates] = useState([]); const [isLoading, setIsLoading] = useState(false); const [movieCategoryStates, setMovieCategoryStates] = useState([]); @@ -84,6 +86,18 @@ const M3UGroupFilter = ({ playlist = null, isOpen, onClose }) => { ); }, [playlist, channelGroups]); + // Fetch VOD categories when modal opens for XC accounts with VOD enabled + useEffect(() => { + if ( + isOpen && + playlist && + playlist.account_type === 'XC' && + playlist.enable_vod + ) { + fetchCategories(); + } + }, [isOpen, playlist, fetchCategories]); + const submit = async () => { setIsLoading(true); try {