hensei-api/lib/granblue/downloaders/job_downloader.rb

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