64 lines
1.5 KiB
Ruby
64 lines
1.5 KiB
Ruby
|
|
# frozen_string_literal: true
|
||
|
|
|
||
|
|
require "net/http"
|
||
|
|
require "oj"
|
||
|
|
|
||
|
|
require "provider/adapters/adapter"
|
||
|
|
|
||
|
|
class Provider
|
||
|
|
module Adapters
|
||
|
|
# Central Bank of Uzbekistan. Publishes daily rates for 20+ currencies against UZS.
|
||
|
|
# Per-day JSON endpoint at https://cbu.uz/en/arkhiv-kursov-valyut/json/all/{YYYY-MM-DD}/
|
||
|
|
class CBU < Adapter
|
||
|
|
URL = "https://cbu.uz/en/arkhiv-kursov-valyut/json/all/"
|
||
|
|
|
||
|
|
class << self
|
||
|
|
def backfill_range = 30
|
||
|
|
end
|
||
|
|
|
||
|
|
def fetch(after: nil, upto: nil)
|
||
|
|
end_date = upto || Date.today
|
||
|
|
dataset = []
|
||
|
|
|
||
|
|
first = true
|
||
|
|
(after..end_date).each do |date|
|
||
|
|
next if date.saturday? || date.sunday?
|
||
|
|
|
||
|
|
sleep(0.2) unless first
|
||
|
|
first = false
|
||
|
|
|
||
|
|
dataset.concat(fetch_date(date))
|
||
|
|
end
|
||
|
|
|
||
|
|
dataset
|
||
|
|
end
|
||
|
|
|
||
|
|
def parse(json)
|
||
|
|
data = json.is_a?(String) ? Oj.load(json, mode: :strict) : json
|
||
|
|
return [] unless data.is_a?(Array)
|
||
|
|
|
||
|
|
data.filter_map do |row|
|
||
|
|
code = row["Ccy"]
|
||
|
|
next unless code&.match?(/\A[A-Z]{3}\z/)
|
||
|
|
|
||
|
|
nominal = Integer(row["Nominal"])
|
||
|
|
rate = Float(row["Rate"])
|
||
|
|
next if rate.zero? || nominal.zero?
|
||
|
|
|
||
|
|
date = Date.strptime(row["Date"], "%d.%m.%Y")
|
||
|
|
|
||
|
|
{ date:, base: code, quote: "UZS", rate: rate / nominal }
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
private
|
||
|
|
|
||
|
|
def fetch_date(date)
|
||
|
|
url = URI("#{URL}#{date.strftime("%Y-%m-%d")}/")
|
||
|
|
response = Net::HTTP.get(url)
|
||
|
|
parse(response)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|