historic_bank_rates 0.2.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: ec4e067c61d7a2a2019467a7fe7d4a67e5ebcd6b
4
+ data.tar.gz: b3c08906e498dfd73398d22c13d516ddac679ad3
5
+ SHA512:
6
+ metadata.gz: 1d1b4b51374c3da98e47ee018f9179d86de3400dd2c7b2392f7f3683c41a273d8cba9aa3d9814cef8fb7c81c75f78afa6e0851380534f72845a5c310a3555cba
7
+ data.tar.gz: 87782f7295536eeda089bccc0363e45db7745c0f6f3561d0e0553206cee76d9dd10a76ef444e36c76f73facf5a2179215e1828cc3a6f44c1adc27a0de546eed0
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 mobisol
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # Historic Bank Rates
2
+ [![Build Status](https://travis-ci.org/plugintheworld/historic_bank_rates.svg?branch=master)](https://travis-ci.org/plugintheworld/historic_bank_rates)
3
+
4
+ Wraps a simple scraper to retrieve the historic exchange rates. Returns the average rates for yesterday or any day specified and supported by the Central Bank of Kenya.
5
+
6
+ ## Install
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'historic_bank_rates'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ ```ruby
17
+ $ bundle
18
+ ```
19
+
20
+ Or install it yourself as:
21
+
22
+ ```ruby
23
+ $ gem install historic_bank_rates
24
+ ```
25
+
26
+ ## Usage
27
+
28
+ ### Initialize (NOTE: the date used can affect the success of the import! method)
29
+
30
+ ```ruby
31
+ scraper = HistoricBankRates::BankScraper::CentralBankOfKenya.new
32
+ hbr = HistoricBankRates::Rates.new(scraper, Date.new(2016, 05, 30))
33
+ hbr.import! # => true
34
+ ```
35
+
36
+ import! returns true if rates have been found. Might also throw HTTP errors. It will also return false when requesting rates for weekend days.
37
+
38
+ Update an instance's import_date and rerun the import process:
39
+
40
+ ```ruby
41
+ hbr.import!(Date.new(2015, 06, 30)) # => true
42
+ ```
43
+
44
+ ### Retrieve a specific rate
45
+
46
+ ```ruby
47
+ hbr.rate('KES', 'EUR') # => 112.2322
48
+ ```
49
+
50
+ Get all available currencies:
51
+
52
+ ```ruby
53
+ hbr.currencies # => ['ZAR', 'USD', 'EUR', 'RWF'… ]
54
+ ```
55
+
56
+ Get all rates
57
+
58
+ ```ruby
59
+ hbr.rates # => { 'ZAR'=>6.4373, 'USD'=>100.6606, … }
60
+ ```
61
+
62
+ ## Legal
63
+
64
+ The author of this gem is not affiliated with any of the banks referenced/scraped by the gem.
65
+
66
+ ### License
67
+
68
+ MIT, see LICENSE file
69
+
70
+ ### No Warranty
71
+
72
+ The Software is provided "as is" without warranty of any kind, either express or implied, including without limitation any implied warranties of condition, uninterrupted use, merchantability, fitness for a particular purpose, or non-infringement.
@@ -0,0 +1,75 @@
1
+ require_relative 'rate_scraper.rb'
2
+ module HistoricBankRates
3
+ module BankScrapers
4
+ class BankOfTanzania < HistoricBankRates::BankScrapers::RateScraper
5
+ TRANSLATE = { 'Kenya SHS' => 'KES',
6
+ 'Uganda SHS' => 'UGX',
7
+ 'Rwandan Franc' => 'RWF',
8
+ 'Burundi Franc' => 'BFI',
9
+ 'USD' => 'USD',
10
+ 'Pound STG' => 'GBP',
11
+ 'EURO' => 'EUR',
12
+ 'Canadian $' => 'CAD',
13
+ 'Switz. Franc' => 'CHF',
14
+ 'Japanese YEN' => 'JPY',
15
+ 'Swedish Kronor' => 'SEK',
16
+ 'Norweg. Kronor' => 'NOK',
17
+ 'Danish Kronor' => 'DKK',
18
+ 'Australian $' => 'AUD',
19
+ 'Indian RPS' => 'INR',
20
+ 'Pakistan RPS' => 'PKR',
21
+ 'Zambian Kwacha' => 'ZAK',
22
+ 'Malawian Kwacha' => 'MWK',
23
+ 'Mozambique-MET' => 'MZN',
24
+ 'Zimbabwe $' => 'ZWD',
25
+ 'SDR' => 'XDR',
26
+ 'S. African Rand' => 'ZAR',
27
+ 'UAE Dirham' => 'AED',
28
+ 'Singapore $' => 'SGD',
29
+ 'Honk Kong $' => 'HKD',
30
+ 'Saud Arabian Rial' => 'SAR',
31
+ 'Kuwait Dinar' => 'KWD',
32
+ 'Botswana Pula' => 'BWP',
33
+ 'Chinese Yuan' => 'CNY',
34
+ 'Malaysia Ringgit' => 'MYR',
35
+ 'South Korea Won' => 'KRW',
36
+ 'Newzealand' => 'NZD' }
37
+
38
+ def base_currency
39
+ 'TZS'
40
+ end
41
+
42
+ private
43
+
44
+ def rates
45
+ response = Net::HTTP.post_form(URI(form_url), form_params)
46
+ dom = Nokogiri::HTML(response.body)
47
+ rows = dom.css(element_matcher)
48
+
49
+ Hash[rows.map do |row|
50
+ currency = TRANSLATE[row.css(':nth-child(1) font').text.split.join(' ')]
51
+ buy = Float(row.css(':nth-child(3) font').text.delete(',', '')) rescue nil
52
+ sell = Float(row.css(':nth-child(4) font').text.delete(',', '')) rescue nil
53
+ next if currency.nil? || buy.nil? || sell.nil?
54
+
55
+ # average of by and sell, divide by 100 b/c conversion is given in 100 units
56
+ [currency, (buy + sell) / 200]
57
+ end.compact]
58
+ end
59
+
60
+ def form_url
61
+ @form_url ||= 'http://www.bot-tz.org/FinancialMarkets/ExchangeRates/ShowExchangeRates.asp'
62
+ end
63
+
64
+ def form_params
65
+ {
66
+ 'SelectedExchandeDate' => start_date.strftime('%m/%d/%y')
67
+ }
68
+ end
69
+
70
+ def element_matcher
71
+ '#table1 > tr > td > table > tr > td > div > table > tr > td > table > tr'
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,73 @@
1
+ require_relative 'rate_scraper.rb'
2
+
3
+ module HistoricBankRates
4
+ module BankScrapers
5
+ class CentralBankOfKenya < HistoricBankRates::BankScrapers::RateScraper
6
+ TRANSLATE = { 'US DOLLAR' => 'USD',
7
+ 'STG POUND' => 'GBP',
8
+ 'EURO' => 'EUR',
9
+ 'SA RAND' => 'ZAR',
10
+ 'KES / USHS' => 'UGX',
11
+ 'KES / TSHS' => 'TZS',
12
+ 'KES / RWF' => 'RWF',
13
+ 'KES / BIF' => 'BIF',
14
+ 'AE DIRHAM' => 'AED',
15
+ 'CAN $' => 'CAD',
16
+ 'S FRANC' => 'CHF',
17
+ 'JPY (100)' => 'JPY',
18
+ 'SW KRONER' => 'SEK',
19
+ 'NOR KRONER' => 'NOK',
20
+ 'DAN KRONER' => 'DKK',
21
+ 'IND RUPEE' => 'INR',
22
+ 'HONGKONG DOLLAR' => 'HKD',
23
+ 'SINGAPORE DOLLAR' => 'SGD',
24
+ 'SAUDI RIYAL' => 'SAR',
25
+ 'CHINESE YUAN' => 'CNY',
26
+ 'AUSTRALIAN $' => 'AUD' }
27
+
28
+ def base_currency
29
+ 'KES'
30
+ end
31
+
32
+ private
33
+
34
+ def rates
35
+ response = Net::HTTP.post_form(URI(form_url), form_params)
36
+ dom = Nokogiri::HTML(response.body)
37
+ rows = dom.css(element_matcher)
38
+
39
+ Hash[rows.map do |row|
40
+ currency = TRANSLATE[row.css(':nth-child(2)').text]
41
+ next if currency.nil?
42
+ next if currency.empty?
43
+ avrg = row.css(':nth-child(5)').text
44
+ next if avrg.nil?
45
+ next if avrg.empty?
46
+
47
+ [currency, Float(avrg)] rescue nil
48
+ end.compact]
49
+ end
50
+
51
+ def form_url
52
+ @form_url ||= 'https://www.centralbank.go.ke/index.php/rate-and-statistics/exchange-rates-2'
53
+ end
54
+
55
+ def form_params
56
+ {
57
+ 'date' => start_date.strftime('%d'),
58
+ 'month' => start_date.strftime('%m').upcase,
59
+ 'year' => start_date.strftime('%Y'),
60
+ 'tdate' => start_date.strftime('%d'),
61
+ 'tmonth' => start_date.strftime('%m').upcase,
62
+ 'tyear' => start_date.strftime('%Y'),
63
+ 'currency' => '',
64
+ 'searchForex' => 'Search'
65
+ }
66
+ end
67
+
68
+ def element_matcher
69
+ '#cont1 > #cont3 > div.item-page > #interbank > table > tr > td > table > tr'
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,50 @@
1
+ require 'nokogiri'
2
+ require 'uri'
3
+ require 'net/http'
4
+
5
+ module HistoricBankRates
6
+ module BankScrapers
7
+ class RateScraper
8
+ TRANSLATE = {}
9
+
10
+ attr_reader :start_date
11
+ attr_accessor :form_url
12
+
13
+ def initialize
14
+ end
15
+
16
+ def call start_date
17
+ @start_date = start_date
18
+
19
+ rates
20
+ end
21
+
22
+ def base_currency
23
+ # Must implement
24
+ raise NotImplementedError
25
+ end
26
+
27
+ private
28
+
29
+ def rates
30
+ # Must implement
31
+ raise NotImplementedError
32
+ end
33
+
34
+ def form_url
35
+ # Must implement
36
+ raise NotImplementedError
37
+ end
38
+
39
+ def form_params
40
+ # Must implement
41
+ raise NotImplementedError
42
+ end
43
+
44
+ def element_matcher
45
+ # Must implement
46
+ raise NotImplementedError
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,60 @@
1
+ require 'date'
2
+ require_relative 'bank_scrapers/central_bank_of_kenya'
3
+ require_relative 'bank_scrapers/bank_of_tanzania'
4
+
5
+ module HistoricBankRates
6
+ class MissingRates < StandardError; end
7
+ class Rates
8
+ attr_reader :start_date
9
+ attr_accessor :rate_scraper
10
+
11
+ def initialize rate_scraper, start_date=nil
12
+ @rate_scraper = rate_scraper
13
+ @start_date = start_date || date_yesterday
14
+ end
15
+
16
+ def rate(iso_from, iso_to)
17
+ case rate_scraper.base_currency
18
+ when iso_from
19
+ rates[iso_to] ? 1/rates[iso_to] : nil
20
+ when iso_to
21
+ rates[iso_from]
22
+ else
23
+ fail_if_rates_missing
24
+ end
25
+ end
26
+
27
+ # Returns a list of ISO currencies
28
+ def currencies
29
+ rates.keys
30
+ end
31
+
32
+ # Returns all rates imported
33
+ def rates
34
+ fail_if_rates_missing
35
+ @rates
36
+ end
37
+
38
+ # Returns true when reading the website was successful
39
+ def has_rates?
40
+ @rates && @rates.any?
41
+ end
42
+
43
+ # Triggers the scraping
44
+ def import! import_date=nil
45
+ @start_date = import_date unless import_date.nil?
46
+ @rates = rate_scraper.call(start_date)
47
+ has_rates?
48
+ end
49
+
50
+ private
51
+
52
+ def date_yesterday
53
+ Date.today - 1
54
+ end
55
+
56
+ def fail_if_rates_missing
57
+ fail MissingRates unless has_rates?
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,5 @@
1
+ require_relative 'historic_bank_rates/rates'
2
+
3
+ module HistoricBankRates
4
+ VERSION = '0.2.0'
5
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: historic_bank_rates
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Alexander Donkin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-06-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: nokogiri
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nyan-cat-formatter
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: vcr
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: webmock
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: |-
84
+ Wraps a simple scraper to retrieve the historic exchange
85
+ rates of specific banks. Returns the average (between buy
86
+ and sell) rates for any day specified (if date isn't
87
+ specified it defaults to yesterday).
88
+ email:
89
+ - alexander_donkin@yahoo.co.uk
90
+ executables: []
91
+ extensions: []
92
+ extra_rdoc_files: []
93
+ files:
94
+ - LICENSE
95
+ - README.md
96
+ - lib/historic_bank_rates.rb
97
+ - lib/historic_bank_rates/bank_scrapers/bank_of_tanzania.rb
98
+ - lib/historic_bank_rates/bank_scrapers/central_bank_of_kenya.rb
99
+ - lib/historic_bank_rates/bank_scrapers/rate_scraper.rb
100
+ - lib/historic_bank_rates/rates.rb
101
+ homepage: http://github.com/plugintheworld/historic_bank_rates
102
+ licenses:
103
+ - MIT
104
+ metadata: {}
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 2.4.8
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: Scrapes various bank websites to generate a list of currencies and their
125
+ historic rates.
126
+ test_files: []