bank_scrap 0.0.6 → 0.0.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8aa6ea0f009804787942dd42adff98aef36dd601
4
- data.tar.gz: a137f771dfd1eee094edbd9f71d74cbc02cce20f
3
+ metadata.gz: 4680376ad7f26ae34f9cf4262fa04b98b5b466ea
4
+ data.tar.gz: 4be7fda00b5c1a410ffb602979d20894d3511f6b
5
5
  SHA512:
6
- metadata.gz: e0b08d23ebcd36680a143636d1f7eb5452b28049bee9f17b2e5b42548fa016f1627f3358216f5dcfe51c1ea7afdfa0b53129c83e76d5be4a035f8c0c0604819a
7
- data.tar.gz: 558ce9735baad049a50360b48b66b13755a28365347cde5577c0625492f283522b59193a45d390af25cb6b4bd55c90f7d80b3c673ae9293a7dbaebfc52284627
6
+ metadata.gz: 9debe3eadab0fa8a98e3d52640cf2d2a49348f92f6a5b0d2bb5b2a9555ca19d4e61559ea3b990f28bbdcef9ceda1bf36e259d540ffe4c1e23ef25ec7ce53c250
7
+ data.tar.gz: d314b783e5a962669d2717f1fa2d15568284e7c4e03195e8d32073296138f7325758d2d218aa492cbfff6fe1b0b47105b951a94d05f995ba2f7fc34bcb128e70
data/.gitignore CHANGED
@@ -13,5 +13,7 @@
13
13
  *.a
14
14
  mkmf.log
15
15
 
16
+ *.gem
17
+
16
18
  # MAC OS X files
17
19
  .DS_Store
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Bankscrap
1
+ # BankScrap
2
2
 
3
3
  Ruby gem to extract balance and transactions from banks. You can use it either as command line tool or as a library.
4
4
 
@@ -23,7 +23,7 @@ There are two approaches to solve this problem:
23
23
  - Web scraping on the bank's site.
24
24
  - Reverse engineering the bank's mobile app to use the same API the app uses.
25
25
 
26
- Bankscrap uses both methods depending on the bank.
26
+ BankScrap uses both methods depending on the bank.
27
27
 
28
28
  ## Requirements
29
29
 
@@ -52,10 +52,22 @@ Or, if you're using Bundler, just add the following to your Gemfile:
52
52
  ### From terminal
53
53
  Retrieve balance account
54
54
 
55
- $ bank_scrap balance BANK_NAME --user YOUR_BANK_USER --password YOUR_BANK_PASSWORD
55
+ ##### Bankinter
56
56
 
57
- BANK_NAME should be in underscore case (`bankinter`, `bbva`).
57
+ $ bank_scrap balance bankinter --user YOUR_BANKINTER_USER --password YOUR_BANKINTER_PASSWORD
58
58
 
59
+ ##### BBVA
60
+
61
+ $ bank_scrap balance bbva --user YOUR_BBVA_USER --password YOUR_BBVA_PASSWORD
62
+
63
+ ##### ING Direct
64
+ ING needs one more argument: your bithday.
65
+
66
+ $ bank_scrap balance ing --user YOUR_DNI --password YOUR_PASSWORD --extra=birthday:01/01/1980
67
+
68
+ Replace 01/01/1980 with your actual birthday.
69
+
70
+ ---
59
71
  If you don't want to pass your user and password everytime you can define them in your .bash_profile by adding:
60
72
 
61
73
  export BANK_SCRAP_USER=YOUR_BANK_USER
@@ -63,7 +75,7 @@ If you don't want to pass your user and password everytime you can define them i
63
75
 
64
76
  ### From Ruby code
65
77
 
66
- You can also use this gem from your own app as library. To do so first you must initialize a Bankscrapper::Bank object
78
+ You can also use this gem from your own app as library. To do so first you must initialize a BankScrap::Bank object
67
79
 
68
80
  ```ruby
69
81
  require 'bank_scrap'
data/bank_scrap.gemspec CHANGED
@@ -22,12 +22,12 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_development_dependency 'bundler', '~> 1.7'
24
24
  spec.add_development_dependency 'rake', '~> 10.0'
25
- spec.add_development_dependency 'byebug', '~> 3.5.1'
25
+ spec.add_development_dependency 'byebug', '~> 3.5', '>= 3.5.1'
26
26
 
27
27
  spec.add_dependency 'thor', "~> 0.19"
28
28
  spec.add_dependency 'nokogiri', "~> 1.6"
29
29
  spec.add_dependency 'execjs', "~> 2.2"
30
- spec.add_dependency 'curb', "~> 0.8"
30
+ spec.add_dependency 'mechanize', "~> 2.7.3"
31
31
  spec.add_dependency 'activesupport', "~> 4.1"
32
- spec.add_dependency 'rmagick', "~> 2.2.2"
32
+ spec.add_dependency 'rmagick', '~> 2.2', '>= 2.2.2'
33
33
  end
@@ -1,66 +1,58 @@
1
- require 'curb'
1
+ require 'mechanize'
2
+ require 'logger'
2
3
 
3
4
  module BankScrap
4
5
  class Bank
5
6
 
6
7
  WEB_USER_AGENT = 'Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 4 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19'
8
+ attr_accessor :headers
7
9
 
8
10
  private
9
11
 
10
12
  def get(url)
11
- @curl.url = url
12
- @curl.get
13
-
14
- @curl.body_str
13
+ @http.get(url).body
15
14
  end
16
15
 
17
16
  def post(url, fields)
18
- @curl.url = url
19
-
20
- # If hash, transform to Curl::PostField objects
21
- if fields.is_a? Hash
22
- fields = fields.collect {|key, value| Curl::PostField.content(key, value)}
23
- end
24
-
25
- @curl.post(fields)
26
- @curl.body_str
17
+ @http.post(url, fields, @headers).body
27
18
  end
28
19
 
29
20
  def put(url, fields)
30
- @curl.url = url
31
-
32
- @curl.put(fields)
33
- @curl.body_str
21
+ @http.put(url, fields, @headers).body
34
22
  end
35
23
 
36
- def set_header(name, value)
37
- @curl.headers[name] = value
24
+ # Sets temporary HTTP headers, execute a code block
25
+ # and resets the headers
26
+ def with_headers(tmp_headers)
27
+ current_headers = @headers
28
+ set_headers(tmp_headers)
29
+ yield
30
+ ensure
31
+ set_headers(current_headers)
38
32
  end
39
33
 
34
+
40
35
  def set_headers(headers)
41
- headers.each { |key, value| set_header(key, value) }
36
+ @headers.merge! headers
37
+ @http.request_headers = @headers
42
38
  end
43
39
 
44
- def get_headers
45
- @curl.header_str
46
- end
47
40
 
48
41
  def initialize_cookie(url)
49
42
  log 'Initialize cookie'
50
43
 
51
- @curl.url = url
52
- @curl.get
53
-
54
- @curl.body_str
44
+ @http.url = url
45
+ @http.get(url).body
55
46
  end
56
47
 
57
48
  def initialize_connection
58
- @curl = Curl::Easy.new
59
- @curl.follow_location = true
60
- @curl.ssl_verify_peer = false
61
- @curl.verbose = true if @debug
62
- @curl.enable_cookies = true
63
- @curl.headers["User-Agent"] = WEB_USER_AGENT
49
+ @http = Mechanize.new do |mechanize|
50
+ mechanize.user_agent = WEB_USER_AGENT
51
+ mechanize.agent.http.verify_mode = OpenSSL::SSL::VERIFY_NONE
52
+ mechanize.log = Logger.new(STDOUT) if @debug
53
+ end
54
+
55
+ @headers = {}
64
56
  end
65
57
 
66
58
  def log(msg)
@@ -5,7 +5,8 @@ module BankScrap
5
5
  BASE_ENDPOINT = 'https://bancamovil.grupobbva.com'
6
6
  LOGIN_ENDPOINT = '/DFAUTH/slod/DFServletXML'
7
7
  BALANCE_ENDPOINT = '/ENPP/enpp_mult_web_mobility_02/products/v1'
8
- USER_AGENT = 'Android;LGE;Nexus 5;1080x1776;Android;4.4.4;BMES;4.0.4'
8
+ # BBVA expects an identifier before the actual User Agent, but 12345 works fine
9
+ USER_AGENT = '12345;Android;LGE;Nexus 5;1080x1776;Android;4.4.4;BMES;4.0.4'
9
10
 
10
11
  def initialize(user, password, log: false, debug: false, extra_args: nil)
11
12
  @user = format_user(user.dup)
@@ -24,6 +25,7 @@ module BankScrap
24
25
  'Accept-Charset' => 'UTF-8',
25
26
  'Connection' => 'Keep-Alive',
26
27
  'Host' => 'bancamovil.grupobbva.com',
28
+ 'Cookie2' => '$Version=1'
27
29
  })
28
30
 
29
31
  login
@@ -31,7 +33,13 @@ module BankScrap
31
33
 
32
34
  def get_balance
33
35
  log 'get_balance'
34
- response = post(BASE_ENDPOINT + BALANCE_ENDPOINT, nil)
36
+
37
+ # Even if the required method is an HTTP POST
38
+ # the API requires a funny header that says is a GET
39
+ # otherwise the request doesn't work.
40
+ response = with_headers({'BBVA-Method' => 'GET'}) do
41
+ post(BASE_ENDPOINT + BALANCE_ENDPOINT, {})
42
+ end
35
43
 
36
44
  json = JSON.parse(response)
37
45
  json["balances"]["personalAccounts"]
@@ -37,6 +37,10 @@ module BankScrap
37
37
  balance
38
38
  end
39
39
 
40
+ def raw_product_data
41
+ @data
42
+ end
43
+
40
44
  private
41
45
 
42
46
  def bundled_login
@@ -120,7 +124,7 @@ module BankScrap
120
124
  0.upto(9) do |j|
121
125
  pinpad_pixels_sample = single_number.get_pixels(0,0, SAMPLE_WIDTH, SAMPLE_HEIGHT)
122
126
 
123
- img = Magick::ImageList.new("lib/bank_scrap/banks/ing/numbers/pinpad#{j}.png").first
127
+ img = Magick::ImageList.new(File.join(File.dirname(__FILE__), "/ing/numbers/pinpad#{j}.png")).first
124
128
  number_pixels_sample = img.get_pixels(0, 0, SAMPLE_WIDTH, SAMPLE_HEIGHT)
125
129
  diff = 0
126
130
  pinpad_pixels_sample.each_with_index do |pixel, index|
@@ -0,0 +1,237 @@
1
+ require 'execjs'
2
+ require 'pp'
3
+ require 'json'
4
+ require 'base64'
5
+ require 'RMagick'
6
+ require 'active_support'
7
+ require 'byebug'
8
+ require 'open-uri'
9
+
10
+ module BankScrap
11
+ class Ing < Bank
12
+
13
+ DESKTOP_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36'
14
+
15
+ BASE_ENDPOINT = 'https://ing.ingdirect.es/'
16
+ FALSE_LOGIN_ENDPOINT = BASE_ENDPOINT + 'login/'
17
+ CACHE_ENDPOINT = BASE_ENDPOINT + 'login/cache.manifest'
18
+ DELETE_SESSION_ENDPOINT = BASE_ENDPOINT + 'genoma_api/rest/session'
19
+ LOGIN_ENDPOINT = BASE_ENDPOINT + 'genoma_login/rest/session'
20
+ POST_AUTH_ENDPOINT = BASE_ENDPOINT + 'genoma_api/login/auth/response'
21
+ CLIENT_ENDPOINT = BASE_ENDPOINT + 'genoma_api/rest/client'
22
+ PRODUCTS_ENDPOINT = BASE_ENDPOINT + 'genoma_api/rest/products'
23
+
24
+ SAMPLE_WIDTH = 30
25
+ SAMPLE_HEIGHT = 30
26
+
27
+ def initialize(dni, birthday, password, log: false, debug: false)
28
+ @dni = dni
29
+ @birthday = birthday
30
+ @password = password.to_s
31
+ @log = log
32
+ @debug = debug
33
+
34
+ initialize_connection
35
+
36
+ @curl.proxy_port = 8888
37
+ @curl.proxy_url = '192.168.1.21'
38
+
39
+ false_login
40
+ cache
41
+ delete_session
42
+ selected_positions = login
43
+
44
+ ticket = pass_pinpad(selected_positions)
45
+
46
+ post_auth(ticket)
47
+ call_client
48
+
49
+ get_products
50
+ end
51
+
52
+ private
53
+
54
+ def false_login
55
+ @curl.url = FALSE_LOGIN_ENDPOINT
56
+ @curl.headers['Host'] = 'ing.ingdirect.es'
57
+ @curl.headers['Connection'] = 'keep-alive'
58
+ @curl.headers['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
59
+ @curl.headers['Accept-Encoding'] = 'gzip,deflate,sdch'
60
+ @curl.headers['Accept-Language'] = 'en,es;q=0.8'
61
+
62
+ response = @curl.get
63
+ end
64
+
65
+ def cache
66
+ @curl.url = CACHE_ENDPOINT
67
+ @curl.headers['Host'] = 'ing.ingdirect.es'
68
+ @curl.headers['Connection'] = 'keep-alive'
69
+ @curl.headers['Accept-Encoding'] = 'gzip,deflate,sdch'
70
+ @curl.headers['Accept-Language'] = 'en,es;q=0.8'
71
+ end
72
+
73
+ def delete_session
74
+ @curl.headers['Host'] = 'ing.ingdirect.es'
75
+ @curl.headers['Connection'] = 'keep-alive'
76
+ @curl.headers['Pragma'] = 'no-cache'
77
+ @curl.headers['Accept'] = 'application/json, text/javascript, */*; q=0.01'
78
+ @curl.headers['Origin'] = 'https://ing.ingdirect.es'
79
+ @curl.headers['X-Requested-With'] = 'XMLHttpRequest'
80
+ @curl.headers['Content-Type'] = 'application/json; charset=utf-8'
81
+ @curl.headers['Referer'] = 'https://ing.ingdirect.es/login/'
82
+ @curl.headers['Accept-Encoding'] = 'zip,deflate,sdch'
83
+ @curl.headers['Accept-Language'] = 'n,es;q=0.8'
84
+ @curl.headers['Cookie'] = 's_cc=true; s_mca=Direct; s_gts=1; s_nr=1414955726141; s_sq=%5B%5BB%5D%5D'
85
+
86
+ response = @curl.delete
87
+ pp response
88
+ end
89
+
90
+ def login
91
+ param = '{"loginDocument":{"documentType":0,"document":"' + @dni.to_s +
92
+ '"},"birthday":"' + @birthday.to_s + '","companyDocument":null,"device":"desktop"}'
93
+ puts param
94
+ @curl.url = LOGIN_ENDPOINT
95
+ @curl.headers['Host'] = 'ing.ingdirect.es'
96
+ @curl.headers['Connection'] = 'keep-alive'
97
+ @curl.headers['Pragma'] = 'no-cache'
98
+
99
+ @curl.headers['Accept'] = 'application/json, text/javascript, */*; q=0.01'
100
+ @curl.headers['Origin'] = 'https://ing.ingdirect.es'
101
+ @curl.headers['X-Requested-With'] = 'XMLHttpRequest'
102
+ @curl.headers['Content-Type'] = 'application/json; charset=utf-8'
103
+ @curl.headers['Referer'] = 'https://ing.ingdirect.es/login/'
104
+ @curl.headers['Accept-Encoding'] = 'zip,deflate,sdch'
105
+ @curl.headers['Accept-Language'] = 'n,es;q=0.8'
106
+ @curl.headers['Cookie'] = 's_cc=true; s_mca=Direct; s_gts=1; s_nr=1414955726141; s_sq=%5B%5BB%5D%5D'
107
+
108
+ response = post(LOGIN_ENDPOINT, param)
109
+ # response = @curl.body_str
110
+ response = JSON.parse(response)
111
+ positions = response['pinPositions']
112
+ pinpad = response['pinpad']
113
+
114
+ save_pinpad_numbers(pinpad)
115
+ pinpad_numbers = recognize_pinpad_numbers
116
+
117
+ get_correct_positions(pinpad_numbers, positions)
118
+ end
119
+
120
+ def pass_pinpad(positions)
121
+ param = "{\"pinPositions\": #{positions}}"
122
+ @curl.url = LOGIN_ENDPOINT
123
+ @curl.headers['Host'] = 'ing.ingdirect.es'
124
+ @curl.headers['Connection'] = 'keep-alive'
125
+ @curl.headers['Accept'] = 'application/json, text/javascript, */*; q=0.01'
126
+ @curl.headers['Origin'] = 'https://ing.ingdirect.es'
127
+ @curl.headers['X-Requested-With'] = 'XMLHttpRequest'
128
+ @curl.headers['Content-Type'] = 'application/json; charset=utf-8'
129
+ @curl.headers['Referer'] = 'https://ing.ingdirect.es/login/?clientId=281afde24c938607e5edeac6239e8a38&continue=%2Fpfm%2F'
130
+ @curl.headers['Accept-Encoding'] = 'gzip,deflate,sdch'
131
+
132
+ response = put(LOGIN_ENDPOINT, param)
133
+ response = ActiveSupport::Gzip.decompress(response)
134
+ response = JSON.parse(response)
135
+
136
+ response['ticket']
137
+ end
138
+
139
+ def post_auth(ticket)
140
+ @curl.headers['Host'] = 'ing.ingdirect.es'
141
+ @curl.headers['Connection'] = 'keep-alive'
142
+ @curl.headers['Accept'] = 'application/json, text/javascript, */*; q=0.01'
143
+ @curl.headers['Origin'] = 'https://ing.ingdirect.es'
144
+ @curl.headers['X-Requested-With'] = 'XMLHttpRequest'
145
+ @curl.headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'
146
+ @curl.headers['Referer'] = 'https://ing.ingdirect.es/login'
147
+ @curl.headers['Accept-Encoding'] = 'gzip,deflate'
148
+
149
+ @curl.url = POST_AUTH_ENDPOINT
150
+ param = "ticket=#{ticket}&device=desktop"
151
+ @curl.post(param)
152
+ response = @curl.body_str
153
+ end
154
+
155
+ def call_client
156
+ @curl.headers['Host'] = 'ing.ingdirect.es'
157
+ @curl.headers['Connection'] = 'keep-alive'
158
+ @curl.headers['Accept'] = 'application/json, text/javascript, */*; q=0.01'
159
+ @curl.headers['X-Requested-With'] = 'XMLHttpRequest'
160
+ @curl.headers['Content-Type'] = 'application/json; charset=utf-8'
161
+ @curl.headers['Referer'] = 'https://ing.ingdirect.es/pfm'
162
+ @curl.headers['Accept-Encoding'] = 'gzip,deflate,sdch'
163
+
164
+ response = get(CLIENT_ENDPOINT)
165
+
166
+ response = ActiveSupport::Gzip.decompress(response)
167
+ response = JSON.parse(response)
168
+ end
169
+
170
+ def get_products
171
+ @curl.headers['Host'] = 'ing.ingdirect.es'
172
+ @curl.headers['Connection'] = 'keep-alive'
173
+ @curl.headers['Accept'] = '*/*'
174
+ @curl.headers['X-Requested-With'] = 'XMLHttpRequest'
175
+ @curl.headers['Content-Type'] = 'application/json; charset=utf-8'
176
+ @curl.headers['Referer'] = 'https://ing.ingdirect.es/pfm'
177
+ @curl.headers['Accept-Encoding'] = 'gzip,deflate,sdch'
178
+
179
+ response = get(PRODUCTS_ENDPOINT)
180
+
181
+ File.open('response_raw.txt', 'w') { |file| file.write(response) }
182
+ response = ActiveSupport::Gzip.decompress(response)
183
+ File.open('response_decompressed.txt', 'w') { |file| file.write(response) }
184
+ File.open('response_parsed.txt', 'w') { |file| file.write(JSON.parse(response)) }
185
+ end
186
+
187
+ def save_pinpad_numbers(pinpad)
188
+ pinpad.each_with_index do |p,index|
189
+ File.open(build_tmp_path(index), 'wb'){ |f| f.write(Base64.decode64(p)) }
190
+ end
191
+ end
192
+
193
+ def build_tmp_path(number)
194
+ "tmp/original_pinpad_#{number}.png"
195
+ end
196
+
197
+ def recognize_pinpad_numbers
198
+ pinpad_numbers = []
199
+ 0.upto(9) do |i|
200
+ pinpad = Magick::ImageList.new(build_tmp_path(i)).first
201
+
202
+ differences = []
203
+ 0.upto(9) do |j|
204
+ pinpad_pixels_sample = pinpad.get_pixels(0,0, SAMPLE_WIDTH, SAMPLE_HEIGHT)
205
+
206
+ img = Magick::ImageList.new("numbers/pinpad#{j}.png").first
207
+ number_pixels_sample = img.get_pixels(0, 0, SAMPLE_WIDTH, SAMPLE_HEIGHT)
208
+ diff = 0
209
+ pinpad_pixels_sample.each_with_index do |pixel, index|
210
+ sample_pixel = number_pixels_sample[index]
211
+ diff += (pixel.red - sample_pixel.red).abs +
212
+ (pixel.green - sample_pixel.green).abs +
213
+ (pixel.blue - sample_pixel.blue).abs
214
+ end
215
+ differences << diff
216
+ end
217
+
218
+ real_number = differences.each_with_index.min.last
219
+ pinpad_numbers << real_number
220
+ end
221
+
222
+ pinpad_numbers
223
+ end
224
+
225
+ def get_correct_positions(pinpad_numbers, positions)
226
+ first_digit = @password[positions[0] - 1]
227
+ second_digit = @password[positions[1] - 1]
228
+ third_digit = @password[positions[2] - 1]
229
+
230
+ [
231
+ pinpad_numbers.index(first_digit.to_i),
232
+ pinpad_numbers.index(second_digit.to_i),
233
+ pinpad_numbers.index(third_digit.to_i)
234
+ ]
235
+ end
236
+ end
237
+ end
@@ -1,3 +1,3 @@
1
1
  module BankScrap
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bank_scrap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ismael Sánchez
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2014-11-10 00:00:00.000000000 Z
14
+ date: 2015-01-25 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -46,6 +46,9 @@ dependencies:
46
46
  requirement: !ruby/object:Gem::Requirement
47
47
  requirements:
48
48
  - - "~>"
49
+ - !ruby/object:Gem::Version
50
+ version: '3.5'
51
+ - - ">="
49
52
  - !ruby/object:Gem::Version
50
53
  version: 3.5.1
51
54
  type: :development
@@ -53,6 +56,9 @@ dependencies:
53
56
  version_requirements: !ruby/object:Gem::Requirement
54
57
  requirements:
55
58
  - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.5'
61
+ - - ">="
56
62
  - !ruby/object:Gem::Version
57
63
  version: 3.5.1
58
64
  - !ruby/object:Gem::Dependency
@@ -98,19 +104,19 @@ dependencies:
98
104
  - !ruby/object:Gem::Version
99
105
  version: '2.2'
100
106
  - !ruby/object:Gem::Dependency
101
- name: curb
107
+ name: mechanize
102
108
  requirement: !ruby/object:Gem::Requirement
103
109
  requirements:
104
110
  - - "~>"
105
111
  - !ruby/object:Gem::Version
106
- version: '0.8'
112
+ version: 2.7.3
107
113
  type: :runtime
108
114
  prerelease: false
109
115
  version_requirements: !ruby/object:Gem::Requirement
110
116
  requirements:
111
117
  - - "~>"
112
118
  - !ruby/object:Gem::Version
113
- version: '0.8'
119
+ version: 2.7.3
114
120
  - !ruby/object:Gem::Dependency
115
121
  name: activesupport
116
122
  requirement: !ruby/object:Gem::Requirement
@@ -130,6 +136,9 @@ dependencies:
130
136
  requirement: !ruby/object:Gem::Requirement
131
137
  requirements:
132
138
  - - "~>"
139
+ - !ruby/object:Gem::Version
140
+ version: '2.2'
141
+ - - ">="
133
142
  - !ruby/object:Gem::Version
134
143
  version: 2.2.2
135
144
  type: :runtime
@@ -137,6 +146,9 @@ dependencies:
137
146
  version_requirements: !ruby/object:Gem::Requirement
138
147
  requirements:
139
148
  - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: '2.2'
151
+ - - ">="
140
152
  - !ruby/object:Gem::Version
141
153
  version: 2.2.2
142
154
  description: Command line tools to get bank account details from some banks.
@@ -169,6 +181,7 @@ files:
169
181
  - lib/bank_scrap/banks/ing/numbers/pinpad7.png
170
182
  - lib/bank_scrap/banks/ing/numbers/pinpad8.png
171
183
  - lib/bank_scrap/banks/ing/numbers/pinpad9.png
184
+ - lib/bank_scrap/banks/ing_backup.rb
172
185
  - lib/bank_scrap/cli.rb
173
186
  - lib/bank_scrap/version.rb
174
187
  homepage: https://github.com/ismaGNU/bank_scrap
@@ -196,4 +209,3 @@ signing_key:
196
209
  specification_version: 4
197
210
  summary: Get your bank account details.
198
211
  test_files: []
199
- has_rdoc: