module Api module V1 class TeamsController < BaseController include Api::UrlHelper include BrandingAttachments def index teams = current_user.streamable_teams render json: teams.map { |t| team_json(t) } end def show team = current_user.manageable_teams.find(params[:id]) render json: team_json(team, detail: true) end def create if current_user.owned_clubs.exists? return render json: { error: "Registra o gestisci la società dal sito web per aggiungere squadre." }, status: :unprocessable_entity end club = Club.create!(name: team_params[:name], sport: team_params[:sport] || "volleyball", primary_color: "#e53935", secondary_color: "#ffffff") ClubMembership.create!(user: current_user, club: club, role: "owner") team = club.teams.create!(name: team_params[:name], sport: club.sport) Billing::AssignPlan.call(club: club, plan_slug: "free") render json: team_json(team), status: :created end def recordings team = current_user.streamable_teams.find { |t| t.id.to_s == params[:id].to_s } raise ActiveRecord::RecordNotFound unless team unless team.entitlements.can_access_recordings? return render json: { error: "Archivio gare disponibile con Premium Light o Full", error_code: "premium_required", billing_url: team.entitlements.billing_url }, status: :forbidden end recs = team.recordings.not_deleted .where(status: %w[ready processing]) .includes(stream_session: :match) .order(recorded_at: :desc, created_at: :desc) .limit(50) render json: recs.map { |r| recording_json(r) } end def update team = current_user.manageable_teams.find(params[:id]) team.update!(team_params) attach_team_logo(team) render json: team_json(team) end def add_member team = current_user.manageable_teams.find(params[:id]) team.entitlements.assert_can_invite! member = User.find(params[:user_id]) UserTeam.find_or_create_by!(user: member, team: team) { |ut| ut.role = "member" } head :no_content end def remove_member team = current_user.manageable_teams.find(params[:id]) ut = team.user_teams.find_by!(user_id: params[:user_id], role: "member") ut.destroy! head :no_content end private def team_params p = params.require(:team).permit(:name, :sport, :logo_url, :primary_color, :secondary_color) if p[:primary_color].present? p[:primary_color] = normalize_hex_color(p[:primary_color], p[:primary_color]) end if p[:secondary_color].present? p[:secondary_color] = normalize_hex_color(p[:secondary_color], p[:secondary_color]) end p end def attach_team_logo(team) file = params[:logo_file] team.logo_file.attach(file) if file.present? end def team_json(team, detail: false) ent = team.entitlements yt = Youtube::TeamStatus.new(team) resolver = Youtube::CredentialResolver.new(team) data = { id: team.id, name: team.name, sport: team.sport, logo_url: api_absolute_url(team.effective_logo_url), primary_color: team.effective_primary_color, secondary_color: team.effective_secondary_color, club_id: team.club_id, club_name: team.club.name, youtube_connected: yt.connected?, youtube_selectable: yt.selectable?, youtube_channel_title: yt.channel_title, youtube_uses_platform_channel: yt.uses_platform_channel?, youtube_platform_available: resolver.platform_available?, youtube_team_channel_available: resolver.team_channel_available?, youtube_team_channel_title: team.club.youtube_credential&.channel_title, plan_slug: ent.plan.slug, plan_name: ent.plan.name, premium_active: ent.premium_active?, premium_full: ent.premium_full?, subscription_status: ent.subscription.status, features: ent.plan.features, billing_url: ent.billing_url, staff_manage_url: ent.staff_manage_url, max_staff: ent.max_staff, max_staff_transmission: ent.max_staff_transmission, staff_used: ent.staff_count, staff_transmission_used: ent.staff_count_for("transmission"), concurrent_streams_used: ent.concurrent_streams_used, concurrent_streams_limit: ent.concurrent_streams_limit, recordings_enabled: ent.can_access_recordings?, phone_download_enabled: ent.phone_download_enabled?, youtube_enabled: ent.youtube_enabled?, youtube_mode: ent.plan.youtube_mode, staff_role: current_user.staff_role_for(team), can_stream: current_user.can_stream_for?(team), can_connect_youtube: team.club.owned_by?(current_user) && ent.premium_full? && ent.youtube_enabled? } if detail data[:members] = team.user_teams.includes(:user).where.not(role: "owner").map do |ut| { id: ut.user.id, name: ut.user.name, email: ut.user.email, role: ut.role } end end data end def recording_json(recording) session = recording.stream_session match = session.match ent = recording.team.entitlements { id: recording.id, session_id: session.id, match_id: match.id, title: recording.title_or_default, opponent_name: match.opponent_name, team_name: match.team.name, status: recording.status, status_label: recording.status_label, privacy_status: recording.privacy_status, ended_at: session.ended_at, recorded_at: recording.recorded_at_or_fallback, duration_secs: recording.duration_secs, duration_label: recording.duration_label, byte_size: recording.byte_size, byte_size_label: recording.byte_size_label, replay_url: recording.replay_url, playback_url: recording.playback_stream_url, thumbnail_url: recording.thumbnail_url, download_enabled: ent.phone_download_enabled?, view_count: recording.view_count, views_label: recording.views_label, youtube_video_id: recording.youtube_video_id, youtube_watch_url: recording.youtube_watch_url, youtube_publish_enabled: ent.premium_full? && ent.youtube_enabled?, expires_at: recording.expires_at, metadata: recording.metadata } end end end end