diff --git a/lib/granblue/downloaders/base_downloader.rb b/lib/granblue/downloaders/base_downloader.rb new file mode 100644 index 0000000..a4a85de --- /dev/null +++ b/lib/granblue/downloaders/base_downloader.rb @@ -0,0 +1,145 @@ +# frozen_string_literal: true + +module Granblue + module Downloader + class BaseDownloader + SIZES = %w[main grid square].freeze + + def initialize(id, test_mode: false, verbose: false, storage: :both) + @id = id + @base_url = base_url + @test_mode = test_mode + @verbose = verbose + @storage = storage + @aws_service = AwsService.new + ensure_directories_exist unless @test_mode + end + + def download + log_info "#{object_type.capitalize} #{@id}" + return if @test_mode + + SIZES.each do |size| + path = download_path(size) + url = build_url(size) + process_download(url, size, path) + end + end + + private + + def process_download(url, size, path) + filename = File.basename(url) + s3_key = build_s3_key(size, filename) + download_uri = "#{path}/#{filename}" + + should_process = should_download?(download_uri, s3_key) + return unless should_process + + log_info "\tDownloading #{size}\t#{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 + + def download_to_local(url, download_uri) + download = URI.parse(url).open + IO.copy_stream(download, download_uri) + end + + def stream_to_s3(url, s3_key) + return if @aws_service.file_exists?(s3_key) + + URI.parse(url).open do |file| + @aws_service.upload_stream(file, s3_key) + end + end + + def download_to_both(url, download_uri, s3_key) + download = URI.parse(url).open + + # Write to local file + IO.copy_stream(download, download_uri) + + # Reset file pointer for S3 upload + download.rewind + + # Upload to S3 if it doesn't exist + unless @aws_service.file_exists?(s3_key) + @aws_service.upload_stream(download, s3_key) + end + end + + def should_download?(local_path, s3_key) + case @storage + when :local + !File.exist?(local_path) + when :s3 + !@aws_service.file_exists?(s3_key) + when :both + !File.exist?(local_path) || !@aws_service.file_exists?(s3_key) + end + end + + def ensure_directories_exist + return unless store_locally? + + SIZES.each do |size| + FileUtils.mkdir_p(download_path(size)) + end + end + + def store_locally? + %i[local both].include?(@storage) + end + + def download_path(size) + "#{Rails.root}/download/#{object_type}-#{size}" + end + + def build_s3_key(size, filename) + "#{object_type}-#{size}/#{filename}" + end + + def log_info(message) + puts message if @verbose + end + + def download_elemental_image(url, size, path, filename) + return if @test_mode + + filepath = "#{path}/#{filename}" + download = URI.parse(url).open + log_info "\tDownloading #{size}\t#{url}..." + IO.copy_stream(download, filepath) + rescue OpenURI::HTTPError + log_info "\t404 returned\t#{url}" + end + + def object_type + raise NotImplementedError, 'Subclasses must define object_type' + end + + def base_url + raise NotImplementedError, 'Subclasses must define base_url' + end + + def directory_for_size(size) + raise NotImplementedError, 'Subclasses must define directory_for_size' + end + + def build_url(size) + directory = directory_for_size(size) + "#{@base_url}/#{directory}/#{@id}.jpg" + end + end + end +end diff --git a/lib/granblue/downloaders/character_downloader.rb b/lib/granblue/downloaders/character_downloader.rb new file mode 100644 index 0000000..34aa8a6 --- /dev/null +++ b/lib/granblue/downloaders/character_downloader.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Granblue + module Downloader + class CharacterDownloader < BaseDownloader + private + + def object_type + 'character' + end + + def base_url + 'http://gbf.game-a.mbga.jp/assets/img/sp/assets/npc' + end + + def directory_for_size(size) + case size.to_s + when 'main' then 'f' + when 'grid' then 'm' + when 'square' then 's' + end + end + end + end +end diff --git a/lib/granblue/downloaders/elemental_weapon_downloader.rb b/lib/granblue/downloaders/elemental_weapon_downloader.rb new file mode 100644 index 0000000..9ad5e79 --- /dev/null +++ b/lib/granblue/downloaders/elemental_weapon_downloader.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require_relative 'weapon_downloader' + +module Granblue + module Downloader + class ElementalWeaponDownloader < WeaponDownloader + SUFFIXES = [2, 3, 4, 1, 6, 5].freeze + + def initialize(id_base) + @id_base = id_base.to_i + end + + def download + (1..6).each do |i| + id = @id_base + (i - 1) * 100 + suffix = SUFFIXES[i - 1] + + puts "Elemental Weapon #{id}_#{suffix}" + SIZES.each do |size| + path = download_path(size) + url = build_url_for_id(id, size) + filename = "#{id}_#{suffix}.jpg" + download_elemental_image(url, size, path, filename) + end + + progress_reporter(count: i, total: 6, result: "Elemental Weapon #{id}_#{suffix}") + end + end + + private + + def build_url_for_id(id, size) + directory = directory_for_size(size) + "#{base_url}/#{directory}/#{id}.jpg" + end + + def progress_reporter(count:, total:, result:, bar_len: 40) + filled_len = (bar_len * count / total).round + status = result + percents = (100.0 * count / total).round(1) + bar = '=' * filled_len + '-' * (bar_len - filled_len) + print("\n[#{bar}] #{percents}% ...#{' ' * 14}#{status}\n") + end + end + end +end diff --git a/lib/granblue/downloaders/summon_downloader.rb b/lib/granblue/downloaders/summon_downloader.rb new file mode 100644 index 0000000..2d9ba8d --- /dev/null +++ b/lib/granblue/downloaders/summon_downloader.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Granblue + module Downloader + class SummonDownloader < BaseDownloader + private + + def object_type + 'summon' + end + + def base_url + 'http://gbf.game-a.mbga.jp/assets/img/sp/assets/summon' + end + + def directory_for_size(size) + case size.to_s + when 'main' then 'party_main' + when 'grid' then 'party_sub' + when 'square' then 's' + end + end + end + end +end diff --git a/lib/granblue/downloaders/weapon_downloader.rb b/lib/granblue/downloaders/weapon_downloader.rb new file mode 100644 index 0000000..38f158f --- /dev/null +++ b/lib/granblue/downloaders/weapon_downloader.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Granblue + module Downloader + class WeaponDownloader < BaseDownloader + private + + def object_type + 'weapon' + end + + def base_url + 'http://gbf.game-a.mbga.jp/assets/img/sp/assets/weapon' + end + + def directory_for_size(size) + case size.to_s + when 'main' then 'ls' + when 'grid' then 'm' + when 'square' then 's' + end + end + end + end +end