Integrazione YouTube Live: OAuth squadra, canale piattaforma Light e UI.
Collegamento da Dettagli squadra e admin per il refresh token Match Live TV; API e app mobile allineate ai piani Light/Full. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -4,7 +4,8 @@ module Youtube
|
||||
|
||||
def initialize(team)
|
||||
@team = team
|
||||
@credential = team.youtube_credential
|
||||
@resolver = CredentialResolver.new(team)
|
||||
@credential = @resolver.resolve
|
||||
end
|
||||
|
||||
def create_broadcast!(title:, privacy_status: "unlisted", scheduled_at: nil)
|
||||
|
||||
18
backend/app/services/youtube/channel_info.rb
Normal file
18
backend/app/services/youtube/channel_info.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
module Youtube
|
||||
class ChannelInfo
|
||||
def self.fetch(access_token:)
|
||||
service = Google::Apis::YoutubeV3::YouTubeService.new
|
||||
service.authorization = access_token
|
||||
resp = service.list_channels("snippet", mine: true, max_results: 1)
|
||||
item = resp.items&.first
|
||||
return { channel_id: nil, channel_title: nil } unless item
|
||||
|
||||
{
|
||||
channel_id: item.id,
|
||||
channel_title: item.snippet&.title
|
||||
}
|
||||
rescue Google::Apis::Error
|
||||
{ channel_id: nil, channel_title: nil }
|
||||
end
|
||||
end
|
||||
end
|
||||
24
backend/app/services/youtube/credential_resolver.rb
Normal file
24
backend/app/services/youtube/credential_resolver.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
module Youtube
|
||||
class CredentialResolver
|
||||
def self.for_team(team)
|
||||
new(team).resolve
|
||||
end
|
||||
|
||||
def initialize(team)
|
||||
@team = team
|
||||
@mode = team.entitlements.plan.youtube_mode
|
||||
end
|
||||
|
||||
def resolve
|
||||
if @mode == "matchlivetv_light" && PlatformCredential.configured?
|
||||
PlatformCredential.new
|
||||
else
|
||||
@team.youtube_credential
|
||||
end
|
||||
end
|
||||
|
||||
def uses_platform_channel?
|
||||
@mode == "matchlivetv_light" && PlatformCredential.configured?
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -13,12 +13,13 @@ module Youtube
|
||||
data = JSON.parse(response.body)
|
||||
raise BroadcastService::Error, data["error_description"] if data["error"]
|
||||
|
||||
info = ChannelInfo.fetch(access_token: data["access_token"])
|
||||
{
|
||||
access_token: data["access_token"],
|
||||
refresh_token: data["refresh_token"],
|
||||
expires_in: data["expires_in"].to_i,
|
||||
channel_id: nil,
|
||||
channel_title: nil
|
||||
channel_id: info[:channel_id],
|
||||
channel_title: info[:channel_title]
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
39
backend/app/services/youtube/oauth_state.rb
Normal file
39
backend/app/services/youtube/oauth_state.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
module Youtube
|
||||
class OauthState
|
||||
PURPOSE = :youtube_oauth_connect
|
||||
|
||||
class << self
|
||||
def for_team(team_id:, user_id:)
|
||||
verifier.generate([team_id.to_s, user_id.to_s], expires_in: 1.hour)
|
||||
end
|
||||
|
||||
def for_platform(admin_id:)
|
||||
verifier.generate(["platform", admin_id.to_s], expires_in: 1.hour)
|
||||
end
|
||||
|
||||
def verify!(token)
|
||||
payload = verifier.verify(token)
|
||||
case payload
|
||||
when Array
|
||||
if payload.first == "platform"
|
||||
{ kind: :platform, admin_id: payload[1] }
|
||||
elsif payload.size == 2
|
||||
{ kind: :team, team_id: payload[0], user_id: payload[1] }
|
||||
else
|
||||
raise ArgumentError, "stato OAuth non valido"
|
||||
end
|
||||
else
|
||||
raise ArgumentError, "stato OAuth non valido"
|
||||
end
|
||||
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
||||
raise ArgumentError, "stato OAuth scaduto o non valido"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def verifier
|
||||
Rails.application.message_verifier(PURPOSE)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -6,7 +6,7 @@ module Youtube
|
||||
"https://www.googleapis.com/auth/youtube.force-ssl"
|
||||
].join(" ").freeze
|
||||
|
||||
def self.build(team_id:, redirect_uri:)
|
||||
def self.build(state:, redirect_uri: ENV["YOUTUBE_REDIRECT_URI"])
|
||||
params = {
|
||||
client_id: ENV.fetch("YOUTUBE_CLIENT_ID", "not_configured"),
|
||||
redirect_uri: redirect_uri,
|
||||
@@ -14,7 +14,7 @@ module Youtube
|
||||
scope: SCOPES,
|
||||
access_type: "offline",
|
||||
prompt: "consent",
|
||||
state: team_id
|
||||
state: state
|
||||
}
|
||||
"#{AUTH_URL}?#{URI.encode_www_form(params)}"
|
||||
end
|
||||
|
||||
44
backend/app/services/youtube/team_status.rb
Normal file
44
backend/app/services/youtube/team_status.rb
Normal file
@@ -0,0 +1,44 @@
|
||||
module Youtube
|
||||
class TeamStatus
|
||||
PLATFORM_LABEL = "Match Live TV".freeze
|
||||
|
||||
def initialize(team)
|
||||
@team = team
|
||||
@ent = team.entitlements
|
||||
@mode = @ent.plan.youtube_mode
|
||||
end
|
||||
|
||||
def selectable?
|
||||
return false unless @ent.youtube_enabled?
|
||||
|
||||
case @mode
|
||||
when "matchlivetv_light"
|
||||
PlatformCredential.configured?
|
||||
when "team"
|
||||
@team.youtube_credential.present?
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
def connected?
|
||||
selectable?
|
||||
end
|
||||
|
||||
def uses_platform_channel?
|
||||
@mode == "matchlivetv_light" && PlatformCredential.configured?
|
||||
end
|
||||
|
||||
def channel_title
|
||||
if uses_platform_channel?
|
||||
PLATFORM_LABEL
|
||||
else
|
||||
@team.youtube_credential&.channel_title
|
||||
end
|
||||
end
|
||||
|
||||
def needs_team_oauth?
|
||||
@mode == "team" && @ent.premium_full?
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user