]> code.delx.au - monosys/blob - scripts/virginmobile.rb
8a6cc874c09d31e311c6347cafe7331092e5d90b
[monosys] / scripts / virginmobile.rb
1 #!/usr/bin/env ruby
2
3 # # Sample config file
4 # ROOTCA = "/etc/ssl/certs/ca-certificates.crt"
5 # SMTPSERVER = "mail.example.com"
6 # FROMADDR = "cron@example.com"
7 # SLEEPTIME = 15
8 # ACCOUNTS = [
9 # ["person1@example.com", "0499999999", "000000", 100, 30],
10 # ["person2@example.com", "0499999998", "000000", 100, 30],
11 # ]
12
13 require 'optparse'
14 require 'net/http'
15 require 'net/https'
16 require 'net/smtp'
17 require 'uri'
18
19 class VirginMobile
20 def initialize(sleep_time, username, password)
21 @sleep_time = sleep_time
22 @username = username
23 @password = password
24 @cookie = nil
25 end
26
27 def do_request(path, form_data=nil)
28 sleep(@sleep_time) # Don't look like a bot
29 http = Net::HTTP.new("www.virginmobile.com.au", 443)
30 http.use_ssl = true
31 if File.exist? ROOTCA
32 http.ca_file = ROOTCA
33 http.verify_mode = OpenSSL::SSL::VERIFY_PEER
34 http.verify_depth = 5
35 end
36 if @cookie
37 req = Net::HTTP::Get.new(path)
38 req["Cookie"] = @cookie
39 end
40 if form_data
41 req = Net::HTTP::Post.new(path)
42 req.form_data = form_data
43 end
44 return http.request(req)
45 end
46
47 def do_login
48 form_data = {
49 "username" => @username,
50 "password" => @password,
51 }
52 res = do_request("/selfcare/MyAccount/LogoutLoginPre.jsp", form_data)
53 @cookie = res.fetch("Set-Cookie")
54
55 while location = res.get_fields("Location")
56 location = URI.parse(location[0])
57 res = do_request(location.path)
58 end
59 end
60
61 def do_logout
62 do_request("/selfcare/dispatch/Logout")
63 end
64
65 def request_bill_preview
66 res = do_request("/selfcare/dispatch/PostPayUnbilledUsage")
67 usage = res.body.scan(/\$([\d\.]*)/).flatten
68 last_bill_date = res.body.gsub(/\n/, '').scan(/Last bill date:.*(\d\d?\/\d\d?\/\d\d\d\d)/).flatten
69 return usage, last_bill_date
70 end
71
72 def request_mobile_browsing
73 res = do_request("/selfcare/dispatch/DataUsageRequest")
74 data_usage = res.body.scan(/USAGE: ([\d\.]*)MB/).flatten
75 return data_usage
76 end
77
78 def dump_result(res)
79 res.each_capitalized do |key, value|
80 print "#{key}: #{value}\n"
81 end
82 print res.body + "\n"
83 end
84 end
85
86 def check_usage(sleep_time, ignore_limits, destination, username, password, usageLimit, dataLimit)
87 message = ""
88 data = VirginMobile.new(sleep_time, username, password)
89 data.do_login
90
91 usage, last_bill_date = data.request_bill_preview
92 usage.each do |x|
93 if ignore_limits or (usageLimit >= 0 and x.to_f >= usageLimit)
94 message += "Unbilled usage: $#{x}\n"
95 end
96 end
97
98 data_usage = data.request_mobile_browsing
99 data_usage.each do |x|
100 if ignore_limits or (dataLimit >= 0 and x.to_f >= dataLimit)
101 message += "Data usage: #{x} MiB\n"
102 end
103 end
104
105 data.do_logout
106
107 if message.length > 0
108 return destination, <<EOT
109 From: #{FROMADDR}
110 To: #{destination}
111 Subject: Virgin Mobile Usage
112
113 Virgin Mobile Usage
114 -------------------
115
116 Previous bill: #{last_bill_date}
117 #{message}
118
119 https://www.virginmobile.com.au/selfcare/MyAccount/login.jsp
120
121 EOT
122
123 end
124 end
125
126 def send_emails(emails)
127 Net::SMTP.start(SMTPSERVER, 25) do |smtp|
128 emails.each do |destination, message|
129 smtp.send_message(message, FROMADDR, destination)
130 end
131 end
132 end
133
134 def do_email(sleep_time, ignore_limits)
135 emails = []
136 ACCOUNTS.each do |args|
137 if ret = check_usage(sleep_time, ignore_limits, *args)
138 emails.push(ret)
139 end
140 end
141 send_emails(emails)
142 end
143
144 def do_print(sleep_time, ignore_limits)
145 emails = []
146 ACCOUNTS.each do |args|
147 if ret = check_usage(sleep_time, ignore_limits, *args)
148 print ret[1]
149 end
150 end
151 end
152
153 def main
154 ignore_limits = dry_run = fast = false
155 OptionParser.new do |opts|
156 opts.banner = "Usage: #{$0} [options] config\n"
157 opts.on("--fast", "Don't sleep between connections") do |v|
158 fast = v
159 end
160 opts.on("--dry-run", "Don't send emails, just print them") do |v|
161 dry_run = v
162 end
163 opts.on("--ignore-limits", "Treat all limits as 0") do |v|
164 ignore_limits = v
165 end
166 end.parse!
167
168 config = ARGV[0]
169 begin
170 eval File.open(config).read
171 rescue
172 $stderr.print "Error parsing config file!\n\n"
173 raise
174 end
175
176 if fast
177 sleep_time = 0
178 else
179 sleep_time = SLEEPTIME
180 end
181
182 if dry_run
183 do_print(sleep_time, ignore_limits)
184 else
185 do_email(sleep_time, ignore_limits)
186 end
187 end
188
189 if __FILE__ == $0
190 main
191 end
192