File Coverage

blib/lib/WebService/Futu.pm
Criterion Covered Total %
statement 30 77 38.9
branch 7 24 29.1
condition 3 6 50.0
subroutine 8 15 53.3
pod 6 6 100.0
total 54 128 42.1


line stmt bran cond sub pod time code
1             package WebService::Futu;
2              
3 2     2   45553 use warnings;
  2         6  
  2         64  
4 2     2   11 use strict;
  2         5  
  2         67  
5              
6 2     2   2231 use LWP::UserAgent;
  2         113545  
  2         67  
7 2     2   2381 use JSON::XS;
  2         20801  
  2         166  
8 2     2   20 use HTTP::Status qw(:constants :is status_message);
  2         5  
  2         1401  
9 2     2   1899 use HTTP::Cookies;
  2         20230  
  2         68  
10              
11 2     2   2586 use Data::Dumper;
  2         18176  
  2         1896  
12              
13             =head1 NAME
14              
15             WebService::Futu - Perl interface to the Futu API
16              
17             =head1 VERSION
18              
19             Version 0.01
20              
21             =cut
22              
23             our $VERSION = '0.02';
24              
25              
26             =head1 SYNOPSIS
27              
28             use WebService::Futu;
29            
30             my $ws = WebService::Futu->new( user => 'username',
31             pass => 'password' );
32              
33             my $body = $ws->perform_get('/api/personal');
34              
35             my $trans = {
36             date => {
37             day => 12,
38             month => 10,
39             year => 2010
40             },
41             amount => 100,
42             tags => {
43             dir => 'out',
44             how => 'platba v hotovosti',
45             regularity => "b\x{11b}\x{17e}n\x{e1}",
46             what => "Jidlo",
47             whom => "Tesco",
48             who => "",
49             product => "cash",
50             card => ""
51             },
52             note => 'Something to eat.'
53             };
54              
55             $ws->perform_post('/api/transaction/', $trans));
56              
57             =head1 DESCRIPTION
58              
59             Library for comuniccation with Futu API.
60              
61             =head1 METHODS
62              
63             =over 4
64              
65             =item new( [user => $username|id => $futuid], pass => $password, url => $url )
66              
67             Call new() to create a new Futu object.
68             You have to pass username or futu id and password.
69              
70             It is possible to pass base url for API queries with parameter url. (default 'http://www.futu.cz')
71              
72             Example:
73              
74             my $bc = WebService::Futu->new( user => $username,
75             pass => $password );
76             =cut
77              
78             sub new {
79 3     3 1 3810 my $class = shift;
80 3         11 my %hash = @_;
81            
82 3 50 66     36 unless ( (defined($hash{'user'}) or defined($hash{'id'})) && defined($hash{'pass'}) ) {
      33        
83 0         0 die "Must define user and pass to initialise object";
84             }
85 3         6 my $self;
86 3 100       14 $self->{_user} = $hash{'user'} if exists $hash{'user'};
87 3 100       15 $self->{_id} = $hash{'id'} if exists $hash{'id'};
88 3         7 $self->{_pass} = $hash{'pass'};
89 3 100       19 $self->{_url} = exists $hash{'url'} ? $hash{'url'} : 'https://www.futu.cz';
90            
91 3         15 return bless($self, $class);
92             }
93              
94             ### ERROR MESSAGES
95             =pod
96              
97             =item error()
98              
99             Returns any error messages as a string.
100              
101             =cut
102              
103             sub error {
104 0     0 1   return shift->{'_error'};
105             }
106              
107             =pod
108              
109             =item perform_get()
110              
111             Perform request on the server.
112             Automatically request authentication token.
113              
114             my $personal = $self->perform_get('/api/personal');
115            
116             =cut
117              
118             sub perform_get {
119 0     0 1   my ($self, @other) = @_;
120 0           return $self->_perform_auth('GET', @other);
121             }
122              
123             =pod
124              
125             =item perform_post($content)
126              
127             Perform post on the server.
128             Automatically request authentication token.
129             $content is used for sending content.
130              
131             my $personal = $self->perform_post('/api/transaction/', $content);
132            
133             =cut
134              
135             sub perform_post {
136 0     0 1   my ($self, @other) = @_;
137 0           return $self->_perform_auth('POST', @other);
138             }
139              
140             =pod
141              
142             =item perform_put($content)
143              
144             Perform put on the server.
145             Automatically request authentication token.
146             $content is used for sending content.
147              
148             my $personal = $self->perform_put('/api/transaction/123', $content);
149            
150             =cut
151              
152             sub perform_put {
153 0     0 1   my ($self, @other) = @_;
154 0           return $self->_perform_auth('PUT', @other);
155             }
156              
157             =item perform_delete($content)
158              
159             Perform delete on the server.
160             Automatically request authentication token.
161             $content is used for sending content.
162              
163             my $personal = $self->perform_delete('/api/transaction/123', $content);
164            
165             =cut
166              
167             sub perform_delete {
168 0     0 1   my ($self, @other) = @_;
169 0           return $self->_perform_auth('DELETE', @other);
170             }
171              
172             sub _perform_auth {
173 0     0     my ($self, $method, $query, $content) = @_;
174              
175 0 0         my $json_content = encode_json($content) if $content;
176 0           my $max = 10;
177              
178 0           for (my $i = 0; $i < $max; $i++){
179            
180 0           my $body = $self->_perform($method, $query, $json_content);
181              
182             # run command
183 0 0         if ($body->code eq HTTP_OK) {
    0          
184 0 0         if ($body->content){
185 0           return decode_json($body->content)
186             }else{
187 0           return {};
188             };
189             } elsif ($body->code eq HTTP_UNAUTHORIZED) {
190             # make auth content
191 0           my $auth_content = { password => $self->{_pass} };
192 0 0         if ( $self->{_user} ){
    0          
193 0           $auth_content->{email} = $self->{_user};
194             }elsif( $self->{_id} ){
195 0           $auth_content->{id} = $self->{_id};
196             }
197             # auth request
198 0           my $auth_body = $self->_perform('POST','/auth/', encode_json($auth_content));
199              
200 0 0         if ( $auth_body->code eq HTTP_OK ){
201 0           next;
202             }else{
203 0           $self->{'_error'} = $body->status_line;
204 0           return 0;
205             }
206             }else{
207 0           $self->{'_error'} = $body->status_line;
208 0           return 0
209             }
210             }
211              
212 0           return 0;
213             }
214              
215             sub _perform {
216 0     0     my $self = shift;
217 0           my $method = shift;
218 0           my $query = shift;
219 0           my $content = shift;
220              
221 0           my $url = $self->{'_url'}.$query;
222              
223             # user agent initialization
224 0           my $ua = LWP::UserAgent->new;
225 0           my $req = HTTP::Request->new($method => $url);
226            
227 0           my $cookie_jar = HTTP::Cookies->new(
228             file => "/tmp/futu_cookies.dat",
229             autosave => 1,
230             ignore_discard => 1
231             );
232              
233 0           $ua->cookie_jar( $cookie_jar );
234            
235             # http params
236 0           $req->header('Accept' => 'application/json');
237 0           $req->content_type('application/json');
238 0 0         if ($content){
239 0           $req->content_length(length($content));
240 0           $req->content($content);
241             }
242              
243 0           my $body = $ua->request($req);
244             #print STDERR Dumper($body);
245              
246 0           return $body;
247             }
248              
249              
250              
251             =back
252              
253             =head1 AUTHOR
254              
255             Vaclav Dovrtel, C<< >>
256              
257             =head1 BUGS
258              
259             Please report any bugs or feature requests to C, or through
260             the web interface at L. I will be notified, and then you'll
261             automatically be notified of progress on your bug as I make changes.
262              
263             =head1 SUPPORT
264              
265             You can find documentation for this module with the perldoc command.
266              
267             perldoc WebService::Futu
268              
269              
270             You can also look for information at:
271              
272             =over 4
273              
274             =item * RT: CPAN's request tracker
275              
276             L
277              
278             =item * AnnoCPAN: Annotated CPAN documentation
279              
280             L
281              
282             =item * CPAN Ratings
283              
284             L
285              
286             =item * Search CPAN
287              
288             L
289              
290             =back
291              
292              
293             =head1 ACKNOWLEDGEMENTS
294              
295              
296             =head1 LICENSE AND COPYRIGHT
297              
298             Copyright 2010 Vaclav Dovrtel.
299              
300             This program is free software; you can redistribute it and/or modify it
301             under the terms of either: the GNU General Public License as published
302             by the Free Software Foundation; or the Artistic License.
303              
304             See http://dev.perl.org/licenses/ for more information.
305              
306              
307             =cut
308              
309             1; # End of WebService::Futu