"""Playlist blueprint for managing player playlists.""" from flask import (Blueprint, render_template, request, redirect, url_for, flash, jsonify, current_app) from flask_login import login_required from sqlalchemy import desc import os from app.extensions import db, cache from app.models import Player, Content from app.utils.logger import log_action playlist_bp = Blueprint('playlist', __name__, url_prefix='/playlist') @playlist_bp.route('/') @login_required def manage_playlist(player_id: int): """Manage playlist for a specific player.""" player = Player.query.get_or_404(player_id) # Get all content for this player, ordered by position playlist_content = Content.query.filter_by( player_id=player_id ).order_by(Content.position).all() # Get available content (files not already in this player's playlist) all_files = db.session.query(Content.filename).distinct().all() playlist_filenames = {c.filename for c in playlist_content} available_files = [f[0] for f in all_files if f[0] not in playlist_filenames] return render_template('playlist/manage_playlist.html', player=player, playlist_content=playlist_content, available_files=available_files) @playlist_bp.route('//add', methods=['POST']) @login_required def add_to_playlist(player_id: int): """Add content to player's playlist.""" player = Player.query.get_or_404(player_id) try: filename = request.form.get('filename') duration = request.form.get('duration', type=int, default=10) if not filename: flash('Please provide a filename.', 'warning') return redirect(url_for('playlist.manage_playlist', player_id=player_id)) # Get max position max_position = db.session.query(db.func.max(Content.position)).filter_by( player_id=player_id ).scalar() or 0 # Get file info from existing content existing_content = Content.query.filter_by(filename=filename).first() if not existing_content: flash('File not found.', 'danger') return redirect(url_for('playlist.manage_playlist', player_id=player_id)) # Create new content entry for this player new_content = Content( filename=filename, content_type=existing_content.content_type, duration=duration, file_size=existing_content.file_size, player_id=player_id, position=max_position + 1 ) db.session.add(new_content) # Increment playlist version player.playlist_version += 1 db.session.commit() cache.clear() log_action('info', f'Added "{filename}" to playlist for player "{player.name}"') flash(f'Added "{filename}" to playlist.', 'success') except Exception as e: db.session.rollback() log_action('error', f'Error adding to playlist: {str(e)}') flash('Error adding to playlist.', 'danger') return redirect(url_for('playlist.manage_playlist', player_id=player_id)) @playlist_bp.route('//remove/', methods=['POST']) @login_required def remove_from_playlist(player_id: int, content_id: int): """Remove content from player's playlist.""" player = Player.query.get_or_404(player_id) content = Content.query.get_or_404(content_id) if content.player_id != player_id: flash('Content does not belong to this player.', 'danger') return redirect(url_for('playlist.manage_playlist', player_id=player_id)) try: filename = content.filename # Delete content db.session.delete(content) # Reorder remaining content remaining_content = Content.query.filter_by( player_id=player_id ).order_by(Content.position).all() for idx, item in enumerate(remaining_content, start=1): item.position = idx # Increment playlist version player.playlist_version += 1 db.session.commit() cache.clear() log_action('info', f'Removed "{filename}" from playlist for player "{player.name}"') flash(f'Removed "{filename}" from playlist.', 'success') except Exception as e: db.session.rollback() log_action('error', f'Error removing from playlist: {str(e)}') flash('Error removing from playlist.', 'danger') return redirect(url_for('playlist.manage_playlist', player_id=player_id)) @playlist_bp.route('//reorder', methods=['POST']) @login_required def reorder_playlist(player_id: int): """Reorder playlist items.""" player = Player.query.get_or_404(player_id) try: # Get new order from JSON data = request.get_json() content_ids = data.get('content_ids', []) if not content_ids: return jsonify({'success': False, 'message': 'No content IDs provided'}), 400 # Update positions for idx, content_id in enumerate(content_ids, start=1): content = Content.query.get(content_id) if content and content.player_id == player_id: content.position = idx # Increment playlist version player.playlist_version += 1 db.session.commit() cache.clear() log_action('info', f'Reordered playlist for player "{player.name}" (version {player.playlist_version})') return jsonify({ 'success': True, 'message': 'Playlist reordered successfully', 'version': player.playlist_version }) except Exception as e: db.session.rollback() log_action('error', f'Error reordering playlist: {str(e)}') return jsonify({'success': False, 'message': str(e)}), 500 @playlist_bp.route('//update-duration/', methods=['POST']) @login_required def update_duration(player_id: int, content_id: int): """Update content duration in playlist.""" player = Player.query.get_or_404(player_id) content = Content.query.get_or_404(content_id) if content.player_id != player_id: return jsonify({'success': False, 'message': 'Content does not belong to this player'}), 403 try: duration = request.form.get('duration', type=int) if not duration or duration < 1: return jsonify({'success': False, 'message': 'Invalid duration'}), 400 content.duration = duration player.playlist_version += 1 db.session.commit() cache.clear() log_action('info', f'Updated duration for "{content.filename}" in player "{player.name}" playlist') return jsonify({ 'success': True, 'message': 'Duration updated', 'version': player.playlist_version }) except Exception as e: db.session.rollback() log_action('error', f'Error updating duration: {str(e)}') return jsonify({'success': False, 'message': str(e)}), 500 @playlist_bp.route('//clear', methods=['POST']) @login_required def clear_playlist(player_id: int): """Clear all content from player's playlist.""" player = Player.query.get_or_404(player_id) try: # Delete all content for this player Content.query.filter_by(player_id=player_id).delete() # Increment playlist version player.playlist_version += 1 db.session.commit() cache.clear() log_action('info', f'Cleared playlist for player "{player.name}"') flash('Playlist cleared successfully.', 'success') except Exception as e: db.session.rollback() log_action('error', f'Error clearing playlist: {str(e)}') flash('Error clearing playlist.', 'danger') return redirect(url_for('playlist.manage_playlist', player_id=player_id))