EGP_Rates 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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