1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
-
-
-
-
-
-
+
-
+
-
-
-
+
+
+
+
+
-
+
-
+
-
-
+
+
+
+
-
+
-
+
+
+
-
-
+
+
+
+
-
-
+
+
+
+
+
+
-
+
-
+
-
+
-
+
-
-
+
+
|
require 'optparse'
require 'mechanize'
require 'nokogiri'
optparse = OptionParser.new do |opts|
opts.on('-d', '--date DATE', "Date") { |d| Date_back = d }
end
optparse.parse!
class Smile
attr_writer :date_back
attr_reader :page
attr_reader :transactions
def initialize
@a = Mechanize.new
@transactions = []
end
def transactions(date_back)
@date_back = Date.parse(date_back)
logon_start
logon_passcode
logon_other
logon_bulletin
recent_transactions
previous_statements
#previous calls recent (I could change this though so it reads more sensibly here)
write_ledger
end
#All these private
#Note sure how valid it is breaking these out into separate methods
#Might make more sense in a rakefile as separate tasks with dependencies,
#but these methods can't be used alone
#Also, really not sure about using instance variables instead of passing args
def logon_start
@page = @a.get("https://banking.smile.co.uk/SmileWeb/start.do")
page = @a.get("https://banking.smile.co.uk/SmileWeb/start.do")
#Since dealing with sensitive logon data don't want to get it from anywhere apart from keyboard input
#Sortcode and Account number login
puts "Enter sortcode"
sortCode = gets.strip
puts "Enter Account number"
accountNumber = gets.strip
@page.form.sortCode = sortCode
@page.form.accountNumber = accountNumber
@page = @page.form.submit
page.form.sortCode = sortCode
page.form.accountNumber = accountNumber
page = page.form.submit
end
def logon_passcode
#Requires
page = logon_start
#Passcode login
doc = Nokogiri::HTML(@page.body)
doc = Nokogiri::HTML(page.body)
puts doc.xpath("//label")[0].text
@page.form.firstPassCodeDigit = gets.strip
page.form.firstPassCodeDigit = gets.strip
puts doc.xpath("//label")[1].text
@page.form.secondPassCodeDigit = gets.strip
@page = @page.form.submit
page.form.secondPassCodeDigit = gets.strip
page = page.form.submit
end
def logon_other
#requires
page = logon_passcode
#Other logon details
@page.form.fields.each do |field|
page.form.fields.each do |field|
unless field.type == "hidden"
puts field.name
field.value = gets.strip
end
end
@page = @page.form.submit
page = page.form.submit
end
def logon_bulletin
#requires
page = logon_other
if @page.form.action.include?("bulletinBoard")
@page = @page.form.submit
if page.form.action.include?("bulletinBoard")
page = page.form.submit
end
end
def recent_transactions
#requires
page = logon_bulletin
@page = @a.click(@page.link_with(:text => "current account"))
get_transactions
page = @a.click(page.link_with(:text => "current account"))
get_transactions(page)
#Need to return this
page
end
def previous_statements
#requires
page = recent_transactions
#Previous statements
@page = @a.click(@page.link_with(:text => "previous statements"))
page = @a.click(page.link_with(:text => "previous statements"))
#Get first page of previous statements
@page = @a.click(@page.links_with(:href => %r{getDomestic} )[0])
page = @a.click(page.links_with(:href => %r{getDomestic} )[0])
date = Date.today
until date < @date_back
get_transactions
get_transactions(page)
#On previous statement pages most recent transaction is at bottom
#This is opposite to recent item page
date = @transactions[-1][:date]
@page = @a.click(@page.link_with(:text => "previous statement page"))
page = @a.click(page.link_with(:text => "previous statement page"))
end
end
def get_transactions
doc = Nokogiri::HTML(@page.body)
def get_transactions(page)
doc = Nokogiri::HTML(page.body)
#Look for summaryTable
rows = doc.xpath("//table[@class='summaryTable']//tr")
#Skip first row (table headers, ths)
rows = rows[1..-1]
transactions = []
rows.each do |row|
#Skip last row, maybe
|