File Coverage

blib/lib/Business/UTV.pm
Criterion Covered Total %
statement 65 102 63.7
branch 15 30 50.0
condition 3 9 33.3
subroutine 8 9 88.8
pod 3 4 75.0
total 94 154 61.0


line stmt bran cond sub pod time code
1             package Business::UTV;
2              
3 6     6   421537 use strict;
  6         13  
  6         226  
4 6     6   37 use warnings;
  6         12  
  6         188  
5              
6 6     6   1175 use LWP::UserAgent;
  6         63627  
  6         152  
7 6     6   6417 use HTTP::Request::Common;
  6         23843  
  6         529  
8 6     6   48 use URI::Escape;
  6         14  
  6         7119  
9              
10             our $VERSION = 0.05;
11             our $errstr = undef;
12              
13             sub login
14             {
15 5     5 1 3413 my ( $class , $username , $password , $atts ) = @_;
16              
17 5         20 errstr( "" );
18            
19 5         12 my $name = $atts->{"name"};
20 5         10 my $login_url = "https://ssl2.u.tv/clicksilveraccountie/gologin.asp";
21 5         18 my $usage_url = "https://ssl2.u.tv/clicksilveraccountie/onlineusage.asp?id=$username";
22 5         21 my $newindex_url = "https://ssl2.u.tv/clicksilveraccountie/newindex.asp";
23            
24 5         12 my $statement_url = "https://ssl2.u.tv/clicksilveraccountie/statementbeta.asp";
25            
26 5         45 my $ua = LWP::UserAgent->new();
27              
28 5         101 my $login_request = $ua->post( $login_url ,
29             { "id" => $username , "password" => $password } ,
30             "Referer" => $newindex_url );
31              
32 5 100       807 if( $login_request->is_error() )
33             {
34 1         14 errstr( "Login failed : http problem" );
35 1         19 return undef;
36             }
37              
38 4         89 my $login = $login_request->content();
39 4         55 my %data = ();
40              
41 4 100       73 unless( $login =~ /\Q$name\E/ )
42             {
43 2         14 errstr( "Login failed : your name '$name' not matched" );
44 2         41 return undef;
45             }
46              
47 2         10 while( $login =~ /]+)['"]?>/ig )
48             {
49 0         0 $data{$1}=$2;
50             }
51            
52 2         8 my %self = %$atts;
53            
54 2         6 $self{"ua"} = $ua;
55 2         3 $self{"login_url"} = $login_url;
56 2         5 $self{"usage_url"} = $usage_url;
57 2         4 $self{"statement_url"} = $statement_url;
58            
59 2         5 $self{"username"} = $username;
60 2         4 $self{"password"} = $password;
61 2         6 $self{"_data"} = \%data;
62            
63 2         30 bless( \%self , $class );
64             }
65              
66              
67             sub usage
68             {
69 8     8 1 11614 my ( $self ) = @_;
70              
71 8         14 errstr( "" );
72            
73 8         9 my $upload;
74             my $download;
75              
76 8         53 my $usage_request = $self->{"ua"}->get( $self->{"usage_url"} );
77              
78 8 100       405 if( $usage_request->is_error() )
79             {
80 1         15 errstr( "Usage failed : http problem" );
81 1         9 return undef;
82             }
83              
84 7         67 my $usage = $usage_request->content();
85            
86 7 100       81 if( $usage =~ /Incoming:\s*(\d+(\.\d+)?)MB/ )
87             {
88 5         10 $upload = $1;
89             }
90 7 100       24 if( $usage =~ /Outgoing:\s*(\d+(\.\d+)?)MB/ )
91             {
92 5         9 $download = $1;
93             }
94              
95 7 100 100     42 if( defined($upload) && defined($download) )
96             {
97 4         25 return { "upload" => $upload , "download" => $download };
98             }
99             else
100             {
101 3         7 errstr( "Could not retrieve upload and download usage" );
102 3         22 return undef;
103             }
104             }
105              
106              
107             sub current_statement
108             {
109 0     0 1 0 my ( $self ) = @_;
110              
111 0         0 errstr( "" );
112            
113 0         0 my $total = undef;
114 0         0 my $mytotal = 0;
115 0         0 my @calls = ();
116            
117 0         0 my $referer = "https://ssl2.u.tv/clicksilveraccountie/menu.asp" .
118             "?usersname=" . uri_escape( $self->{"_data"}->{"usersname"} ) .
119             "&tariffcode=" . uri_escape( $self->{"_data"}->{"tariffcode"} );
120              
121 0         0 my $statement_request = $self->{"ua"}->post(
122             $self->{"statement_url"} ,
123             { "custid" => $self->{"username"} },
124             "Referer" => $referer
125             );
126            
127 0         0 my $statement = $statement_request->content();
128 0         0 $statement =~ s/]+>//ig;
129 0         0 $statement =~ s/<\/font>//ig;
130 0         0 $statement =~ s/ //g;
131              
132 0         0 while( $statement =~ /]*>(.*?)<\/tr>/isg )
133             {
134 0         0 my $line = $1;
135 0 0       0 if( $line =~ /total/i )
136             {
137 0 0       0 if( $line =~ /€(.+)\s/ )
138             {
139 0         0 $total = $1;
140             }
141             }
142            
143 0         0 my $count = 0;
144 0         0 my @fields = ();
145 0         0 my $call = {};
146 0         0 while( $line =~ /]+>(.*?)<\/td>/g )
147             {
148 0 0       0 if( length($1) > 0 )
149             {
150 0         0 push( @fields , $1 );
151             }
152 0         0 $count++;
153             }
154              
155 0 0 0     0 if( $count == 8 && scalar( @fields ) == 6 && $fields[0] ne "Date" )
      0        
