Update SwfAsset#image_url
to use all the latest tech
I think there's no call sites for these anymore, so now I can start repurposing these methods for the new API endpoints I'm planning! :3 Now, `SwfAsset#image_url` approximately matches Impress 2020 logic: use the thumbnail PNG from the manifest if one exists, or the Impress 2020 converter for canvas movies, or the old AWS copy generated by gnash if necessary, or return nil.
This commit is contained in:
parent
600cb6b2ea
commit
e0b5382c3f
2 changed files with 89 additions and 36 deletions
|
@ -38,7 +38,7 @@ class AltStyle < ApplicationRecord
|
||||||
swf_asset = swf_assets.first
|
swf_asset = swf_assets.first
|
||||||
return nil if swf_asset.nil?
|
return nil if swf_asset.nil?
|
||||||
|
|
||||||
swf_asset.html5_image_url
|
swf_asset.image_url
|
||||||
end
|
end
|
||||||
|
|
||||||
def biology=(biology)
|
def biology=(biology)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
require 'addressable/template'
|
||||||
require 'async'
|
require 'async'
|
||||||
require 'async/barrier'
|
require 'async/barrier'
|
||||||
require 'async/semaphore'
|
require 'async/semaphore'
|
||||||
|
@ -10,12 +11,6 @@ class SwfAsset < ApplicationRecord
|
||||||
|
|
||||||
# Used in `item_is_body_specific?`. (TODO: Could we refactor this out?)
|
# Used in `item_is_body_specific?`. (TODO: Could we refactor this out?)
|
||||||
attr_accessor :item
|
attr_accessor :item
|
||||||
|
|
||||||
IMAGE_SIZES = {
|
|
||||||
:small => [150, 150],
|
|
||||||
:medium => [300, 300],
|
|
||||||
:large => [600, 600]
|
|
||||||
}
|
|
||||||
|
|
||||||
belongs_to :zone
|
belongs_to :zone
|
||||||
has_many :parent_swf_asset_relationships
|
has_many :parent_swf_asset_relationships
|
||||||
|
@ -29,28 +24,14 @@ class SwfAsset < ApplicationRecord
|
||||||
scope :biology_assets, -> { where(:type => PetState::SwfAssetType) }
|
scope :biology_assets, -> { where(:type => PetState::SwfAssetType) }
|
||||||
scope :object_assets, -> { where(:type => Item::SwfAssetType) }
|
scope :object_assets, -> { where(:type => Item::SwfAssetType) }
|
||||||
|
|
||||||
PARTITION_COUNT = 3
|
CANVAS_MOVIE_IMAGE_URL_TEMPLATE = Addressable::Template.new(
|
||||||
PARTITION_DIGITS = 3
|
Rails.configuration.impress_2020_origin +
|
||||||
PARTITION_ID_LENGTH = PARTITION_COUNT * PARTITION_DIGITS
|
"/api/assetImage{?libraryUrl,size}"
|
||||||
def partition_path
|
)
|
||||||
(remote_id / 10**PARTITION_DIGITS).to_s.rjust(PARTITION_ID_LENGTH, '0').tap do |id_str|
|
LEGACY_IMAGE_URL_TEMPLATE = Addressable::Template.new(
|
||||||
PARTITION_COUNT.times do |n|
|
"https://aws.impress-asset-images.openneo.net/{type}" +
|
||||||
id_str.insert(PARTITION_ID_LENGTH - (n * PARTITION_DIGITS), '/')
|
"/{id1}/{id2}/{id3}/{id}/{size}x{size}.png?v2-{time}"
|
||||||
end
|
)
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def image_version
|
|
||||||
converted_at.to_i
|
|
||||||
end
|
|
||||||
|
|
||||||
def image_url(size=IMAGE_SIZES[:large])
|
|
||||||
size_key = size.join('x')
|
|
||||||
image_dir = "#{self['type']}/#{partition_path}#{self.remote_id}"
|
|
||||||
|
|
||||||
"https://impress-asset-images.openneo.net/#{image_dir}/#{size_key}.png?" +
|
|
||||||
"#{image_version}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def as_json(options={})
|
def as_json(options={})
|
||||||
super({
|
super({
|
||||||
|
@ -63,13 +44,14 @@ class SwfAsset < ApplicationRecord
|
||||||
{
|
{
|
||||||
swf: url,
|
swf: url,
|
||||||
png: image_url,
|
png: image_url,
|
||||||
|
svg: manifest_asset_urls[:svg],
|
||||||
manifest: manifest_url,
|
manifest: manifest_url,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def manifest
|
def manifest
|
||||||
raise "manifest_url is blank" if manifest_url.blank?
|
raise "manifest_url is blank" if manifest_url.blank?
|
||||||
NeopetsMediaArchive.load_json(manifest_url)
|
@manifest ||= NeopetsMediaArchive.load_json(manifest_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
def preload_manifest
|
def preload_manifest
|
||||||
|
@ -82,18 +64,89 @@ class SwfAsset < ApplicationRecord
|
||||||
return {} if manifest_url.nil?
|
return {} if manifest_url.nil?
|
||||||
|
|
||||||
begin
|
begin
|
||||||
# Organize the asset URLs by file extension, grab the ones we want, and
|
# Organize the asset URLs by file extension, convert them from paths to
|
||||||
# convert them from paths to full URLs.
|
# full URLs, and grab the ones we want.
|
||||||
manifest["cpmanifest"]["assets"][0]["asset_data"].
|
assets_by_ext = manifest["cpmanifest"]["assets"][0]["asset_data"].
|
||||||
to_h { |a| [a["file_ext"].to_sym, a] }.
|
group_by { |a| a["file_ext"].to_sym }.
|
||||||
slice(:png, :svg, :js)
|
transform_values do |assets|
|
||||||
.transform_values { |a| (MANIFEST_BASE_URL + a["url"]).to_s }
|
assets.map { |a| (MANIFEST_BASE_URL + a["url"]).to_s }
|
||||||
|
end
|
||||||
|
|
||||||
|
if assets_by_ext[:js].present?
|
||||||
|
# If a JS asset is present, assume any other assets are supporting
|
||||||
|
# assets, and skip them. (e.g. if there's a PNG, it's likely to be an
|
||||||
|
# "atlas" file used in the animation, rather than a thumbnail.)
|
||||||
|
#
|
||||||
|
# NOTE: We take the last one, because sometimes there are multiple JS
|
||||||
|
# assets in the same manifest, and earlier ones are broken and later
|
||||||
|
# ones are fixed. I don't know the logic exactly, but that's what we've
|
||||||
|
# seen!
|
||||||
|
{ js: assets_by_ext[:js].last }
|
||||||
|
else
|
||||||
|
# Otherwise, return the last PNG and the last SVG, arbitrarily.
|
||||||
|
# (There's probably only one of each! I'm just going by the same logic
|
||||||
|
# we've seen in the JS library case, that later entries are more likely
|
||||||
|
# to be correct.)
|
||||||
|
{ png: assets_by_ext[:png].last, svg: assets_by_ext[:svg].last }
|
||||||
|
end
|
||||||
rescue StandardError => error
|
rescue StandardError => error
|
||||||
Rails.logger.error "Could not read URLs from manifest: #{error.full_message}"
|
Rails.logger.error "Could not read URLs from manifest: #{error.full_message}"
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def image_url
|
||||||
|
# Use the PNG image from the manifest, if one exists.
|
||||||
|
return manifest_asset_urls[:png] if manifest_asset_urls[:png].present?
|
||||||
|
|
||||||
|
# Or, if this is a canvas movie, let Impress 2020 generate a PNG for us.
|
||||||
|
return canvas_movie_image_url if manifest_asset_urls[:js].present?
|
||||||
|
|
||||||
|
# Otherwise, if we don't have the manifest or it doesn't have the files we
|
||||||
|
# need, fall back to the Classic DTI image storage, which was generated
|
||||||
|
# from the SWFs via an old version of gnash (or sometimes manually
|
||||||
|
# overridden). It's less accurate, but well-tested to generally work okay,
|
||||||
|
# and it's the only image we have for assets not yet converted to HTML5.
|
||||||
|
#
|
||||||
|
# NOTE: We've stopped generating these images for new assets! This is
|
||||||
|
# mainly for old assets not yet converted to HTML5.
|
||||||
|
#
|
||||||
|
# NOTE: If you're modeling from a fresh development database, `has_image?`
|
||||||
|
# might be false even though we *do* have a saved copy of the image
|
||||||
|
# available in production. But if you're using the public modeling
|
||||||
|
# data exported from production, then this check should be fine!
|
||||||
|
#
|
||||||
|
# TODO: Rename `has_image?` to `has_legacy_image?`.
|
||||||
|
return legacy_image_url if has_image?
|
||||||
|
|
||||||
|
# Otherwise, there's no image URL.
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def canvas_movie_image_url
|
||||||
|
return nil unless manifest_asset_urls[:js]
|
||||||
|
|
||||||
|
CANVAS_MOVIE_IMAGE_URL_TEMPLATE.expand(
|
||||||
|
libraryUrl: manifest_asset_urls[:js],
|
||||||
|
size: 600,
|
||||||
|
).to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def legacy_image_url
|
||||||
|
return nil unless has_image?
|
||||||
|
|
||||||
|
padded_id = remote_id.to_s.rjust(12, "0")
|
||||||
|
LEGACY_IMAGE_URL_TEMPLATE.expand(
|
||||||
|
type: type,
|
||||||
|
id1: padded_id[0...3],
|
||||||
|
id2: padded_id[3...6],
|
||||||
|
id3: padded_id[6...9],
|
||||||
|
id: remote_id,
|
||||||
|
size: "600",
|
||||||
|
time: converted_at.to_i,
|
||||||
|
).to_s
|
||||||
|
end
|
||||||
|
|
||||||
def html5_image_url
|
def html5_image_url
|
||||||
manifest_asset_urls[:png]
|
manifest_asset_urls[:png]
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue