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:
113
backend/db/migrate/20260525000001_create_match_live_tv_schema.rb
Normal file
113
backend/db/migrate/20260525000001_create_match_live_tv_schema.rb
Normal file
@@ -0,0 +1,113 @@
|
||||
class CreateMatchLiveTvSchema < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
enable_extension "pgcrypto" unless extension_enabled?("pgcrypto")
|
||||
|
||||
create_table :users, id: :uuid do |t|
|
||||
t.string :email, null: false
|
||||
t.string :password_digest, null: false
|
||||
t.string :name, null: false
|
||||
t.string :role, null: false, default: "coach"
|
||||
t.timestamps
|
||||
end
|
||||
add_index :users, :email, unique: true
|
||||
|
||||
create_table :teams, id: :uuid do |t|
|
||||
t.string :name, null: false
|
||||
t.string :sport, default: "volleyball"
|
||||
t.string :logo_url
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
create_table :user_teams, id: :uuid do |t|
|
||||
t.references :user, type: :uuid, null: false, foreign_key: true
|
||||
t.references :team, type: :uuid, null: false, foreign_key: true
|
||||
t.string :role, null: false, default: "member"
|
||||
t.timestamps
|
||||
end
|
||||
add_index :user_teams, %i[user_id team_id], unique: true
|
||||
|
||||
create_table :youtube_credentials, id: :uuid do |t|
|
||||
t.references :team, type: :uuid, null: false, foreign_key: true
|
||||
t.text :access_token_encrypted
|
||||
t.text :refresh_token_encrypted
|
||||
t.datetime :expires_at
|
||||
t.string :channel_id
|
||||
t.string :channel_title
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
create_table :matches, id: :uuid do |t|
|
||||
t.references :team, type: :uuid, null: false, foreign_key: true
|
||||
t.string :opponent_name, null: false
|
||||
t.string :location
|
||||
t.datetime :scheduled_at
|
||||
t.string :sport, default: "volleyball"
|
||||
t.integer :sets_to_win, default: 3
|
||||
t.jsonb :roster_numbers, default: []
|
||||
t.string :category
|
||||
t.string :phase
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
create_table :stream_sessions, id: :uuid do |t|
|
||||
t.references :match, type: :uuid, null: false, foreign_key: true
|
||||
t.references :user, type: :uuid, null: false, foreign_key: true
|
||||
t.string :status, null: false, default: "idle"
|
||||
t.string :platform, default: "youtube"
|
||||
t.text :stream_key_encrypted
|
||||
t.string :rtmp_url
|
||||
t.string :youtube_broadcast_id
|
||||
t.string :youtube_stream_id
|
||||
t.string :privacy_status, default: "unlisted"
|
||||
t.string :quality_preset, default: "720p_30_2.5mbps"
|
||||
t.integer :target_bitrate, default: 2_500_000
|
||||
t.integer :target_fps, default: 30
|
||||
t.datetime :started_at
|
||||
t.datetime :ended_at
|
||||
t.integer :total_duration_secs, default: 0
|
||||
t.integer :disconnection_count, default: 0
|
||||
t.string :publish_token
|
||||
t.string :pairing_token_digest
|
||||
t.datetime :pairing_token_expires_at
|
||||
t.string :timeout_job_id
|
||||
t.timestamps
|
||||
end
|
||||
add_index :stream_sessions, :publish_token, unique: true
|
||||
add_index :stream_sessions, :status
|
||||
|
||||
create_table :stream_events, id: :uuid do |t|
|
||||
t.references :stream_session, type: :uuid, null: false, foreign_key: true
|
||||
t.string :event_type, null: false
|
||||
t.jsonb :metadata, default: {}
|
||||
t.datetime :occurred_at, null: false
|
||||
end
|
||||
add_index :stream_events, %i[stream_session_id occurred_at]
|
||||
|
||||
create_table :score_states, id: :uuid do |t|
|
||||
t.references :stream_session, type: :uuid, null: false, foreign_key: true, index: { unique: true }
|
||||
t.integer :home_sets, default: 0
|
||||
t.integer :away_sets, default: 0
|
||||
t.integer :home_points, default: 0
|
||||
t.integer :away_points, default: 0
|
||||
t.integer :current_set, default: 1
|
||||
t.string :period
|
||||
t.boolean :timeout_home, default: false
|
||||
t.boolean :timeout_away, default: false
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
create_table :device_states, id: :uuid do |t|
|
||||
t.references :stream_session, type: :uuid, null: false, foreign_key: true
|
||||
t.string :device_role, null: false
|
||||
t.integer :battery_level
|
||||
t.string :network_type
|
||||
t.integer :signal_strength
|
||||
t.integer :current_bitrate
|
||||
t.integer :target_bitrate
|
||||
t.integer :fps
|
||||
t.datetime :last_seen_at
|
||||
t.timestamps
|
||||
end
|
||||
add_index :device_states, %i[stream_session_id device_role], unique: true
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class AddSetPartialsToScoreStates < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
add_column :score_states, :set_partials, :jsonb, null: false, default: []
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class AddScoringRulesToMatches < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
add_column :matches, :scoring_rules, :jsonb, null: false, default: {}
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,47 @@
|
||||
class AddBillingAndRecordings < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
create_table :plans, id: :uuid do |t|
|
||||
t.string :slug, null: false
|
||||
t.string :name, null: false
|
||||
t.string :stripe_price_id
|
||||
t.jsonb :features, null: false, default: {}
|
||||
t.timestamps
|
||||
end
|
||||
add_index :plans, :slug, unique: true
|
||||
|
||||
create_table :subscriptions, id: :uuid do |t|
|
||||
t.references :team, null: false, type: :uuid, foreign_key: true, index: { unique: true }
|
||||
t.references :plan, null: false, type: :uuid, foreign_key: true
|
||||
t.string :status, null: false, default: "active"
|
||||
t.string :stripe_customer_id
|
||||
t.string :stripe_subscription_id
|
||||
t.datetime :current_period_start
|
||||
t.datetime :current_period_end
|
||||
t.boolean :cancel_at_period_end, default: false, null: false
|
||||
t.timestamps
|
||||
end
|
||||
add_index :subscriptions, :stripe_subscription_id, unique: true, where: "stripe_subscription_id IS NOT NULL"
|
||||
|
||||
create_table :recordings, id: :uuid do |t|
|
||||
t.references :stream_session, null: false, type: :uuid, foreign_key: true, index: { unique: true }
|
||||
t.references :team, null: false, type: :uuid, foreign_key: true
|
||||
t.string :status, null: false, default: "processing"
|
||||
t.string :storage_path
|
||||
t.datetime :expires_at
|
||||
t.timestamps
|
||||
end
|
||||
add_index :recordings, :expires_at
|
||||
|
||||
create_table :team_invitations, id: :uuid do |t|
|
||||
t.references :team, null: false, type: :uuid, foreign_key: true
|
||||
t.string :email, null: false
|
||||
t.string :token_digest, null: false
|
||||
t.string :role, null: false, default: "member"
|
||||
t.datetime :expires_at, null: false
|
||||
t.datetime :accepted_at
|
||||
t.timestamps
|
||||
end
|
||||
add_index :team_invitations, [:team_id, :email]
|
||||
add_index :team_invitations, :token_digest, unique: true
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
class UpdatePlansThreeTier < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
# Plan features and slugs are applied via db/seeds/plans.rb (loaded from db:seed)
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
8
backend/db/migrate/20260527120000_add_staff_kind.rb
Normal file
8
backend/db/migrate/20260527120000_add_staff_kind.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
class AddStaffKind < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
add_column :team_invitations, :staff_kind, :string, null: false, default: "transmission"
|
||||
add_column :user_teams, :staff_kind, :string
|
||||
add_index :team_invitations, [:team_id, :staff_kind]
|
||||
add_index :user_teams, [:team_id, :staff_kind]
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user