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 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