File Coverage

blib/lib/WWW/DreamHost/API.pm
Criterion Covered Total %
statement 40 51 78.4
branch 7 16 43.7
condition 2 3 66.6
subroutine 8 9 88.8
pod 4 4 100.0
total 61 83 73.4


line stmt bran cond sub pod time code
1             package WWW::DreamHost::API;
2              
3             # $Id: API.pm 41 2013-06-25 07:31:41Z stro $
4              
5 2     2   7491 use strict;
  2         2  
  2         58  
6 2     2   10 use warnings;
  2         3  
  2         42  
7 2     2   8 use Carp;
  2         2  
  2         150  
8              
9             our $VERSION = '1.06';
10              
11 2     2   2019 use LWP::UserAgent;
  2         260430  
  2         83  
12 2     2   3766 use Data::UUID;
  2         2070  
  2         1291  
13              
14             =head1 NAME
15              
16             WWW::DreamHost::API - Perl interface to DreamHost Web Panel API
17              
18             =head1 VERSION
19              
20             1.06
21              
22             =head1 SYNOPSIS
23              
24             my $key = '6SHU5P2HLDAYECUM';
25             my $api = new WWW::DreamHost::API($key);
26             my $res = $api->command('api-list_accessible_cmds');
27             print Data::Dumper->Dump([$res]);
28              
29             =head1 DESCRIPTION
30              
31             WWW::DreamHost::API provides a simple Perl interface to DreamHost Web Panel API.
32              
33             Read more about API commands at L
34              
35             =head1 METHODS
36              
37             =head2 new ( $key )
38              
39             Creates WWW::DreamHost::API object
40              
41             =cut
42              
43             sub new {
44 1     1 1 20837 my $class = shift;
45 1         2 my ($key) = @_;
46              
47 1 50       6 croak 'You should provide a key in order to use WWW::DreamHost::API' unless defined $key;
48              
49 1         11 my $self = {
50             '__key' => $key,
51             '__ua' => LWP::UserAgent->new('agent' => 'WWW-DreamHost-API/' . $VERSION),
52             '__ug' => Data::UUID->new(),
53             '__uniq' => int(rand(time())),
54              
55             };
56              
57 1         246313 $self->{'__ua'}->env_proxy();
58              
59             # Check if JSON is available
60 1 50       23106 if (eval { require JSON; }) {
  1         441  
61 0         0 $self->{'__format'} = 'json';
62             } else {
63 1         4 $self->{'__format'} = 'perl';
64             }
65              
66 1         7 bless $self, $class;
67 1         6 return $self;
68             }
69              
70             =head2 uuid ( )
71              
72             Returns UUID. Probably actually unique (randomly based on key and run time).
73             Don't worry, if it's not, because it's reinitializing in case of failure (though I cannot imagine how it can happen).
74              
75             =cut
76              
77             sub uuid {
78 21     21 1 36 my $self = shift;
79 21         843 my $uuid = $self->{'__ug'}->create_from_name('WWW-DreamHost-API-'. $self->{'__key'}, $self->{'__uniq'}++);
80 21         524 return $self->{'__ug'}->to_string($uuid);
81             }
82              
83             =head2 reinit ( )
84              
85             If unique check fails, attempt to re-initialize. You don't have to call it yourself.
86              
87             =cut
88              
89             sub reinit {
90 0     0 1 0 my $self = shift;
91 0         0 $self->{'__uniq'} = int(rand(time()));
92 0         0 return 1;
93             }
94              
95             =head2 command ( $cmd, [ $param => $value, ]+ )
96              
97             Execute a command.
98              
99             To get a list of availible commands, use something like that:
100              
101             my $res = $api->command('api-list_accessible_cmds');
102             if ($res->{'result'} eq 'success') {
103             my @commands = @{ $res->{'data'} };
104             }
105              
106             Returns a hash reference with (usually) 'result' and 'data' keys. 'result' can be 'success' or 'error', and 'data' depends on command executed.
107              
108             See L for more details.
109              
110             =cut
111              
112             sub command {
113 21     21 1 23756 my $self = shift;
114 21         66 my ($cmd, %extraparam) = @_;
115 21         205 delete $extraparam{$_} foreach (qw/ key cmd unique_id format /); # fool-proof
116              
117 21         61 while (1) {
118             # Loop until UUID is unique. Though I'm VERY doubtful this can happen in real life.
119              
120 21         123 my $res = $self->{'__ua'}->post('https://api.dreamhost.com/', {
121             'key' => $self->{'__key'},
122             'cmd' => $cmd,
123             'unique_id' => $self->uuid(),
124             'format' => $self->{'__format'},
125             %extraparam,
126             });
127              
128 21 50       25685717 if ($res->is_success()) {
129 21         282 my $result;
130              
131 21 50       113 if ($self->{'__format'} eq 'json') {
132 0 0       0 return unless $result = JSON::from_json($res->content());
133             } else {
134             ## no critic (ProhibitStringyEval)
135 21 50       115 return unless eval $res->content();
136             ## use critic
137             }
138              
139 21 50       456 return unless ref($result) eq 'HASH';
140              
141 21 50 66     146 if ($result->{'result'} eq 'error' and $result->{'data'} eq 'unique_id_already_used') {
142 0         0 $self->reinit(); # Reinitialize random seed
143 0         0 redo; # Send another request
144             }
145              
146 21         681 return $result;
147             } else {
148 0           eval { die $res->status_line(); };
  0            
149 0           return;
150             }
151             }
152              
153 0           return; # for Perl::Critic
154             }
155              
156             =head1 CONFIGURATION AND ENVIRONMENT
157              
158             WWW::DreamHost::API is based on I which uses I
159             or I, with all consequences: HTTPS_proxy environment
160             variable and so on. See I documentation unless you're already familiar
161             with it.
162              
163             =head1 DEPENDENCIES
164              
165             LWP::UserAgent
166             Crypt::SSLeay
167             Data::UUID
168             LWP::protocol::https
169              
170             If JSON.pm is installed, JSON format is used when making requests to API;
171             otherwise Data::Dumper format is used. Note that Data::Dumper format is
172             "eval"-ed so (in theory) it can be used for security breach. On the side note,
173             Data::Dumper way is 7 times faster.
174              
175             =head1 INCOMPATIBILITIES
176              
177             Not known.
178              
179             =head1 BUGS AND LIMITATIONS
180              
181             Not known, but test suite MAY fail if DreamHost adds some other commands or
182             change their behaviour.
183             If you are using L in your service, I'll know about it.
184             Consider installing it, as it really helps authors to know about possible bugs.
185             See L.
186              
187             =head1 AUTHOR
188              
189             Serguei Trouchelle L
190              
191             =head1 LICENSE AND COPYRIGHT
192              
193             This module is distributed under the same terms as Perl itself.
194              
195             Copyright (c) 2009-2013 Serguei Trouchelle
196              
197             =cut
198              
199             1;