Initial commit: monorepo Match Live TV.
Rails API, app Flutter, infrastruttura Docker/MediaMTX, sito marketing e documentazione di deploy. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
4
backend/app/channels/application_cable/channel.rb
Normal file
4
backend/app/channels/application_cable/channel.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
module ApplicationCable
|
||||
class Channel < ActionCable::Channel::Base
|
||||
end
|
||||
end
|
||||
17
backend/app/channels/application_cable/connection.rb
Normal file
17
backend/app/channels/application_cable/connection.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
module ApplicationCable
|
||||
class Connection < ActionCable::Connection::Base
|
||||
identified_by :current_user
|
||||
|
||||
def connect
|
||||
payload = JsonWebToken.decode(token_from_header)
|
||||
self.current_user = User.find_by(id: payload[:user_id]) if payload
|
||||
reject_unauthorized_connection unless current_user
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def token_from_header
|
||||
request.headers["Authorization"].to_s.delete_prefix("Bearer ").presence
|
||||
end
|
||||
end
|
||||
end
|
||||
9
backend/app/channels/concerns/cable_broadcastable.rb
Normal file
9
backend/app/channels/concerns/cable_broadcastable.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
module CableBroadcastable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
class_methods do
|
||||
def broadcast_message(session, data)
|
||||
broadcast_to(session, method: "receive_message", data: data)
|
||||
end
|
||||
end
|
||||
end
|
||||
83
backend/app/channels/session_channel.rb
Normal file
83
backend/app/channels/session_channel.rb
Normal file
@@ -0,0 +1,83 @@
|
||||
class SessionChannel < ApplicationCable::Channel
|
||||
include CableBroadcastable
|
||||
def subscribed
|
||||
session = StreamSession.joins(match: :team)
|
||||
.merge(current_user.teams)
|
||||
.find(params[:session_id])
|
||||
stream_for session
|
||||
session.device_states.find_or_create_by!(device_role: params[:device_role] || "controller")
|
||||
end
|
||||
|
||||
def unsubscribed
|
||||
stop_all_streams
|
||||
end
|
||||
|
||||
def receive(data)
|
||||
session = StreamSession.find(params[:session_id])
|
||||
handle_message(session, data)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def handle_message(session, data)
|
||||
case data["type"]
|
||||
when "command"
|
||||
SessionChannel.broadcast_message(session, data)
|
||||
execute_command(session, data)
|
||||
when "score_update"
|
||||
update_score(session, data)
|
||||
when "timeout"
|
||||
update_timeout(session, data)
|
||||
when "device_state"
|
||||
update_device(session, data)
|
||||
end
|
||||
end
|
||||
|
||||
def execute_command(session, data)
|
||||
case data["action"]
|
||||
when "start_stream"
|
||||
Sessions::Start.new(session).call
|
||||
when "stop_stream"
|
||||
Sessions::Stop.new(session).call
|
||||
when "pause_stream"
|
||||
Sessions::Pause.new(session).call
|
||||
end
|
||||
end
|
||||
|
||||
def update_score(session, data)
|
||||
score = session.score_state || session.create_score_state!
|
||||
score.update!(
|
||||
home_sets: data["home_sets"] || score.home_sets,
|
||||
away_sets: data["away_sets"] || score.away_sets,
|
||||
home_points: data["home_points"] || score.home_points,
|
||||
away_points: data["away_points"] || score.away_points,
|
||||
current_set: data["current_set"] || score.current_set,
|
||||
set_partials: data.key?("set_partials") ? data["set_partials"] : score.set_partials
|
||||
)
|
||||
SessionChannel.broadcast_message(session, score.as_cable_payload)
|
||||
end
|
||||
|
||||
def update_timeout(session, data)
|
||||
score = session.score_state
|
||||
return unless score
|
||||
|
||||
if data["team"] == "home"
|
||||
score.update!(timeout_home: true)
|
||||
else
|
||||
score.update!(timeout_away: true)
|
||||
end
|
||||
SessionChannel.broadcast_message(session, { type: "timeout", team: data["team"] })
|
||||
end
|
||||
|
||||
def update_device(session, data)
|
||||
state = session.device_states.find_or_initialize_by(device_role: data["device_role"] || "camera")
|
||||
state.update!(
|
||||
battery_level: data["battery"],
|
||||
network_type: data["network"],
|
||||
current_bitrate: data["bitrate"],
|
||||
fps: data["fps"],
|
||||
last_seen_at: Time.current
|
||||
)
|
||||
SessionChannel.broadcast_message(session, state.as_cable_payload)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user