module Public class LiveController < SiteBaseController layout "marketing_live" ACTIVE_STATUSES = %w[live connecting reconnecting].freeze def index @query = params[:q].to_s.strip @club = Club.find_by(id: params[:club_id]) if params[:club_id].present? team_ids = @club&.teams&.pluck(:id) sessions = StreamSession .broadcasting .includes(:score_state, match: { team: :club }) sessions = sessions.joins(:match).where(matches: { team_id: team_ids }) if team_ids.present? @sessions = sessions .search_by_team_or_opponent(@query) .order(Arel.sql("started_at DESC NULLS LAST"), created_at: :desc) # Solo dirette già in onda: le partite «programmate» restano visibili anche se c’è sessione idle. broadcasting_match_ids = StreamSession.broadcasting.select(:match_id) upcoming = Match.scheduled_for_live.includes(team: :club) upcoming = upcoming.where(team_id: team_ids) if team_ids.present? @upcoming_matches = upcoming .search_teams_or_opponents(@query) .where.not(id: broadcasting_match_ids) .order(scheduled_at: :asc) .limit(50) @online_paths = Mediamtx::Client.new.online_path_names return unless logged_in? && @club @schedulable_teams = current_user.schedulable_teams_for(@club) @can_schedule_match = @schedulable_teams.any? end def show @session = StreamSession.includes(match: { team: :club }).find(params[:id]) @match = @session.match @stream_closed = @session.terminal? @on_air = !@stream_closed && mediamtx_online?(@session) end def status session = StreamSession.includes(match: { team: :club }).find(params[:id]) closed = session.terminal? render json: { status: session.status, stream_closed: closed, live: !closed && (session.live? || mediamtx_online?(session)), on_air: !closed && mediamtx_online?(session), ended_at: session.ended_at, home_name: session.match.team.name, away_name: session.match.opponent_name, score: session.score_state&.as_cable_payload } end private def mediamtx_online?(session) @online_paths_cache ||= Mediamtx::Client.new.online_path_names @online_paths_cache.include?(session.mediamtx_path_name) end end end