burglar 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad15042c4c2a1593be0e0fed11ce0a41d0d944f8
4
- data.tar.gz: 6220d4e9cfc3b9e8b00838d0a074877da2f89d0b
3
+ metadata.gz: 81787646ec2d922aea291dfaf4de5fcb7d08eb01
4
+ data.tar.gz: a329034499aa42ad0ef1a8ec79459d1cf89fa50e
5
5
  SHA512:
6
- metadata.gz: ab4cfcd6e4b02078c03d52f1516280b330a49a2e55c46cfb54ec695541e796c35ea7c88992653f54abe5334b7febfceb4457507b2ee0378830120e501d7fc5af
7
- data.tar.gz: 60304bd5cedb001bbad65625f9140270bb3fa7e6efe923342d146eaf2f45164765fd39410a30896b384734586949b3e8cf525ed0cd32ebe1c0d803071464379c
6
+ metadata.gz: 4d9e2cc34ec13edf2daa8e1ea132061ef0bd660b43991ddac1cbdd175d9d3fca126510c79542ed9bb92545b1c9867828d1fb9bb3f66074e31a661ddaa7aead81
7
+ data.tar.gz: 6b236a999b709735b7bfc130dd57ad321c391d478cd4004beebc14585b5056c8b18a6dca41fae9e74fcb701e9cf201595b190c92742d773f48cf3eaf57175172
data/.circle-ruby ADDED
@@ -0,0 +1,3 @@
1
+ 2.4.2
2
+ 2.3.5
3
+ 2.2.8
data/.prospectus CHANGED
@@ -1,11 +1,25 @@
1
+ Prospectus.extra_dep('file', 'prospectus_circleci')
2
+
3
+ my_slug = 'akerl/burglar'
4
+
1
5
  item do
2
- expected do
3
- static
4
- set 'green'
5
- end
6
+ noop
6
7
 
7
- actual do
8
- gemnasium
9
- slug 'akerl/burglar'
8
+ deps do
9
+ item do
10
+ name 'gems'
11
+
12
+ expected do
13
+ static
14
+ set 'green'
15
+ end
16
+
17
+ actual do
18
+ gemnasium
19
+ slug my_slug
20
+ end
21
+ end
10
22
  end
23
+
24
+ extend ProspectusCircleci::Build.new(my_slug)
11
25
  end
data/.rubocop.yml CHANGED
@@ -1,2 +1,5 @@
1
- Encoding:
2
- Enabled: false
1
+ inherit_gem:
2
+ goodcop: .rubocop.yml
3
+ AllCops:
4
+ Include:
5
+ - 'bin/*'
data/Gemfile CHANGED
@@ -1,4 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
-
data/README.md CHANGED
@@ -3,15 +3,76 @@ burglar
3
3
 
