# frozen_string_literal: true require 'net/http' require 'uri' require 'json' require_relative 'open_struct' module SpaceTraders class Client DEFAULT_BASE_URL = ENV['SPACETRADERS_DEFAULT_BASE_URL'] || 'https://api.spacetraders.io/v2' def self.register(name:, faction: 'COSMIC', base_url: DEFAULT_BASE_URL) Log.debug("register new account #{name} faction #{faction}") res = Net::HTTP.post( URI("#{base_url}/register"), { symbol: name, faction: faction }.to_json, 'Content-Type' => 'application/json' ) token = JSON.parse(res.body).dig('data', 'token') new(token: token, base_url: base_url) end def self.load_from_env new(token: ENV['SPACETRADERS_TOKEN'], base_url: DEFAULT_BASE_URL) end attr_accessor :token, :base_url # @param parse : if false, get/post will return the raw response, not the parsed body def initialize(token:, base_url: DEFAULT_BASE_URL, parse: true) raise 'Invalid Nil token' if token.nil? @parse = parse @token = token @base_url = base_url end def parse? @parse end private def parse!(res) @res = res @body = JSON.parse(res.body) OpenStruct.deep_load @body["data"] end def meta @body["meta"] if @body end def data(parse: true) if @body data = @body["data"] data = OpenStruct.deep_load(data) if parse data end end def post(endpoint:, body:) Log.debug("post #{endpoint} with body #{body}") res = Net::HTTP.post( URI("#{base_url}/#{endpoint}"), body ? body.to_json : nil, 'Authorization' => "Bearer #{@token}", 'Content-Type' => 'application/json' ) if block_given? yield JSON.parse(res.body), res elsif parse? parse!(res) else res end end def get(endpoint:) Log.debug("get #{endpoint}") res = Net::HTTP.get_response( URI("#{@base_url}/#{endpoint}"), 'Authorization' => "Bearer #{@token}", 'Content-Type' => 'application/json' ) if block_given? yield JSON.parse(res.body), res elsif parse? parse!(res) else res end end end require 'endpoint' class Client def self.add_endpoint(name) Log.debug("add_endpoint #{name}") define_method(name.to_s.downcase) do variable_name = "@memoize_#{name}" variable = nil # variable = instance_variable_get(variable_name) if variable.nil? endpoint = SpaceTraders::Endpoint::const_get(name.to_s.camelcase).new(client: self) instance_variable_set(variable_name, endpoint) endpoint else variable end end end def self.add_endpoints(*names) names.each { add_endpoint(_1) } end add_endpoints :agents, :contracts, :ships, :systems end end