171 lines
No EOL
6.1 KiB
Ruby
171 lines
No EOL
6.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Granblue
|
|
module Downloaders
|
|
# Downloads job image assets from the game server in different sizes and variants.
|
|
# Handles job-specific images including wide and zoom formats with gender variants.
|
|
#
|
|
# @example Download images for a specific job
|
|
# downloader = JobDownloader.new("100401", storage: :both)
|
|
# downloader.download
|
|
#
|
|
# @note Job images come in wide and zoom formats only
|
|
# @note Zoom images have male (0) and female (1) variants
|
|
class JobDownloader < BaseDownloader
|
|
# Override SIZES to include only 'wide' and 'zoom' for job images
|
|
SIZES = %w[wide zoom].freeze
|
|
|
|
# Downloads images for all variants of a job.
|
|
# Overrides {BaseDownloader#download} to handle job-specific variants.
|
|
#
|
|
# @param selected_size [String] The size to download. If nil, downloads all sizes.
|
|
# @return [void]
|
|
# @note Skips download if job is not found in database
|
|
# @note Downloads gender variants for zoom images
|
|
def download(selected_size = nil)
|
|
job = Job.find_by(granblue_id: @id)
|
|
return unless job
|
|
|
|
download_variants(job, selected_size)
|
|
end
|
|
|
|
private
|
|
|
|
# Downloads all variants of a job's images
|
|
#
|
|
# @param job [Job] Job model instance to download images for
|
|
# @param selected_size [String] The size to download. If nil, downloads all sizes.
|
|
# @return [void]
|
|
def download_variants(job, selected_size = nil)
|
|
log_info "-> #{@id}" if @verbose
|
|
return if @test_mode
|
|
|
|
sizes = selected_size ? [selected_size] : SIZES
|
|
|
|
sizes.each_with_index do |size, index|
|
|
case size
|
|
when 'zoom'
|
|
# Download both male and female variants for zoom images
|
|
download_zoom_variants(index == sizes.size - 1)
|
|
when 'wide'
|
|
# Download both male and female variants for wide images
|
|
download_wide_variants(index == sizes.size - 1)
|
|
end
|
|
end
|
|
end
|
|
|
|
# Downloads zoom variants for both genders
|
|
#
|
|
# @param is_last [Boolean] Whether zoom is the last size being processed
|
|
# @return [void]
|
|
def download_zoom_variants(is_last)
|
|
path = download_path('zoom')
|
|
|
|
# Download male variant (_a suffix, 0 in URL)
|
|
url_male = build_zoom_url(0)
|
|
filename_male = "#{@id}_a.png"
|
|
download_variant(url_male, 'zoom', path, filename_male, 'zoom-male', last: false)
|
|
|
|
# Download female variant (_b suffix, 1 in URL)
|
|
url_female = build_zoom_url(1)
|
|
filename_female = "#{@id}_b.png"
|
|
download_variant(url_female, 'zoom', path, filename_female, 'zoom-female', last: is_last)
|
|
end
|
|
|
|
# Downloads a specific variant
|
|
#
|
|
# @param url [String] URL to download from
|
|
# @param size [String] Size category for S3 key
|
|
# @param path [String] Local path for download
|
|
# @param filename [String] Filename to save as
|
|
# @param label [String] Label for logging
|
|
# @param last [Boolean] Whether this is the last item being processed
|
|
# @return [void]
|
|
def download_variant(url, size, path, filename, label, last: false)
|
|
s3_key = build_s3_key(size, filename)
|
|
download_uri = "#{path}/#{filename}"
|
|
|
|
should_process = should_download?(download_uri, s3_key)
|
|
return unless should_process
|
|
|
|
prefix = last ? "\t└" : "\t├"
|
|
log_info "#{prefix} #{label}: #{url}..."
|
|
|
|
case @storage
|
|
when :local
|
|
download_to_local(url, download_uri)
|
|
when :s3
|
|
stream_to_s3(url, s3_key)
|
|
when :both
|
|
download_to_both(url, download_uri, s3_key)
|
|
end
|
|
rescue OpenURI::HTTPError
|
|
log_info "\t404 returned\t#{url}"
|
|
end
|
|
|
|
# Builds URL for wide images
|
|
#
|
|
# @param size [String] Image size variant
|
|
# @return [String] Complete URL for downloading the image
|
|
def build_job_url(size)
|
|
case size
|
|
when 'wide'
|
|
# Wide images always download both male and female variants
|
|
nil # Will be handled by download_wide_variants
|
|
when 'zoom'
|
|
nil # Handled by build_zoom_url
|
|
else
|
|
nil
|
|
end
|
|
end
|
|
|
|
# Downloads wide variants for both genders
|
|
#
|
|
# @param is_last [Boolean] Whether wide is the last size being processed
|
|
# @return [void]
|
|
def download_wide_variants(is_last)
|
|
path = download_path('wide')
|
|
|
|
# Download male variant (_a suffix, _01 in URL)
|
|
url_male = "https://prd-game-a3-granbluefantasy.akamaized.net/assets_en/img/sp/assets/leader/m/#{@id}_01.jpg"
|
|
filename_male = "#{@id}_a.jpg"
|
|
download_variant(url_male, 'wide', path, filename_male, 'wide-male', last: false)
|
|
|
|
# Download female variant (_b suffix, _01 in URL - same as male for wide)
|
|
url_female = "https://prd-game-a3-granbluefantasy.akamaized.net/assets_en/img/sp/assets/leader/m/#{@id}_01.jpg"
|
|
filename_female = "#{@id}_b.jpg"
|
|
download_variant(url_female, 'wide', path, filename_female, 'wide-female', last: is_last)
|
|
end
|
|
|
|
# Builds URL for zoom images with gender variant
|
|
#
|
|
# @param gender [Integer] Gender variant (0 for male, 1 for female)
|
|
# @return [String] Complete URL for downloading the zoom image
|
|
def build_zoom_url(gender)
|
|
"https://media.skycompass.io/assets/customizes/jobs/1138x1138/#{@id}_#{gender}.png"
|
|
end
|
|
|
|
|
|
# Gets object type for file paths and storage keys
|
|
# @return [String] Returns "job"
|
|
def object_type
|
|
'job'
|
|
end
|
|
|
|
# Gets base URL for job assets
|
|
# @return [String] Base URL for job images
|
|
def base_url
|
|
'https://prd-game-a-granbluefantasy.akamaized.net/assets_en/img/sp/assets/leader'
|
|
end
|
|
|
|
# Gets directory name for a size variant
|
|
#
|
|
# @param size [String] Image size variant
|
|
# @return [String] Directory name in game asset URL structure
|
|
# @note Jobs only have wide and zoom formats, handled with custom URLs
|
|
def directory_for_size(size)
|
|
nil # Jobs don't use the standard directory structure
|
|
end
|
|
end
|
|
end
|
|
end |