Initial commit
This commit is contained in:
57
app/services/vendors/broad_sign/broad_sign_fetch_schedule.rb
vendored
Normal file
57
app/services/vendors/broad_sign/broad_sign_fetch_schedule.rb
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../log/loggable'
|
||||
require_relative '../errors/schedule_fetch_error'
|
||||
require 'net/http'
|
||||
|
||||
module Vendors
|
||||
module BroadSign
|
||||
class BroadSignFetchSchedule
|
||||
include Log::Loggable
|
||||
|
||||
AIR_DOMAIN = 'air.broadsign.com'
|
||||
PATH = 'playlist/v1/generate'
|
||||
|
||||
def initialize(tokens)
|
||||
@tokens = tokens
|
||||
end
|
||||
|
||||
def call(params)
|
||||
params = ActiveSupport::HashWithIndifferentAccess.new(
|
||||
screen: '1',
|
||||
duration: 3600
|
||||
).merge(params_whitelist(params))
|
||||
logger.info "BroadSign fetch schedule request for player #{params[:player]}"
|
||||
url = URI.join("https://#{AIR_DOMAIN}", PATH)
|
||||
res = Net::HTTP.post(
|
||||
url,
|
||||
{
|
||||
player_identifier: params[:player].to_s,
|
||||
screen_identifier: params[:screen]&.to_s,
|
||||
duration: "#{params[:duration]}s"
|
||||
}.to_json,
|
||||
{
|
||||
"Authorization": "Bearer #{@tokens.auth_token}",
|
||||
"Content-Type": 'application/json'
|
||||
}
|
||||
)
|
||||
case res
|
||||
when Net::HTTPSuccess
|
||||
JSON.parse(res.body).with_indifferent_access
|
||||
else
|
||||
logger.error "Error fetching BroadSign Air schedule: #{res.code}"
|
||||
raise Vendors::Errors::ScheduleFetchError, { player: params[:player], response_code: res.code }.to_json
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def params_whitelist(params)
|
||||
params.slice(
|
||||
:player,
|
||||
:screen,
|
||||
:duration
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
15
app/services/vendors/broad_sign/broad_sign_tokens.rb
vendored
Normal file
15
app/services/vendors/broad_sign/broad_sign_tokens.rb
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../log/loggable'
|
||||
|
||||
module Vendors
|
||||
module BroadSign
|
||||
class BroadSignTokens
|
||||
include Singleton
|
||||
|
||||
def auth_token
|
||||
AppConfig.get_mandatory 'vendors.broad_sign.token'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
47
app/services/vendors/broad_sign/broad_sign_transform_schedule.rb
vendored
Normal file
47
app/services/vendors/broad_sign/broad_sign_transform_schedule.rb
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../log/loggable'
|
||||
require_relative '../../schedule_pipeline/models/schedule'
|
||||
require_relative '../../schedule_pipeline/models/schedule_item'
|
||||
require_relative '../errors/schedule_transform_error'
|
||||
|
||||
module Vendors
|
||||
module BroadSign
|
||||
class BroadSignTransformSchedule
|
||||
include Log::Loggable
|
||||
|
||||
def call(vendor, player, schedule, content_map)
|
||||
logger.debug("BroadSign schedule transform for vendor #{vendor}, player #{player}")
|
||||
start_time = nil
|
||||
|
||||
# for performance reasons, here we truncate the items list to the first N items where N is the number of contents
|
||||
# in the schedule. This assumes the schedule round-robins content!
|
||||
truncate_schedule(schedule, content_map.size)
|
||||
|
||||
items = schedule[:items].collect do |item|
|
||||
start_time ||= item[:startTime]
|
||||
SchedulePipeline::Models::ScheduleItem.new(
|
||||
item[:duration],
|
||||
content_map[item[:contentIndex] || 0][:id],
|
||||
# TODO: build full POP reporting url using this token
|
||||
item[:token]
|
||||
)
|
||||
end
|
||||
raise Vendors::Errors::ScheduleTransformError, 'Schedule without a start time' if start_time.nil?
|
||||
|
||||
SchedulePipeline::Models::Schedule.new(
|
||||
"BroadSign schedule for player #{player}",
|
||||
vendor,
|
||||
player,
|
||||
start_time,
|
||||
items
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
def truncate_schedule(schedule, size)
|
||||
schedule[:items] = schedule[:items].first(size)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
7
app/services/vendors/errors/content_ingest_error.rb
vendored
Normal file
7
app/services/vendors/errors/content_ingest_error.rb
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Vendors
|
||||
module Errors
|
||||
class ContentIngestError < StandardError; end
|
||||
end
|
||||
end
|
||||
7
app/services/vendors/errors/schedule_fetch_error.rb
vendored
Normal file
7
app/services/vendors/errors/schedule_fetch_error.rb
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Vendors
|
||||
module Errors
|
||||
class ScheduleFetchError < StandardError; end
|
||||
end
|
||||
end
|
||||
7
app/services/vendors/errors/schedule_publish_error.rb
vendored
Normal file
7
app/services/vendors/errors/schedule_publish_error.rb
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Vendors
|
||||
module Errors
|
||||
class SchedulePublishError < StandardError; end
|
||||
end
|
||||
end
|
||||
7
app/services/vendors/errors/schedule_transform_error.rb
vendored
Normal file
7
app/services/vendors/errors/schedule_transform_error.rb
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Vendors
|
||||
module Errors
|
||||
class ScheduleTransformError < StandardError; end
|
||||
end
|
||||
end
|
||||
93
app/services/vendors/vistar/vistar_fetch_ad.rb
vendored
Normal file
93
app/services/vendors/vistar/vistar_fetch_ad.rb
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../log/loggable'
|
||||
require_relative '../errors/schedule_fetch_error'
|
||||
require 'net/http'
|
||||
|
||||
module Vendors
|
||||
module Vistar
|
||||
class VistarFetchAd
|
||||
include Log::Loggable
|
||||
|
||||
PATH = 'api/v1/get_ad/json'
|
||||
DEFAULT_SUPPORTED_MEDIA = %w[
|
||||
application/x-shockwave-dynamic-flash
|
||||
application/x-shockwave-flash
|
||||
image/jpeg
|
||||
image/png
|
||||
video/mp4
|
||||
video/mpeg
|
||||
video/mpg
|
||||
video/quicktime
|
||||
video/webm
|
||||
video/x-flv
|
||||
video/x-ms-wmv
|
||||
video/x-msvideo
|
||||
]
|
||||
|
||||
def initialize(tokens)
|
||||
@tokens = tokens
|
||||
end
|
||||
|
||||
def call(params)
|
||||
logger.info "Vistar fetch Ad request"
|
||||
res = Net::HTTP.post(
|
||||
Vendors::Vistar::VistarSettings.instance.vistar_url(PATH),
|
||||
body(params),
|
||||
{
|
||||
"Content-Type": 'application/json'
|
||||
}
|
||||
)
|
||||
case res
|
||||
when Net::HTTPSuccess
|
||||
JSON.parse(res.body).with_indifferent_access
|
||||
else
|
||||
logger.error "Error fetching Vistar Ad: #{res.code}"
|
||||
raise Vendors::Errors::ScheduleFetchError, { response_code: res.code }.to_json
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def body(params)
|
||||
display_area = (params[:display_area] || [{}]).each_with_index.collect do |item, idx|
|
||||
{
|
||||
id: "display-#{idx}",
|
||||
width: 1080,
|
||||
height: 1920,
|
||||
supported_media: DEFAULT_SUPPORTED_MEDIA,
|
||||
static_duration: 8
|
||||
}.merge(item)
|
||||
end
|
||||
params_whitelist(params).merge({
|
||||
network_id: Vendors::Vistar::VistarSettings.instance.network_id,
|
||||
api_key: "#{@tokens.api_key}",
|
||||
direct_connection: false,
|
||||
display_area: display_area
|
||||
}).to_json
|
||||
end
|
||||
|
||||
def params_whitelist(params)
|
||||
params.slice(
|
||||
:device_id,
|
||||
:venue_id,
|
||||
:display_time,
|
||||
:device_attribute,
|
||||
:name,
|
||||
:display_area,
|
||||
:id,
|
||||
:width,
|
||||
:height,
|
||||
:allow_audio,
|
||||
:supported_media,
|
||||
:min_duration,
|
||||
:max_duration,
|
||||
:order_id,
|
||||
:max_file_size_bytes,
|
||||
:static_duration,
|
||||
:latitude,
|
||||
:longitude
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
37
app/services/vendors/vistar/vistar_fetch_schedule.rb
vendored
Normal file
37
app/services/vendors/vistar/vistar_fetch_schedule.rb
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
module Vendors
|
||||
module Vistar
|
||||
class VistarFetchSchedule
|
||||
def initialize(tokens)
|
||||
@tokens = tokens
|
||||
end
|
||||
|
||||
def call(params)
|
||||
fetch = fetch_ad(params)
|
||||
return nil unless fetch && fetch[:advertisement]
|
||||
|
||||
ad = fetch[:advertisement][0]
|
||||
{
|
||||
contents: [
|
||||
{
|
||||
name: "vistar_asset_#{ad[:asset_id]}",
|
||||
url: ad[:asset_url]
|
||||
}
|
||||
],
|
||||
startTime: Time.at(ad[:display_time]).to_datetime,
|
||||
items: [
|
||||
{
|
||||
contentIndex: 0,
|
||||
duration: "#{ad[:length_in_seconds]}s",
|
||||
pop_url: ad[:proof_of_play_url]
|
||||
}
|
||||
]
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
def fetch_ad(params)
|
||||
Vendors::Vistar::VistarFetchAd.new(@tokens).call(params)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
20
app/services/vendors/vistar/vistar_settings.rb
vendored
Normal file
20
app/services/vendors/vistar/vistar_settings.rb
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Vendors
|
||||
module Vistar
|
||||
class VistarSettings
|
||||
include Singleton
|
||||
|
||||
def vistar_url(path)
|
||||
URI::join(
|
||||
AppConfig.get_mandatory('vendors.vistar.base_url'),
|
||||
path
|
||||
)
|
||||
end
|
||||
|
||||
def network_id
|
||||
AppConfig.get_mandatory('vendors.vistar.network_id')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
15
app/services/vendors/vistar/vistar_tokens.rb
vendored
Normal file
15
app/services/vendors/vistar/vistar_tokens.rb
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../log/loggable'
|
||||
|
||||
module Vendors
|
||||
module Vistar
|
||||
class VistarTokens
|
||||
include Singleton
|
||||
|
||||
def api_key
|
||||
AppConfig.get_mandatory 'vendors.vistar.api_key'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
35
app/services/vendors/vistar/vistar_transform_schedule.rb
vendored
Normal file
35
app/services/vendors/vistar/vistar_transform_schedule.rb
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative '../../log/loggable'
|
||||
require_relative '../../schedule_pipeline/models/schedule'
|
||||
require_relative '../../schedule_pipeline/models/schedule_item'
|
||||
require_relative '../errors/schedule_transform_error'
|
||||
|
||||
module Vendors
|
||||
module Vistar
|
||||
class VistarTransformSchedule
|
||||
include Log::Loggable
|
||||
|
||||
def call(vendor, player, schedule, content_map)
|
||||
logger.debug("Vistar schedule transform for vendor #{vendor}, player #{player}")
|
||||
start_time = schedule[:startTime]
|
||||
items = schedule[:items].collect do |item|
|
||||
SchedulePipeline::Models::ScheduleItem.new(
|
||||
item[:duration],
|
||||
content_map[item[:contentIndex] || 0][:id],
|
||||
item[:pop_url]
|
||||
)
|
||||
end
|
||||
raise Vendors::Errors::ScheduleTransformError, 'Schedule without a start time' if start_time.nil?
|
||||
|
||||
SchedulePipeline::Models::Schedule.new(
|
||||
"Vistar schedule for player #{player}",
|
||||
vendor,
|
||||
player,
|
||||
start_time,
|
||||
items
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user