syrup 0.0.1

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.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.swp
2
+ **/*.swp
3
+ *.gem
4
+ .bundle
5
+ Gemfile.lock
6
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,3 @@
1
+ 0.0.1 (Date)
2
+
3
+ * initial release
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in syrup.gemspec
4
+ gemspec
data/README.rdoc ADDED
@@ -0,0 +1,28 @@
1
+ = Syrup
2
+
3
+ Syrup is made from a yummy maple extract.
4
+
5
+ == Installation
6
+
7
+ The latest version of Syrup can be installed with Rubygems:
8
+
9
+ [sudo] gem install "syrup"
10
+
11
+ In <b>Rails 3</b>, add this to your Gemfile and run the +bundle+ command.
12
+
13
+ gem "syrup"
14
+
15
+ In <b>Rails 2</b>, add this to your environment.rb file.
16
+
17
+ config.gem "syrup"
18
+
19
+ == Getting Started
20
+
21
+ Spread it all over your pancakes and enjoy!
22
+
23
+ == Usage
24
+
25
+ zions = Syrup::Extract.from_institution(:zions_bank)
26
+ zions.fetch_accounts.each do |act|
27
+ puts name + " " + name.current_balance
28
+ end
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'bundler'
2
+ require 'rspec/core/rake_task'
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ desc "Run RSpec"
7
+ RSpec::Core::RakeTask.new do |t|
8
+
9
+ end
10
+
11
+ task :default => :spec
@@ -0,0 +1,5 @@
1
+ module Syrup
2
+ class Account
3
+ attr_accessor :name, :id, :account_number, :current_balance, :available_balance, :type
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ module Syrup
2
+ class Extract
3
+ def self.from_institution(institution_sym)
4
+ class_name = institution_sym.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
5
+ Institutions.const_get(class_name).new
6
+ end
7
+
8
+ def self.list_institutions
9
+ Institutions::AbstractInstitution.subclasses.map do |subclass|
10
+ subclass.institution_name
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,26 @@
1
+ module Syrup
2
+ module Institutions
3
+ class AbstractInstitution
4
+
5
+ def self.inherited(subclass)
6
+ @subclasses ||= []
7
+ @subclasses << subclass
8
+ end
9
+
10
+ def self.subclasses
11
+ @subclasses
12
+ end
13
+
14
+ protected
15
+
16
+ def agent
17
+ @agent || Mechanize.new
18
+ end
19
+
20
+ def parse_currency(currency)
21
+ currency.scan(/[0-9.]/).join.to_f
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,111 @@
1
+ module Syrup
2
+ module Institutions
3
+ class ZionsBank < AbstractInstitution
4
+ def self.institution_name
5
+ "Zions Bank"
6
+ end
7
+
8
+ attr_accessor :username, :password, :secret_qas
9
+
10
+ def fetch_accounts
11
+ ensure_authenticated
12
+
13
+ # List accounts
14
+ page = agent.get('https://banking.zionsbank.com/ibuir/displayAccountBalance.htm')
15
+ json = ActiveSupport::JSON.decode(page.body)
16
+
17
+ accounts = []
18
+ json['accountBalance']['depositAccountList'].each do |account|
19
+ new_account = Account.new
20
+ new_account.name = account['name']
21
+ new_account.id = account['accountId']
22
+ new_account.account_number = account['number']
23
+ new_account.current_balance = parse_currency(account['currentAmt'])
24
+ new_account.available_balance = parse_currency(account['availableAmt'])
25
+ new_account.type = :deposit
26
+
27
+ accounts << new_account
28
+ end
29
+ json['accountBalance']['creditAccountList'].each do |account|
30
+ new_account = Account.new
31
+ new_account.name = account['name']
32
+ new_account.id = account['accountId']
33
+ new_account.account_number = account['number']
34
+ new_account.current_balance = parse_currency(account['balanceDueAmt'])
35
+ new_account.type = :credit
36
+
37
+ accounts << new_account
38
+ end
39
+
40
+ accounts
41
+ end
42
+
43
+ def fetch_transactions
44
+ ensure_authenticated
45
+
46
+ # https://banking.zionsbank.com/zfnb/userServlet/app/bank/user/register_view_main?actAcct=498282&sortBy=Default&sortOrder=Default
47
+
48
+ # The transactions table is messy. Cells we want either have data, curr, datagrey, or currgrey css class
49
+ end
50
+
51
+ private
52
+
53
+ def ensure_authenticated
54
+
55
+ # Check to see if already authenticated
56
+ page = agent.get('https://banking.zionsbank.com/ibuir')
57
+ if page.body.include?("SessionTimeOutException") # || (page.links.size > 0 && page.links.first.href == "http://www.zionsbank.com")
58
+
59
+ raise ArgumentError, "Username must be supplied before authenticating" unless self.username
60
+ raise ArgumentError, "Password must be supplied before authenticating" unless self.password
61
+
62
+ @agent = Mechanize.new
63
+
64
+ # Enter the username
65
+ page = agent.get('https://zionsbank.com')
66
+ form = page.form('logonForm')
67
+ form.publicCred1 = username
68
+ page = form.submit
69
+
70
+ # If the supplied username is incorrect, raise an exception
71
+ raise "Invalid username" if page.title == "Error Page"
72
+
73
+ # Go on to the next page
74
+ page = page.links.first.click
75
+
76
+ # Find the secret question
77
+ question = page.search('div.form_field')[2].css('div').inner_text
78
+
79
+ # If the answer to this question was not supplied, raise an exception
80
+ raise question unless secret_qas[question]
81
+
82
+ # Enter the answer to the secret question
83
+ form = page.forms.first
84
+ form["challengeEntry.answerText"] = secret_qas[question]
85
+ form.radiobutton_with(:value => 'false').check
86
+ submit_button = form.button_with(:name => '_eventId_submit')
87
+ page = form.submit(submit_button)
88
+
89
+ # If the supplied answer is incorrect, raise an exception
90
+ raise "Invalid answer" unless page.search('#errorComponent').empty?
91
+
92
+ # Enter the password
93
+ form = page.forms.first
94
+ form.privateCred1 = password
95
+ submit_button = form.button_with(:name => '_eventId_submit')
96
+ page = form.submit(submit_button)
97
+
98
+ # If the supplied password is incorrect, raise an exception
99
+ raise "Invalid password" unless page.search('#errorComponent').empty?
100
+
101
+ # Clicking this link logs us into the banking.zionsbank.com domain
102
+ page = page.links.first.click
103
+
104
+ end
105
+
106
+ true
107
+ end
108
+
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,10 @@
1
+ module Syrup
2
+ class Transaction
3
+ attr_accessor :payee, :amount, :posted_at
4
+ def initialize(attr_hash)
5
+ attr_hash.each do |k, v|
6
+ instance_variable_set "@#{k}", v
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module Syrup
2
+ VERSION = "0.0.1"
3
+ end
data/lib/syrup.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'date'
2
+ require 'mechanize'
3
+ require 'active_support/json'
4
+ require 'syrup/extract'
5
+ require 'syrup/account'
6
+ require 'syrup/transaction'
7
+
8
+ # require all institutions
9
+ require 'syrup/institutions/abstract_institution'
10
+ Dir[File.dirname(__FILE__) + '/syrup/institutions/*.rb'].each {|file| require file }
@@ -0,0 +1,25 @@
1
+ #require 'rubygems'
2
+ #require 'bundler/setup'
3
+
4
+ Bundler.require(:default)
5
+
6
+ #RSpec.configure do |config|
7
+ # config.mock_with :rr
8
+ # config.before(:each) do
9
+ #
10
+ # end
11
+ #end
12
+
13
+
14
+ # pass in username, password, secret questions
15
+
16
+ # zions.fetch_accounts
17
+ # should I store things?
18
+ # List accounts
19
+ # * create an array of Account objects
20
+
21
+ # account.transactions OR account.fetch_transactions
22
+ # zions.
23
+ # When getting transactions
24
+ # * create an array of Transaction objects
25
+ # * populate as many variables on Account as you can (eg. current_balance, etc.)
@@ -0,0 +1,12 @@
1
+ require "spec_helper"
2
+
3
+ describe Syrup::Extract do
4
+ it "lists all institutions" do
5
+ Syrup::Extract.list_institutions.size.should == 1
6
+ puts Syrup::Extract.list_institutions
7
+ end
8
+
9
+ it "creates a Zions Bank institution" do
10
+ Syrup::Extract.from_institution(:zions_bank).class.should == Syrup::Institutions::ZionsBank
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ require "spec_helper"
2
+
3
+ describe Syrup::Institutions::ZionsBank do
4
+ it "lists all accounts"
5
+ end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ describe Syrup::Transaction do
4
+ before(:all) do
5
+ @transaction = Syrup::Transaction.new :amount => 10, :payee => "Newegg", :posted_at => DateTime.now
6
+ end
7
+
8
+ it "has an amount" do
9
+ @transaction.amount.should_not be_nil
10
+ end
11
+
12
+ it "has a payee" do
13
+ @transaction.payee.should_not be_nil
14
+ end
15
+
16
+ it "has a posted-at date" do
17
+ @transaction.posted_at.should_not be_nil
18
+ end
19
+
20
+ end
data/syrup.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "syrup/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "syrup"
7
+ s.version = Syrup::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Don Wilson"]
10
+ s.email = ["dontangg@gmail.com"]
11
+ s.homepage = "http://github.com/dontangg/syrup"
12
+ s.summary = %q{Simple account balance/transactions extractor.}
13
+ s.description = %q{Simple account balance/transactions extractor by scraping bank websites.}
14
+
15
+ s.add_dependency "mechanize"
16
+ s.add_dependency "activesupport"
17
+
18
+ s.add_development_dependency "rspec"
19
+
20
+ s.rubyforge_project = s.name
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+ end
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: syrup
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Don Wilson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-02-25 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: mechanize
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: "0"
36
+ type: :runtime
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: rspec
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id003
49
+ description: Simple account balance/transactions extractor by scraping bank websites.
50
+ email:
51
+ - dontangg@gmail.com
52
+ executables: []
53
+
54
+ extensions: []
55
+
56
+ extra_rdoc_files: []
57
+
58
+ files:
59
+ - .gitignore
60
+ - .rspec
61
+ - CHANGELOG.rdoc
62
+ - Gemfile
63
+ - README.rdoc
64
+ - Rakefile
65
+ - lib/syrup.rb
66
+ - lib/syrup/account.rb
67
+ - lib/syrup/extract.rb
68
+ - lib/syrup/institutions/abstract_institution.rb
69
+ - lib/syrup/institutions/zions_bank.rb
70
+ - lib/syrup/transaction.rb
71
+ - lib/syrup/version.rb
72
+ - spec/spec_helper.rb
73
+ - spec/syrup/extract_spec.rb
74
+ - spec/syrup/institutions/zions_bank_spec.rb
75
+ - spec/syrup/transaction_spec.rb
76
+ - syrup.gemspec
77
+ has_rdoc: true
78
+ homepage: http://github.com/dontangg/syrup
79
+ licenses: []
80
+
81
+ post_install_message:
82
+ rdoc_options: []
83
+
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: "0"
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: "0"
98
+ requirements: []
99
+
100
+ rubyforge_project: syrup
101
+ rubygems_version: 1.5.0
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: Simple account balance/transactions extractor.
105
+ test_files:
106
+ - spec/spec_helper.rb
107
+ - spec/syrup/extract_spec.rb
108
+ - spec/syrup/institutions/zions_bank_spec.rb
109
+ - spec/syrup/transaction_spec.rb