module W3DHubLauncher class W3DHubApi API_TIMEOUT = 30 # seconds API_CONNECT_TIMEOUT = 10 # seconds PRIMARY_W3DHUB_API_ENDPOINT = "https://secure.w3dhub.com".freeze ALTERNATIVE_W3DHUB_API_ENDPOINT = "https://backend.w3d.cyberarm.dev".freeze attr_reader :applications def initialize @access_token = nil @applications = [] @http_clients = {} end def headers(form_encoded: false, range: nil) array = [ ["user-agent", W3DHubLauncher::USER_AGENT], ["accept", "application/json"], ] array << ["content-type", "application/x-www-form-urlencoded"] if form_encoded array << ["authorization", "Bearer #{@access_token}"] if @access_token array << ["range", "bytes=#{range}-"] if range # pp array array end # return raw response to requester def fetch(url, method: :get, body: nil, headers: headers()) result = CyberarmEngine::Result.new Sync do |task| task.with_timeout(API_TIMEOUT) do Async::HTTP::Internet.send(method, url, headers, body) do |response| pp [method, url, headers, body, response] if response.success? result.data = response.read else result.error = true end end rescue StandardError => e result.error = e rescue Async::TimeoutError => e result.error = e end result end result end # write response to file, periodically reporting progress to requester def download(url, path:, method: :get, body: nil, headers: headers(), &block) result = CyberarmEngine::Result.new Sync do |task| Async::HTTP::Internet.send(method, url, headers, body) do |response| if response.success? content_length = response.headers["content-length"] || 0 total_downloaded_bytes = 0 range = headers.find { |key, value| key == "range" }&.last&.split("=")&.last&.split("-")&.first File.open(path, range ? "r+b" : "wb") do |file| file.pos = Integer(range) if range response.each do |chunk| file.write(chunk) downloaded_bytes = chunk.length total_downloaded_bytes += downloaded_bytes block&.call(downloaded_bytes, total_downloaded_bytes, content_length) end end result.data = true end rescue StandardError => e result.error = e rescue Async::TimeoutError result.error = e end end result end def user_login() result = CyberarmEngine::Result.new end def refresh_user_login() result = CyberarmEngine::Result.new end def fetch_user_details() result = CyberarmEngine::Result.new end def fetch_applications result = CyberarmEngine::Result.new # If we're not signed in, then the primary backend will try to redirect us to the alternate backend. So skip it if we're not signed in. primary_result = @access_token ? fetch("#{PRIMARY_W3DHUB_API_ENDPOINT}/apis/launcher/1/get-applications") : CyberarmEngine::Result.new(error: true) alternate_result = fetch("#{ALTERNATIVE_W3DHUB_API_ENDPOINT}/apis/launcher/1/get-applications") single_source = false # We've failed to retrieve data if primary_result.error? && alternate_result.error? return result # We've only gotten data back from the primary backend elsif primary_result.okay? && alternate_result.error? result.data = primary_result.data single_source = true # We've only gotten data back from the alternate backend elsif primary_result.error? && alternate_result.okay? result.data = alternate_result.data single_source = true end unless single_source puts "FIXME: merge applications source" # We've gotten data back from both backends, merge them. # pp [primary_result, alternate_result] # FIXME: Merge primary and alternate results end @applications = JSON.parse(result.data)["applications"]&.map { |app| W3DHubLauncher::Worker::Api::Application.new(app) } || [] result end def fetch_news(category) fetch("#{PRIMARY_W3DHUB_API_ENDPOINT}/apis/w3dhub/1/get-news", method: :post, body: "data={\"category\":\"#{category}\"}", headers: headers(form_encoded: true)) end def fetch_events(category) fetch("#{PRIMARY_W3DHUB_API_ENDPOINT}/apis/w3dhub/1/get-server-events", method: :post, body: "data={\"serverPath\":\"#{category}\"}", headers: headers(form_encoded: true)) end def fetch_test_events(category) fetch("#{PRIMARY_W3DHUB_API_ENDPOINT}/apis/w3dhub/1/get-testing-times") end def fetch_manifest() result = CyberarmEngine::Result.new end def fetch_package_details(packages) body = URI.encode_www_form("data": JSON.dump({ packages: packages })) fetch("#{@access_token ? PRIMARY_W3DHUB_API_ENDPOINT : ALTERNATIVE_W3DHUB_API_ENDPOINT}/apis/launcher/1/get-package-details", method: :post, body: body, headers: headers(form_encoded: true)) end def download_package() download() end end end