""" Player management utilities """ from app.extensions import db, bcrypt from app.models.player import Player from app.models.content import Content from app.utils.logger import log_player_created, log_player_edited, log_player_deleted, log_content_reordered def create_player(username, hostname, password, quickconnect_password=None): """ Create a new player Args: username (str): Player username hostname (str): Player hostname password (str): Player password quickconnect_password (str): Quick connect password (optional) Returns: tuple: (success, player_or_error_message) """ try: # Check if hostname already exists if Player.query.filter_by(hostname=hostname).first(): return False, f"Player with hostname '{hostname}' already exists" # Create new player player = Player( username=username, hostname=hostname ) # Set passwords player.set_password(password) if quickconnect_password: player.set_quickconnect_password(quickconnect_password) db.session.add(player) db.session.commit() log_player_created(username, hostname) return True, player except Exception as e: db.session.rollback() return False, str(e) def edit_player(player_id, username=None, hostname=None, password=None, quickconnect_password=None): """ Edit an existing player Args: player_id (int): Player ID username (str): New username (optional) hostname (str): New hostname (optional) password (str): New password (optional) quickconnect_password (str): New quick connect password (optional) Returns: tuple: (success, player_or_error_message) """ try: player = Player.query.get(player_id) if not player: return False, "Player not found" # Check for hostname conflicts if hostname and hostname != player.hostname: existing = Player.query.filter_by(hostname=hostname).first() if existing and existing.id != player_id: return False, f"Player with hostname '{hostname}' already exists" player.hostname = hostname # Update fields if username: player.username = username if password: player.set_password(password) if quickconnect_password: player.set_quickconnect_password(quickconnect_password) db.session.commit() log_player_edited(player.username) return True, player except Exception as e: db.session.rollback() return False, str(e) def delete_player(player_id): """ Delete a player and all its content Args: player_id (int): Player ID Returns: tuple: (success, error_message) """ try: player = Player.query.get(player_id) if not player: return False, "Player not found" username = player.username # Delete all content files import os from flask import current_app upload_folder = os.path.join(current_app.static_folder, 'uploads') for content in player.content: file_path = os.path.join(upload_folder, content.file_name) if os.path.exists(file_path): try: os.remove(file_path) except: pass # File might be used by other content # Remove from groups for group in player.groups: group.players.remove(player) # Delete player (cascades to content) db.session.delete(player) db.session.commit() log_player_deleted(username) return True, None except Exception as e: db.session.rollback() return False, str(e) def get_player_content(player_id): """ Get all content for a player ordered by position Args: player_id (int): Player ID Returns: list: List of Content objects """ return Content.query.filter_by(player_id=player_id).order_by(Content.position).all() def update_player_content_order(player_id, content_items): """ Update the order of content items for a player Args: player_id (int): Player ID content_items (list): List of content items with new positions Returns: tuple: (success, error_message, new_playlist_version) """ try: player = Player.query.get(player_id) if not player: return False, "Player not found", None # Update positions for i, item in enumerate(content_items): content_id = item.get('id') content = Content.query.filter_by(id=content_id, player_id=player_id).first() if content: content.position = i # Increment playlist version player.increment_playlist_version() db.session.commit() log_content_reordered('player', player.username) return True, None, player.playlist_version except Exception as e: db.session.rollback() return False, str(e), None def get_player_by_hostname(hostname): """ Get player by hostname Args: hostname (str): Player hostname Returns: Player: Player object or None """ return Player.query.filter_by(hostname=hostname).first() def verify_player_credentials(hostname, password, quickconnect_code=None): """ Verify player credentials Args: hostname (str): Player hostname password (str): Player password quickconnect_code (str): Quick connect code (optional) Returns: tuple: (success, player_or_error_message) """ player = get_player_by_hostname(hostname) if not player: return False, "Player not found" if quickconnect_code: if player.verify_quickconnect_code(quickconnect_code): return True, player else: return False, "Invalid quick connect code" else: if player.check_password(password): return True, player else: return False, "Invalid password"