156             {
157 0         0 @$call{ ( "date" , "time" , "phone_number" , "type" , "length" , "cost" ) } = @fields;
158 0 0       0 if( $call->{"cost"} eq "FREE!" )
159             {
160 0         0 $call->{"cost"} = 0;
161             }
162 0         0 $mytotal = $mytotal + $call->{"cost"};
163 0         0 push( @calls , $call );
164             }
165             }
166              
167 0 0       0 if( !defined( $total ) )
168             {
169 0         0 errstr( "Could not find their total" );
170 0         0 return undef;
171             }
172 0 0       0 if( abs($total-$mytotal) > 0.1 )
173             {
174 0         0 errstr( "I calculated total of $mytotal but they said total is $total" );
175 0         0 return undef;
176             }
177 0         0 return ( $total , \@calls );
178             }
179              
180             sub errstr
181             {
182 23     23 0 235 my ( $error ) = @_;
183            
184 23 50       65 if( defined( $error ) )
185             {
186 23         32 $errstr = $error;
187 23 100       54 if( length( $errstr ) )
188             {
189 10         133 warn( $errstr );
190             }
191             else
192             {
193 13         23 $errstr = undef;
194             }
195             }
196 23         651 return $errstr;
197             }
198              
199             =head1 NAME
200              
201             Business::UTV - Module for retrieiving UTV internet account information
202              
203             =head1 SYNOPSIS
204              
205             use Business::UTV;
206             my $utv = Business::UTV->login( $id , $password , { "name" => "me" } );
207             my $usage = $utv->usage();
208             print "Upload = " . $usage->{"upload"} . "MB\n";
209              
210             =head1 DESCRIPTION
211              
212             This module enables you to access your UTV account information using perl.
213              
214             Currently the only supported data is your current monthly upload/download
215             usage and call data from your latest phone bill.
216              
217             This module provides the following methods
218              
219             =head2 login
220              
221             $utv = Business::UTV->login( $id , $password , { "name" => $name }
222              
223             The constructor takes your utv id , password and a hash reference
224             and logs into the utv website. Login is verified be checking the
225             name of the account holder is correctly returned.
226              
227             On failure undef is returned and an error message stored in $Business::UTV::errstr
228              
229              
230             =head2 usage
231              
232             my $usage = $utv->usage();
233             print "Upload - " . $usage->{"upload"} . "\n";
234             print "Download - " . $usage->{"download"} . "\n";
235              
236             This method retrieves the accounts current upload and download in
237             megabytes as a hash reference.
238              
239             On failure undef is returned and an error message is stored in $Business::UTV::errstr
240              
241             =head2 current_statement
242              
243             my ( $total , $calls ) = $utv->current_statement();
244              
245             This method returns the total of the latest bill and details of any phone calls.
246              
247             Calls are returned as an array reference with each call a hash ref with the following
248             fields
249              
250             date
251             time
252             phone_number
253             type
254             length
255             cost
256              
257             On failure undef is returned and an error message is stored in $Business::UTV::errstr
258              
259             =head1 LIMITATIONS
260              
261             By definition I am limited to my own account when writting this module.
262             If some features do not work as expected or at all contact me and I'll
263             do my best to add support for different account configurations.
264              
265             =head1 WARNING
266              
267             This warning is (mostly) from Simon Cozens' Finance::Bank::LloydsTSB, and seems almost as apt here.
268            
269             This is code for pretending to be you online, and that could mean your money, and that means BE CAREFUL.
270             You are encouraged, nay, expected, to audit the source of this module yourself to reassure yourself
271             that I am not doing anything untoward with your account data. This software is useful to me, but is
272             provided under NO GUARANTEE, explicit or implied.
273              
274             =head1 SEE ALSO
275              
276             utv_usage_applet.pl
277             utv_usage_tray.pl
278              
279             =cut
280              
281             1;