EGP_Rates 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/egp_rates/bank.rb +15 -0
- data/lib/egp_rates/cbe.rb +77 -0
- data/lib/egp_rates/nbe.rb +71 -0
- data/lib/egp_rates.rb +14 -0
- data/spec/cassettes/CBE.yml +1598 -0
- data/spec/cassettes/NBE.yml +861 -0
- data/spec/egp_rates/bank_spec.rb +10 -0
- data/spec/egp_rates/cbe_spec.rb +90 -0
- data/spec/egp_rates/nbe_spec.rb +91 -0
- data/spec/egp_rates_spec.rb +3 -0
- data/spec/spec_helper.rb +39 -0
- metadata +209 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 226e463d104ebab0ea975d16d7c26ed424e32bd8
|
4
|
+
data.tar.gz: cb8050bc07da0baaaf33eae5d72beac437eb3265
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 85c46b4e3f81dcb391025a11c385cbf7b6d4d43e41183e35c8dca094d9ab3c3a605bf1abca1660ee6c7272603d286b90dd0633fe1cb2985d9e265cdfb2d652c7
|
7
|
+
data.tar.gz: 08e538c1e7f2daf8f9f82353a84da28aee54245a78a01dd9454407619ba358e3bb2db14688364866cb0ed58a8a5d2f5b46ff00900454f4cb61fbc91b4f07b57a
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module EGPRates
|
3
|
+
# Class Representing the bank to get the data from
|
4
|
+
class Bank
|
5
|
+
attr_reader :sym
|
6
|
+
|
7
|
+
# Abstract method
|
8
|
+
# Subclasses banks define the logic to get the exchange rates hash
|
9
|
+
# it should return [Hash] sell: { SYM: rate, ... } , buy: { SYM: rate, ... }
|
10
|
+
# for the available currencies (represented by :SYM) on the bank pages
|
11
|
+
def exchange_rates
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module EGPRates
|
3
|
+
# Central Bank of Egypt
|
4
|
+
class CBE < EGPRates::Bank
|
5
|
+
def initialize
|
6
|
+
@sym = :CBE
|
7
|
+
@uri = URI.parse('http://www.cbe.org.eg/en/EconomicResearch/Statistics/Pages/ExchangeRatesListing.aspx')
|
8
|
+
end
|
9
|
+
|
10
|
+
# @return [Hash] of exchange rates for selling and buying
|
11
|
+
# {
|
12
|
+
# { sell: { SYM: rate }, { SYM: rate }, ... },
|
13
|
+
# { buy: { SYM: rate }, { SYM: rate }, ... }
|
14
|
+
# }
|
15
|
+
def exchange_rates
|
16
|
+
@exchange_rates ||= parse(raw_exchange_rates)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Send the request to the URL and retrun raw data of the response
|
22
|
+
# @return [Enumerator::Lazy] with the table row in HTML that evaluates to
|
23
|
+
# [
|
24
|
+
# "US Dollar \r\n ", "15.7297", "16.3929",
|
25
|
+
# "Euro \r\n, ", "17.5308", "18.1938",
|
26
|
+
# ...
|
27
|
+
# ]
|
28
|
+
#
|
29
|
+
def raw_exchange_rates
|
30
|
+
response = Net::HTTP.get_response(@uri)
|
31
|
+
fail ResponseError, response.code unless response.is_a? Net::HTTPSuccess
|
32
|
+
table_rows = Oga.parse_html(response.body).css('tbody').last&.children
|
33
|
+
# CBE porvide 9 currencies on the home page
|
34
|
+
fail ResponseError, 'Unknown HTML' unless table_rows&.size == 9
|
35
|
+
table_rows.lazy.map(&:children).map { |cell| cell.map(&:text) }
|
36
|
+
end
|
37
|
+
|
38
|
+
# Convert currency string to ISO symbol
|
39
|
+
# @param currency [String] "US Dollar"
|
40
|
+
# @return [Symbol] :USD ISO currency name
|
41
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
42
|
+
# rubocop:disable Metrics/MethodLength
|
43
|
+
def currency_symbol(currency)
|
44
|
+
case currency
|
45
|
+
when /US/ then :USD
|
46
|
+
when /Euro/ then :EUR
|
47
|
+
when /Sterling/ then :GBP
|
48
|
+
when /Swiss/ then :CHF
|
49
|
+
when /Japanese/ then :JPY
|
50
|
+
when /Saudi/ then :SAR
|
51
|
+
when /Kuwait/ then :KWD
|
52
|
+
when /UAE/ then :AED
|
53
|
+
when /Chinese/ then :CNY
|
54
|
+
else fail ResponseError, "Unknown currency #{currency}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
58
|
+
# rubocop:enable Metrics/MethodLength
|
59
|
+
|
60
|
+
# Parse the #raw_exchange_rates returned in response
|
61
|
+
# @return [Hash] of exchange rates for selling and buying
|
62
|
+
# {
|
63
|
+
# { sell: { SYM: rate }, { SYM: rate }, ... },
|
64
|
+
# { buy: { SYM: rate }, { SYM: rate }, ... }
|
65
|
+
# }
|
66
|
+
def parse(raw_data)
|
67
|
+
raw_data.each_with_object(sell: {}, buy: {}) do |row, result|
|
68
|
+
sell_rate = row[2].to_f
|
69
|
+
buy_rate = row[1].to_f
|
70
|
+
currency = currency_symbol(row[0])
|
71
|
+
|
72
|
+
result[:sell][currency] = sell_rate
|
73
|
+
result[:buy][currency] = buy_rate
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module EGPRates
|
3
|
+
# National Bank of Egypt
|
4
|
+
class NBE < EGPRates::Bank
|
5
|
+
def initialize
|
6
|
+
@sym = :NBE
|
7
|
+
@uri = URI.parse('http://www.nbe.com.eg/en/ExchangeRate.aspx')
|
8
|
+
end
|
9
|
+
|
10
|
+
# @return [Hash] of exchange rates for selling and buying
|
11
|
+
# {
|
12
|
+
# { sell: { SYM: rate }, { SYM: rate }, ... },
|
13
|
+
# { buy: { SYM: rate }, { SYM: rate }, ... }
|
14
|
+
# }
|
15
|
+
def exchange_rates
|
16
|
+
@exchange_rates ||= parse(raw_exchange_rates)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Send the request to the URL and retrun raw data of the response
|
22
|
+
# @return [Enumerator::Lazy] with the table row in HTML that evaluates to
|
23
|
+
# [
|
24
|
+
# "\r\n\t\t",
|
25
|
+
# "US DOLLAR",
|
26
|
+
# "USD ",
|
27
|
+
# "\r\n\t\t\t\t\t\t\t\t\t15.9\r\n\t\t\t\t\t\t\t\t",
|
28
|
+
# "\r\n\t\t\t\t\t\t\t\t\t16.05\r\n\t\t\t\t\t\t\t\t",
|
29
|
+
# "\r\n\t\t\t\t\t\t\t\t\t15.9\r\n\t\t\t\t\t\t\t\t",
|
30
|
+
# "\r\n\t\t\t\t\t\t\t\t\t16.05\r\n\t\t\t\t\t\t\t\t",
|
31
|
+
# "\r\n\t"
|
32
|
+
# ], [
|
33
|
+
# "\r\n\t\t",
|
34
|
+
# "EURO",
|
35
|
+
# "EUR ",
|
36
|
+
# "\r\n\t\t\t\t\t\t\t\t\t17.2213\r\n\t\t\t\t\t\t\t\t",
|
37
|
+
# "\r\n\t\t\t\t\t\t\t\t\t17.5314\r\n\t\t\t\t\t\t\t\t",
|
38
|
+
# "\r\n\t\t\t\t\t\t\t\t\t17.2213\r\n\t\t\t\t\t\t\t\t",
|
39
|
+
# "\r\n\t\t\t\t\t\t\t\t\t17.5314\r\n\t\t\t\t\t\t\t\t",
|
40
|
+
# "\r\n\t"
|
41
|
+
# ], [
|
42
|
+
# ...
|
43
|
+
# ]
|
44
|
+
def raw_exchange_rates
|
45
|
+
response = Net::HTTP.get_response(@uri)
|
46
|
+
fail ResponseError, response.code unless response.is_a? Net::HTTPSuccess
|
47
|
+
table_rows = Oga.parse_html(response.body).css('#idts_content tr')
|
48
|
+
# NBE provide 17 currencies only
|
49
|
+
fail ResponseError, 'Unknown HTML' unless table_rows&.size == 18
|
50
|
+
# Drop 1 remove the table headers
|
51
|
+
table_rows.lazy.drop(1).map(&:children).map { |cell| cell.map(&:text) }
|
52
|
+
end
|
53
|
+
|
54
|
+
# Parse the #raw_exchange_rates returned in response
|
55
|
+
# @return [Hash] of exchange rates for selling and buying
|
56
|
+
# {
|
57
|
+
# { sell: { SYM: rate }, { SYM: rate }, ... },
|
58
|
+
# { buy: { SYM: rate }, { SYM: rate }, ... }
|
59
|
+
# }
|
60
|
+
def parse(raw_data)
|
61
|
+
raw_data.each_with_object(sell: {}, buy: {}) do |row, result|
|
62
|
+
sell_rate = row[4].strip.to_f
|
63
|
+
buy_rate = row[3].strip.to_f
|
64
|
+
currency = row[2].strip.to_sym
|
65
|
+
|
66
|
+
result[:sell][currency] = sell_rate
|
67
|
+
result[:buy][currency] = buy_rate
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/egp_rates.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'oga'
|
4
|
+
require 'egp_rates/bank'
|
5
|
+
require 'egp_rates/cbe'
|
6
|
+
require 'egp_rates/nbe'
|
7
|
+
|
8
|
+
# Base Module
|
9
|
+
module EGPRates
|
10
|
+
# Class Idicating HTTPResponseErrors when unexpected behaviour encountered
|
11
|
+
# while scraping the [Bank] data
|
12
|
+
class ResponseError < StandardError
|
13
|
+
end
|
14
|
+
end
|