Blocca la seconda diretta sullo stesso utente, registra gli abusi in admin e presenta la copertina come grafica caricata dalla società, con demo Team MLTV. Co-authored-by: Cursor <cursoragent@cursor.com>
72 lines
2.6 KiB
Ruby
72 lines
2.6 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class StreamConcurrencyViolation < ApplicationRecord
|
|
LOOKBACK = 30.days
|
|
|
|
belongs_to :user, optional: true
|
|
belongs_to :occupying_session, class_name: "StreamSession", optional: true
|
|
belongs_to :attempted_session, class_name: "StreamSession", optional: true
|
|
belongs_to :occupying_club, class_name: "Club", optional: true
|
|
belongs_to :attempted_club, class_name: "Club", optional: true
|
|
|
|
validates :user_email, :occupying_match_label, :attempted_match_label, presence: true
|
|
validates :attempt_action, inclusion: { in: %w[start resume] }
|
|
|
|
scope :recent, -> { order(created_at: :desc) }
|
|
scope :since, ->(time) { where("created_at >= ?", time) }
|
|
scope :lookback, -> { since(LOOKBACK.ago) }
|
|
scope :two_devices, -> { where(devices_differ: true) }
|
|
scope :for_club, lambda { |club_id|
|
|
where("occupying_club_id = :id OR attempted_club_id = :id", id: club_id)
|
|
}
|
|
scope :for_session, lambda { |session_id|
|
|
where("occupying_session_id = :id OR attempted_session_id = :id", id: session_id)
|
|
}
|
|
|
|
def self.record!(attempted:, occupying:, action: "start")
|
|
user = attempted.user || occupying.user
|
|
occupying_club = occupying.match&.team&.club
|
|
attempted_club = attempted.match&.team&.club
|
|
occupying_device = occupying.client_device_label
|
|
attempted_device = attempted.client_device_label
|
|
|
|
create!(
|
|
user: user,
|
|
occupying_session: occupying,
|
|
attempted_session: attempted,
|
|
occupying_club: occupying_club,
|
|
attempted_club: attempted_club,
|
|
attempt_action: action.to_s,
|
|
user_email: user&.email.presence || "unknown",
|
|
user_name: user&.name,
|
|
occupying_club_name: occupying_club&.name,
|
|
attempted_club_name: attempted_club&.name,
|
|
occupying_match_label: occupying.match_label,
|
|
attempted_match_label: attempted.match_label,
|
|
occupying_status: occupying.status,
|
|
occupying_device: occupying_device,
|
|
attempted_device: attempted_device,
|
|
devices_differ: StreamSession.devices_differ?(occupying, attempted),
|
|
metadata: {
|
|
occupying_session_id: occupying.id,
|
|
attempted_session_id: attempted.id,
|
|
occupying_client_os: occupying.client_os,
|
|
attempted_client_os: attempted.client_os,
|
|
occupying_app_version: occupying.app_version,
|
|
attempted_app_version: attempted.app_version
|
|
}.compact
|
|
)
|
|
rescue StandardError => e
|
|
Rails.logger.error("[StreamConcurrencyViolation] record failed: #{e.class} #{e.message}")
|
|
nil
|
|
end
|
|
|
|
def club_name
|
|
attempted_club_name.presence || occupying_club_name
|
|
end
|
|
|
|
def operator_label
|
|
[user_name.presence, user_email].compact.join(" · ")
|
|
end
|
|
end
|