4
4
  [![Gem Version](https://img.shields.io/gem/v/burglar.svg)](https://rubygems.org/gems/burglar)
5
5
  [![Dependency Status](https://img.shields.io/gemnasium/akerl/burglar.svg)](https://gemnasium.com/akerl/burglar)
6
- [![Build Status](https://img.shields.io/circleci/project/akerl/burglar.svg)](https://circleci.com/gh/akerl/burglar)
6
+ [![Build Status](https://img.shields.io/circleci/project/akerl/burglar/master.svg)](https://circleci.com/gh/akerl/burglar)
7
7
  [![Coverage Status](https://img.shields.io/codecov/c/github/akerl/burglar.svg)](https://codecov.io/github/akerl/burglar)
8
- [![Code Quality](https://img.shields.io/codacy/.svg)](https://www.codacy.com/app/akerl/burglar)
8
+ [![Code Quality](https://img.shields.io/codacy/940f3f131d724124a68a0be7d21f951b.svg)](https://www.codacy.com/app/akerl/burglar)
9
9
  [![MIT Licensed](https://img.shields.io/badge/license-MIT-green.svg)](https://tldrlegal.com/license/mit-license)
10
10
 
11
- Tool for parsing data from bank websites
11
+ Tool for parsing data from bank websites into the format of [ledger](http://ledger-cli.org/)
12
12
 
13
13
  ## Usage
14
14
 
15
+ Burglar operates on the concept of `modules` for each bank's site. The module does the heavy lifting to hit the API or scrape the site for data.
16
+
17
+ ### Running burglar
18
+
19
+ Burglar supports a couple of command line flags, each with a sane default:
20
+
21
+ ```
22
+ -c FILE, --config FILE Config file to load
23
+ -b DATE, --begin DATE Beginning of date range
24
+ -e DATE, --end DATE End of date range
25
+ ```
26
+
27
+ The config file will default to `~/.burglar.yml`, begin defaults to 30 days ago, and end defaults to today.
28
+
29
+ ### Configuration file
30
+
31
+ Here's an initial example, which should be mostly self explanatory.
32
+
33
+ ```
34
+ banks:
35
+ amex:
36
+ type: american_express
37
+ user: akerl
38
+ account: Liabilities:Credit:amex
39
+ ```
40
+
41
+ The banks object is a hash of named hashes, each one is an account that will be polled. Each account *must* have a `type`, which is the name of the module to use. You can also pass an `account`, which sets the account name for the ledger output (if not set, modules can attempt to provide a default). Other configuration depends on the module.
42
+
43
+ ### Modules
44
+
45
+ #### American Express
46
+
47
+ This pulls from the American Express site by scraping a CSV.
48
+
49
+ Configuration:
50
+
51
+ * [required] user: your American Express username
52
+
53
+ #### Ally
54
+
55
+ This pulls from the Ally site by scraping a CSV.
56
+
57
+ * [required] user: your Ally username
58
+ * [required] name: the nickname of the specific account
59
+
60
+ ### Helpers
61
+
62
+ Helpers exist to centralize common activity that modules can rely on.
63
+
64
+ #### Creds
65
+
66
+ This uses [keylime](https://github.com/akerl/keylime) to pull creds from an OSX keychain
67
+
68
+ #### Ledger
69
+
70
+ This helps convert transactions into ledger entries using [libledger](https://github.com/akerl/libledger)
71
+
72
+ #### Mechanize
73
+
74
+ This provides a [Mechanize](https://github.com/sparklemotion/mechanize) client for modules that want to scrape the bank website
75
+
15
76
  ## Installation
16
77
 
17
78
  gem install burglar
data/Rakefile CHANGED
@@ -7,8 +7,7 @@ RSpec::Core::RakeTask.new(:spec)
7
7
 
8
8
  desc 'Run Rubocop on the gem'
9
9
  RuboCop::RakeTask.new(:rubocop) do |task|
10
- task.patterns = ['lib/**/*.rb', 'spec/**/*.rb']
11
10
  task.fail_on_error = true
12
11
  end
13
12
 
14
- task default: [:spec, :rubocop, :build, :install]
13
+ task default: %i[spec rubocop build install]
data/bin/burglar ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'burglar'
4
+ require 'mercenary'
5
+ require 'cymbal'
6
+ require 'yaml'
7
+
8
+ def add_common_opts(c)
9
+ c.option :config, '-c FILE', '--config FILE', 'Config file to load'
10
+ c.option :begin, '-b DATE', '--begin DATE', 'Beginning of date range'
11
+ c.option :end, '-e DATE', '--end DATE', 'End of date range'
12
+ end
13
+
14
+ def load_config(file)
15
+ file ||= '~/.burglar.yml'
16
+ file = File.expand_path file
17
+ Cymbal.symbolize YAML.safe_load(File.read(file))
18
+ end
19
+
20
+ Mercenary.program(:burglar) do |p|
21
+ p.version Burglar::VERSION
22
+ p.description 'Load data from banks'
23
+ p.syntax 'burglar [options]'
24
+
25
+ add_common_opts(p)
26
+
27
+ p.action do |_, options|
28
+ options[:end] ||= Date.today
29
+ options[:begin] ||= options[:end] - 30
30
+ config = load_config(options[:config]).merge(options)
31
+ puts Burglar.new(config).transactions
32
+ end
33
+ end
data/burglar.gemspec CHANGED
@@ -1,10 +1,14 @@
1
+ require 'English'
2
+ $LOAD_PATH.unshift File.expand_path('../lib/', __FILE__)
3
+ require 'burglar/version'
4
+
1
5
  Gem::Specification.new do |s|
2
6
  s.name = 'burglar'
3
- s.version = '0.0.1'
7
+ s.version = Burglar::VERSION
4
8
  s.date = Time.now.strftime('%Y-%m-%d')
5
9
 
6
10
  s.summary = 'Tool for parsing data from bank websites'
7
- s.description = "Tool for parsing data from bank websites"
11
+ s.description = 'Tool for parsing data from bank websites'
8
12
  s.authors = ['Les Aker']
9
13
  s.email = 'me@lesaker.org'
10
14
  s.homepage = 'https://github.com/akerl/burglar'
@@ -12,10 +16,17 @@ Gem::Specification.new do |s|
12
16
 
13
17
  s.files = `git ls-files`.split
14
18
  s.test_files = `git ls-files spec/*`.split
19
+ s.executables = ['burglar']
20
+
21
+ s.add_dependency 'cymbal', '~> 1.0.0'
22
+ s.add_dependency 'libledger', '~> 0.0.3'
23
+ s.add_dependency 'logcabin', '~> 0.1.3'
24
+ s.add_dependency 'mercenary', '~> 0.3.4'
15
25
 
16
- s.add_development_dependency 'rubocop', '~> 0.35.0'
17
- s.add_development_dependency 'rake', '~> 10.4.0'
18
26
  s.add_development_dependency 'codecov', '~> 0.1.1'
19
- s.add_development_dependency 'rspec', '~> 3.4.0'
20
- s.add_development_dependency 'fuubar', '~> 2.0.0'
27
+ s.add_development_dependency 'fuubar', '~> 2.2.0'
28
+ s.add_development_dependency 'goodcop', '~> 0.1.0'
29
+ s.add_development_dependency 'rake', '~> 12.3.0'
30
+ s.add_development_dependency 'rspec', '~> 3.7.0'
31
+ s.add_development_dependency 'rubocop', '~> 0.51.0'
21
32
  end
data/circle.yml CHANGED
@@ -1,12 +1,7 @@
1
1
  dependencies:
2
2
  override:
3
- - 'rvm-exec 2.0.0-p645 bundle install'
4
- - 'rvm-exec 2.1.6 bundle install'
5
- - 'rvm-exec 2.2.2 bundle install'
6
- - 'rvm-exec 2.3.1 bundle install'
3
+ - 'for i in $(cat .circle-ruby) ; do rvm-exec $i gem update --system --no-doc || exit 1 ; done'
4
+ - 'for i in $(cat .circle-ruby) ; do rvm-exec $i bundle install || exit 1 ; done'
7
5
  test:
8
6
  override:
9
- - 'rvm-exec 2.0.0-p645 bundle exec rake'
10
- - 'rvm-exec 2.1.6 bundle exec rake'
11
- - 'rvm-exec 2.2.2 bundle exec rake'
12
- - 'rvm-exec 2.3.1 bundle exec rake'
7
+ - 'for i in $(cat .circle-ruby) ; do rvm-exec $i bundle exec rake || exit 1 ; done'
data/lib/burglar.rb CHANGED
@@ -0,0 +1,43 @@
1
+ require 'logcabin'
2
+ require 'libledger'
3
+
4
+ ##
5
+ # This module provides a unified interface for pulling accountig transactions
6
+ module Burglar
7
+ class << self
8
+ ##
9
+ # Insert a helper .new() method for creating a new Heist object
10
+
11
+ def new(*args)
12
+ self::Heist.new(*args)
13
+ end
14
+
15
+ def modules
16
+ @modules ||= LogCabin.new(load_path: load_path(:modules))
17
+ end
18
+
19
+ def helpers
20
+ @helpers ||= LogCabin.new(load_path: load_path(:helpers))
21
+ end
22
+
23
+ def extra_dep(name, dep)
24
+ require dep
25
+ rescue LoadError
26
+ raise("The #{name} module requires the #{dep} gem")
27
+ end
28
+
29
+ private
30
+
31
+ def gem_dir
32
+ Gem::Specification.find_by_name('burglar').gem_dir
33
+ end
34
+
35
+ def load_path(type)
36
+ File.join(gem_dir, 'lib', 'burglar', type.to_s)
37
+ end
38
+ end
39
+ end
40
+
41
+ require 'burglar/version'
42
+ require 'burglar/heist'
43
+ require 'burglar/bank'
@@ -0,0 +1,40 @@
1
+ module Burglar
2
+ ##
3
+ # Single bank's information
4
+ class Bank
5
+ def initialize(params = {})
6
+ @options = params
7
+ extend module_obj
8
+ end
9
+
10
+ def transactions
11
+ Ledger.new(entries: raw_transactions)
12
+ end
13
+
14
+ def begin_date
15
+ @begin_date ||= @options[:begin]
16
+ end
17
+
18
+ def end_date
19
+ @end_date ||= @options[:end]
20
+ end
21
+
22
+ private
23
+
24
+ def account_name
25
+ @account_name ||= @options[:account] || default_account_name
26
+ end
27
+
28
+ def default_account_name
29
+ raise('Module failed to override default_account_name')
30
+ end
31
+
32
+ def type
33
+ @type ||= @options[:type] || raise('Must supply an account type')
34
+ end
35
+
36
+ def module_obj
37
+ @module_obj ||= Burglar.modules.find(type) || raise("No module: #{type}")
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,21 @@
1
+ module Burglar
2
+ ##
3
+ # Collection of banks
4
+ class Heist
5
+ def initialize(params = {})
6
+ @options = params
7
+ end
8
+
9
+ def banks
10
+ @banks ||= @options[:banks].map do |k, v|
11
+ [k, Burglar::Bank.new(@options.merge(v))]
12
+ end.to_h
13
+ end
14
+
15
+ def transactions
16
+ @transactions ||= Ledger.new(
17
+ entries: banks.map { |_, v| v.transactions.entries }.flatten.sort
18
+ )
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,14 @@
1
+ Burglar.extra_dep('creds', 'keylime')
2
+
3
+ module LogCabin
4
+ module Modules
5
+ ##
6
+ # Provide a helper to access OSX keychain credentials
7
+ module Creds
8
+ def creds(server, account)
9
+ credential = Keylime.new(server: server, account: account)
10
+ credential.get!("Enter password for #{server} (#{account})").password
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ module LogCabin
2
+ module Modules
3
+ ##
4
+ # Provide a helper to create simple Ledger objects
5
+ module Ledger
6
+ def simple_ledger(date, name, amount)
7
+ ::Ledger::Entry.new(
8
+ name: name,
9
+ state: date > Date.today ? :pending : :cleared,
10
+ date: date.strftime('%Y/%m/%d'),
11
+ actions: [
12
+ { name: guess_action(name), amount: amount },
13
+ { name: account_name }
14
+ ]
15
+ )
16
+ end
17
+
18
+ def guess_action(name)
19
+ guess = `ledger xact '#{name.delete("'")}' 2>/dev/null`.split("\n")[1]
20
+ guess ? guess.split.first : 'Expenses:generic'
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ Burglar.extra_dep('mechanize', 'mechanize')
2
+
3
+ module LogCabin
4
+ module Modules
5
+ ##
6
+ # Provide a helper to scrape websites
7
+ module Mechanize
8
+ def mech
9
+ return @mech if @mech
10
+ @mech = ::Mechanize.new
11
+ setup_mech if respond_to? :setup_mech, true
12
+ @mech
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,156 @@
1
+ require 'json'
2
+ require 'csv'
3
+ require 'date'
4
+ require 'digest/sha1'
5
+
6
+ module LogCabin
7
+ module Modules
8
+ ##
9
+ # Ally
10
+ module Ally # rubocop:disable Metrics/ModuleLength
11
+ include Burglar.helpers.find(:creds)
12
+ include Burglar.helpers.find(:mechanize)
13
+ include Burglar.helpers.find(:ledger)
14
+
15
+ ALLY_DOMAIN = 'https://secure.ally.com'.freeze
16
+ ALLY_CSRF_URL = ALLY_DOMAIN + '/capi-gw/session/status/olbWeb'
17
+ ALLY_AUTH_URL = ALLY_DOMAIN + '/capi-gw/customer/authentication'
18
+ ALLY_AUTH_PATCH_URL = ALLY_AUTH_URL + '?_method=PATCH'
19
+ ALLY_MFA_URL = ALLY_DOMAIN + '/capi-gw/notification'
20
+ ALLY_DEVICE_URL = ALLY_DOMAIN + '/capi-gw/customer/device'
21
+ ALLY_DEVICE_PATCH_URL = ALLY_DEVICE_URL + '?_method=PATCH'
22
+ ALLY_ACCOUNT_URL = ALLY_DOMAIN + '/capi-gw/accounts'
23
+
24
+ def raw_transactions
25
+ csv.map do |x|
26
+ amount = format('$%.2f', x[:amount] * -1)
27
+ simple_ledger(x[:date], x[:description], amount)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def default_account_name
34
+ 'Assets:' + @options[:name].gsub(/\s/, '')
35
+ end
36
+
37
+ def raw_csv_url
38
+ ALLY_DOMAIN + "/capi-gw/accounts/#{account_id}/transactions.csv"
39
+ end
40
+
41
+ def raw_csv
42
+ csv_headers = headers('text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8') # rubocop:disable Metrics/LineLength
43
+ @raw_csv ||= mech.get(raw_csv_url, csv_data, nil, csv_headers)
44
+ end
45
+
46
+ def csv
47
+ @csv ||= CSV.new(
48
+ raw_csv.body,
49
+ headers: true,
50
+ header_converters: :symbol,
51
+ converters: %i[date float]
52
+ ).map(&:to_h)
53
+ end
54
+
55
+ def csv_data
56
+ @csv_data ||= {
57
+ 'fromDate' => begin_date.strftime('%Y-%m-%d'),
58
+ 'toDate' => end_date.strftime('%Y-%m-%d'),
59
+ 'status' => 'Posted'
60
+ }
61
+ end
62
+
63
+ def user
64
+ @user ||= @options[:user]
65
+ end
66
+
67
+ def password
68
+ @password ||= creds(ALLY_DOMAIN, user)
69
+ end
70
+
71
+ def csrf_token
72
+ mech
73
+ @csrf_token ||= mech.get(ALLY_CSRF_URL).response['csrfchallengetoken']
74
+ end
75
+
76
+ def device_token
77
+ return @device_token if @device_token
78
+ res = `system_profiler SPHardwareDataType`
79
+ raw_token = res.lines.grep(/Serial Number/).first.split.last
80
+ @device_token = Digest::SHA1.hexdigest raw_token
81
+ end
82
+
83
+ def headers(accept, spname = nil)
84
+ {
85
+ 'CSRFChallengeToken' => csrf_token,
86
+ 'ApplicationName' => 'AOB',
87
+ 'ApplicationId' => 'ALLYUSBOLB',
88
+ 'ApplicationVersion' => '1.0',
89
+ 'Accept' => accept,
90
+ 'spname' => spname
91
+ }.reject { |_, v| v.nil? }
92
+ end
93
+
94
+ def auth_headers
95
+ @auth_headers ||= headers('application/v1+json', 'auth')
96
+ end
97
+
98
+ def common_data
99
+ @common_data = {
100
+ 'channelType' => 'OLB',
101
+ 'devicePrintRSA' => device_token
102
+ }
103
+ end
104
+
105
+ def auth_data
106
+ @auth_data = common_data.merge(
107
+ 'userNamePvtEncrypt' => user,
108
+ 'passwordPvtBlock' => password,
109
+ 'rememberMeFlag' => 'false'
110
+ )
111
+ end
112
+
113
+ def setup_mech
114
+ auth = mech.post(ALLY_AUTH_URL, auth_data, auth_headers)
115
+ auth_res = JSON.parse(auth.body)
116
+ mfa(auth_res) if auth_res['authentication']['mfa']
117
+ end
118
+
119
+ def mfa_data(payload)
120
+ mfa_methods = payload['authentication']['mfa']['mfaDeliveryMethods']
121
+ mfa_id = mfa_methods.first['deliveryMethodId']
122
+ common_data.merge('deliveryMethodId' => mfa_id)
123
+ end
124
+
125
+ def mfa_token
126
+ UserInput.new(message: 'MFA token', validation: /^\d+$/).ask
127
+ end
128
+
129
+ def mfa(payload)
130
+ mech.post(ALLY_MFA_URL, mfa_data(payload), auth_headers)
131
+ data = common_data.merge('otpCodePvtBlock' => mfa_token)
132
+ mech.post(ALLY_AUTH_PATCH_URL, data, auth_headers)
133
+ mech.post(ALLY_DEVICE_PATCH_URL, common_data, auth_headers)
134
+ end
135
+
136
+ def accounts
137
+ account_headers = headers('application/vnd.api+json', 'common-api')
138
+ @accounts ||= JSON.parse(
139
+ mech.get(ALLY_ACCOUNT_URL, [], nil, account_headers).body
140
+ )
141
+ end
142
+
143
+ def account
144
+ return @account if @account
145
+ list = accounts['accounts']['deposit']['accountSummary']
146
+ match = list.find { |x| x['accountNickname'].match @options[:name] }
147
+ raise('No matching account found') unless match
148
+ @account = match
149
+ end
150
+
151
+ def account_id
152
+ @account_id ||= account['accountId']
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,79 @@
1
+ require 'csv'
2
+ require 'date'
3
+
4
+ module LogCabin
5
+ module Modules
6
+ ##
7
+ # American Express
8
+ module AmericanExpress
9
+ include Burglar.helpers.find(:creds)
10
+ include Burglar.helpers.find(:ledger)
11
+ include Burglar.helpers.find(:mechanize)
12
+
13
+ # rubocop:disable Metrics/LineLength
14
+ AMEX_DOMAIN = 'https://online.americanexpress.com'.freeze
15
+ AMEX_LOGIN_PATH = '/myca/logon/us/action/LogonHandler?request_type=LogonHandler&Face=en_US'.freeze
16
+ AMEX_LOGIN_FORM = 'lilo_formLogon'.freeze
17
+ AMEX_CSV_PATH = '/myca/estmt/us/downloadTxn.do'.freeze
18
+ # rubocop:enable Metrics/LineLength
19
+
20
+ def raw_transactions
21
+ @raw_transactions ||= csv.map do |row|
22
+ raw_date, raw_amount, raw_name = row.values_at(0, 7, 11)
23
+ date = Date.strptime(raw_date, '%m/%d/%Y %a')
24
+ amount = format('$%.2f', raw_amount)
25
+ name = raw_name.empty? ? 'Amex Payment' : raw_name.downcase
26
+ simple_ledger(date, name, amount)
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ def default_account_name
33
+ 'Liabilities:Credit:american_express'.freeze
34
+ end
35
+
36
+ def user
37
+ @user ||= @options[:user]
38
+ end
39
+
40
+ def password
41
+ @password ||= creds(AMEX_DOMAIN, user)
42
+ end
43
+
44
+ def setup_mech
45
+ mech.user_agent = 'chrome'
46
+ page = mech.get(AMEX_DOMAIN + AMEX_LOGIN_PATH)
47
+ form = page.form_with(id: AMEX_LOGIN_FORM) do |f|
48
+ f.UserID = user
49
+ f.Password = password
50
+ end
51
+ form.submit
52
+ end
53
+
54
+ def csv
55
+ CSV.parse(csv_page.body)
56
+ end
57
+
58
+ def csv_page
59
+ params = static_fields.merge(
60
+ 'startDate' => begin_date.strftime('%m%d%Y'),
61
+ 'endDate' => end_date.strftime('%m%d%Y')
62
+ )
63
+ mech.post(AMEX_DOMAIN + AMEX_CSV_PATH, params)
64
+ end
65
+
66
+ def static_fields
67
+ @static_fields ||= {
68
+ 'request_type' => 'authreg_Statement',
69
+ 'downloadType' => 'C',
70
+ 'downloadView' => 'C',
71
+ 'downloadWithETDTool' => 'true',
72
+ 'viewType' => 'L',
73
+ 'reportType' => '1',
74
+ 'BPIndex' => '-99'
75
+ }.freeze
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # Set the version (needed for Mercenary -v)
5
+ module Burglar
6
+ VERSION = '0.0.2'.freeze
7
+ end
data/spec/burglar_spec.rb CHANGED
@@ -1,2 +1 @@
1
1
  require 'spec_helper'
2
-
metadata CHANGED
@@ -1,43 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: burglar
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Les Aker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-24 00:00:00.000000000 Z
11
+ date: 2017-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rubocop
14
+ name: cymbal
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.35.0
20
- type: :development
19
+ version: 1.0.0
20
+ type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.35.0
26
+ version: 1.0.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: rake
28
+ name: libledger
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 10.4.0
34
- type: :development
33
+ version: 0.0.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: logcabin
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.3
48
+ type: :runtime
35
49
  prerelease: false
36
50
  version_requirements: !ruby/object:Gem::Requirement
37
51
  requirements:
38
52
  - - "~>"
39
53
  - !ruby/object:Gem::Version
40
- version: 10.4.0
54
+ version: 0.1.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: mercenary
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.3.4
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.3.4
41
69
  - !ruby/object:Gem::Dependency
42
70
  name: codecov
43
71
  requirement: !ruby/object:Gem::Requirement
@@ -52,40 +80,84 @@ dependencies:
52
80
  - - "~>"
53
81
  - !ruby/object:Gem::Version
54
82
  version: 0.1.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: fuubar
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 2.2.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 2.2.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: goodcop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 0.1.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.1.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 12.3.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 12.3.0
55
125
  - !ruby/object:Gem::Dependency
56
126
  name: rspec
57
127
  requirement: !ruby/object:Gem::Requirement
58
128
  requirements:
59
129
  - - "~>"
60
130
  - !ruby/object:Gem::Version
61
- version: 3.4.0
131
+ version: 3.7.0
62
132
  type: :development
63
133
  prerelease: false
64
134
  version_requirements: !ruby/object:Gem::Requirement
65
135
  requirements:
66
136
  - - "~>"
67
137
  - !ruby/object:Gem::Version
68
- version: 3.4.0
138
+ version: 3.7.0
69
139
  - !ruby/object:Gem::Dependency
70
- name: fuubar
140
+ name: rubocop
71
141
  requirement: !ruby/object:Gem::Requirement
72
142
  requirements:
73
143
  - - "~>"
74
144
  - !ruby/object:Gem::Version
75
- version: 2.0.0
145
+ version: 0.51.0
76
146
  type: :development
77
147
  prerelease: false
78
148
  version_requirements: !ruby/object:Gem::Requirement
79
149
  requirements:
80
150
  - - "~>"
81
151
  - !ruby/object:Gem::Version
82
- version: 2.0.0
152
+ version: 0.51.0
83
153
  description: Tool for parsing data from bank websites
84
154
  email: me@lesaker.org
85
- executables: []
155
+ executables:
156
+ - burglar
86
157
  extensions: []
87
158
  extra_rdoc_files: []
88
159
  files:
160
+ - ".circle-ruby"
89
161
  - ".gitignore"
90
162
  - ".prospectus"
91
163
  - ".rspec"
@@ -94,9 +166,18 @@ files:
94
166
  - LICENSE
95
167
  - README.md
96
168
  - Rakefile
169
+ - bin/burglar
97
170
  - burglar.gemspec
98
171
  - circle.yml
99
172
  - lib/burglar.rb
173
+ - lib/burglar/bank.rb
174
+ - lib/burglar/heist.rb
175
+ - lib/burglar/helpers/creds.rb
176
+ - lib/burglar/helpers/ledger.rb
177
+ - lib/burglar/helpers/mechanize.rb
178
+ - lib/burglar/modules/ally.rb
179
+ - lib/burglar/modules/american_express.rb
180
+ - lib/burglar/version.rb
100
181
  - spec/burglar_spec.rb
101
182
  - spec/spec_helper.rb
102
183
  homepage: https://github.com/akerl/burglar
@@ -119,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
200
  version: '0'
120
201
  requirements: []
121
202
  rubyforge_project:
122
- rubygems_version: 2.5.1
203
+ rubygems_version: 2.6.14
123
204
  signing_key:
124
205
  specification_version: 4
125
206
  summary: Tool for parsing data from bank websites