mirror of
https://github.com/cyberarm/w3d_hub_linux_launcher.git
synced 2025-12-16 17:22:35 +00:00
104 lines
3.0 KiB
Ruby
104 lines
3.0 KiB
Ruby
class W3DHub
|
|
class Cache
|
|
def self.path(uri)
|
|
ext = File.basename(uri).split(".").last
|
|
|
|
"#{CACHE_PATH}/#{Digest::SHA2.hexdigest(uri)}.#{ext}"
|
|
end
|
|
|
|
# Fetch a generic uri
|
|
def self.fetch(internet, uri, force_fetch = false)
|
|
path = path(uri)
|
|
|
|
if !force_fetch && File.exist?(path)
|
|
path
|
|
else
|
|
response = internet.get(uri, W3DHub::Api::DEFAULT_HEADERS)
|
|
|
|
if response.success?
|
|
response.save(path, "wb")
|
|
|
|
return path
|
|
end
|
|
|
|
false
|
|
end
|
|
end
|
|
|
|
def self.create_directories(path, is_directory = false)
|
|
target_directory = is_directory ? path : File.dirname(path)
|
|
|
|
FileUtils.mkdir_p(target_directory) unless Dir.exist?(target_directory)
|
|
end
|
|
|
|
def self.package_path(category, subcategory, name, version)
|
|
package_cache_dir = Store.settings[:package_cache_dir]
|
|
|
|
"#{package_cache_dir}/#{category}/#{subcategory}/#{version}/#{name}.package"
|
|
end
|
|
|
|
def self.install_path(application, channel)
|
|
app_install_dir = Store.settings[:app_install_dir]
|
|
|
|
"#{app_install_dir}/#{application.category}/#{application.id}/#{channel.id}"
|
|
end
|
|
|
|
# Download a W3D Hub package
|
|
def self.fetch_package(internet, package, block)
|
|
path = package_path(package.category, package.subcategory, package.name, package.version)
|
|
start_from_bytes = package.custom_partially_valid_at_bytes
|
|
|
|
puts " Start from bytes: #{start_from_bytes}"
|
|
|
|
create_directories(path)
|
|
|
|
offset = start_from_bytes
|
|
parts = []
|
|
chunk_size = 4_000_000
|
|
workers = 4
|
|
|
|
file = File.open(path, offset.positive? ? "r+b" : "wb")
|
|
|
|
amount_written = 0
|
|
|
|
while (offset < package.size)
|
|
byte_range_start = offset
|
|
byte_range_end = [offset + chunk_size, package.size].min
|
|
parts << (byte_range_start...byte_range_end)
|
|
|
|
offset += chunk_size
|
|
end
|
|
|
|
semaphore = Async::Semaphore.new(workers)
|
|
barrier = Async::Barrier.new(parent: semaphore)
|
|
|
|
while !parts.empty?
|
|
barrier.async do
|
|
part = parts.shift
|
|
|
|
range_header = [["range", "bytes=#{part.min}-#{part.max}"]]
|
|
|
|
body = "data=#{JSON.dump({ category: package.category, subcategory: package.subcategory, name: package.name, version: package.version })}"
|
|
response = internet.post("#{Api::ENDPOINT}/apis/launcher/1/get-package", W3DHub::Api::FORM_ENCODED_HEADERS + range_header, body)
|
|
|
|
if response.success?
|
|
chunk = response.read
|
|
written = file.pwrite(chunk, part.min)
|
|
|
|
amount_written += written
|
|
remaining_bytes = package.size - amount_written
|
|
total_bytes = package.size
|
|
|
|
block.call(chunk, remaining_bytes, total_bytes)
|
|
# puts " Remaining: #{((remaining_bytes.to_f / total_bytes) * 100.0).round}% (#{W3DHub::format_size(total_bytes - remaining_bytes)} / #{W3DHub::format_size(total_bytes)})"
|
|
end
|
|
end
|
|
|
|
barrier.wait
|
|
end
|
|
ensure
|
|
file&.close
|
|
end
|
|
end
|
|
end
|