File Coverage

blib/lib/WebService/Leanpub.pm
Criterion Covered Total %
statement 36 136 26.4
branch 4 48 8.3
condition 1 3 33.3
subroutine 9 28 32.1
pod 14 14 100.0
total 64 229 27.9


line stmt bran cond sub pod time code
1             package WebService::Leanpub;
2              
3 2     2   147193 use warnings;
  2         17  
  2         76  
4 2     2   11 use strict;
  2         4  
  2         40  
5 2     2   9 use Carp;
  2         3  
  2         121  
6              
7 2     2   960 use version; our $VERSION = qv('v0.3.1');
  2         4210  
  2         12  
8              
9 2     2   1320 use HTTP::Request::Common;
  2         47756  
  2         167  
10 2     2   1553 use JSON;
  2         21985  
  2         51  
11 2     2   1832 use LWP::UserAgent;
  2         55596  
  2         92  
12 2     2   23 use URI::Escape;
  2         6  
  2         3459  
13              
14             # Module implementation here
15              
16             my $lpurl = 'https://leanpub.com/';
17              
18             sub new {
19 3     3 1 1528 my ($self, $api_key, $slug) = @_;
20 3   33     16 my $type = ref($self) || $self;
21              
22 3 100       11 unless ($api_key) { die "Missing API key for Leanpub"; }
  1         11  
23 2 100       6 unless ($slug) { die "Missing SLUG for book"; }
  1         8  
24              
25 1         4 $self = bless {}, $type;
26              
27 1         5 $self->{api_key} = uri_escape($api_key);
28 1         87 $self->{slug} = uri_escape($slug);
29 1         50 $self->{ua} = LWP::UserAgent->new(
30             agent => "libwebservice-leanpub-perl/$VERSION",
31             );
32 1         3230 $self->{json} = JSON->new;
33              
34 1         6 return $self;
35             } # new()
36              
37             #----- coupons -----
38             sub create_coupon {
39 0     0 1   my ($self,$opt) = @_;
40              
41 0 0         unless ($opt->{coupon_code}) { return; }
  0            
42 0 0         unless ($opt->{discounted_price}) { return; }
  0            
43 0 0         unless ($opt->{start_date}) { return; }
  0            
44              
45             my $var = {
46             'coupon[coupon_code]' => $opt->{coupon_code},
47             'coupon[discounted_price]' => $opt->{discounted_price},
48             'coupon[start_date]' => $opt->{start_date},
49 0           };
50            
51 0 0         if ($opt->{end_date}) {
52 0           $var->{'coupon[end_date]'} = $opt->{end_date};
53             }
54 0 0         if ($opt->{has_uses_limit}) {
55 0           $var->{'coupon[has_uses_limit]'} = $opt->{has_uses_limit};
56             }
57 0 0         if ($opt->{max_uses}) {
58 0           $var->{'coupon[max_uses]'} = $opt->{max_uses};
59             }
60 0 0         if ($opt->{note}) {
61 0           $var->{'coupon[note]'} = $opt->{note};
62             }
63 0 0         if ($opt->{suspended}) {
64 0           $var->{'coupon[suspended]'} = $opt->{suspended};
65             }
66 0           return $self->_post_request( { path => '/coupons.json', var => $var } );
67             } # create_coupon()
68              
69             sub get_coupon_list {
70 0     0 1   my ($self) = @_;
71              
72 0           return $self->_get_request( { path => '/coupons.json' } );
73              
74             } # get_coupon_list()
75              
76             sub update_coupon {
77 0     0 1   my ($self,$opt) = @_;
78              
79 0 0         unless ($opt->{coupon_code}) { return; }
  0            
80              
81 0           my $cc = delete $opt->{coupon_code};
82 0           my $path = "/coupons/$cc.json";
83              
84 0           _wash_coupon_opts($opt);
85 0           my $content = encode_json( $opt );
86              
87 0           return $self->_put_request( { path => $path, content => $content } );
88             } # update_coupon()
89              
90             sub _wash_coupon_opts {
91 0     0     my $opt = $_[0];
92             my $bool = sub {
93 0 0   0     return ($_[0] =~/^(no|false|0)$/i) ? 'false' : 'true';
94 0           };
95 0 0         if (exists $opt->{suspended}) {
96 0           $opt->{suspended} = $bool->($opt->{suspended});
97             }
98 0 0         if (exists $opt->{has_uses_limit}) {
99 0           $opt->{has_uses_limit} = $bool->($opt->{has_uses_limit});
100             }
101             } # _wash_coupon_opts;
102              
103             #----- sales -----
104              
105             sub get_individual_purchases {
106 0     0 1   my ($self,$opt) = @_;
107 0           my $req = { path => '/individual_purchases.json' };
108 0 0         $req->{var} = { page => $opt->{page} } if ($opt->{page});
109 0           return $self->_get_request($req);
110              
111             } # get_individual_purchases()
112              
113             sub get_sales_data {
114 0     0 1   my ($self) = @_;
115              
116 0           return $self->_get_request( { path => '/sales.json' } );
117              
118             } # get_sales_data()
119              
120             #----- jobs -----
121              
122             sub get_job_status {
123 0     0 1   my ($self) = @_;
124              
125 0           return $self->_get_request( { path => '/book_status.json' } );
126              
127             } # get_job_status()
128              
129             sub partial_preview {
130 0     0 1   my ($self) = @_;
131              
132 0           return $self->_post_request( { path => '/preview/subset.json' } );
133             } # partial_preview()
134              
135             sub preview {
136 0     0 1   my ($self) = @_;
137              
138 0           return $self->_post_request( { path => '/preview.json' } );
139             } # preview()
140              
141             sub publish {
142 0     0 1   my ($self,$opt) = @_;
143 0           my $var = {};
144              
145 0 0         if ($opt->{email_readers}) {
146 0           $var->{'publish[email_readers]'} = 'true';
147             }
148 0 0         if (exists $opt->{release_notes}) {
149 0           $var->{'publish[release_notes]'} = $opt->{release_notes};
150             }
151 0           return $self->_post_request( { path => '/publish.json', var => $var } );
152             } # publish()
153              
154             sub single {
155 0     0 1   my ($self,$opt) = @_;
156              
157 0 0         if ($opt->{content}) {
158 0           my $json = JSON->new->encode({ 'content' => $opt->{content} });
159 0           return $self->_json_post_request({ path => '/preview/single.json'
160             , content => $json });
161             }
162             else {
163 0           return;
164             }
165             } # single()
166              
167             sub subset {
168 0     0 1   my ($self) = @_;
169              
170 0           return $self->_post_request( { path => '/preview/subset.json' } );
171             } # subset()
172              
173             sub summary {
174 0     0 1   my ($self) = @_;
175              
176 0           return $self->_get_request( { path => '.json' } );
177             } # summary()
178              
179             #----- JSON functions -----
180             sub pretty_json {
181 0     0 1   my $json = $_[0]->{json};
182 0           return $json->pretty->encode($json->decode($_[1]));
183             } # pretty_json()
184             #----- helper functions -----
185              
186             sub _get_request {
187 0     0     my ($self,$opt) = @_;
188              
189             my $url = $lpurl . $self->{slug} . $opt->{path}
190 0           . '?api_key=' . $self->{api_key};
191 0 0         if ($opt->{var}) {
192 0           foreach my $var (keys %{$opt->{var}}) {
  0            
193 0           $url .= "&$var=" . uri_escape($opt->{var}->{$var});
194             }
195             }
196 0           my $res = $self->{ua}->get($url);
197              
198 0 0         if ($res->is_success) {
199 0           return $res->decoded_content;
200             }
201 0           return;
202             } # _get_request()
203              
204             sub _json_post_request {
205 0     0     my ($self,$opt) = @_;
206             my $url = $lpurl . $self->{slug} . $opt->{path}
207 0           . '?api_key=' . $self->{api_key};
208             my @args = (
209             'Content_Type' => 'application/json; charset=utf-8',
210             'Content' => $opt->{content},
211 0           );
212 0           my $res = $self->{ua}->post($url, @args);
213              
214 0 0         if ($res->is_success) {
215 0           return $res->decoded_content;
216             }
217             } # _json_post_request()
218              
219             sub _post_request {
220 0     0     my ($self,$opt) = @_;
221 0           my $url = $lpurl . $self->{slug} . $opt->{path};
222 0           my $form = { api_key => $self->{api_key}, };
223              
224 0 0         if ($opt->{var}) {
225 0           foreach my $var (keys %{$opt->{var}}) {
  0            
226 0           $form->{$var} = $opt->{var}->{$var};
227             }
228             }
229 0           my $res = $self->{ua}->post($url, $form);
230              
231 0 0         if ($res->is_success) {
232 0           return $res->decoded_content;
233             }
234 0           return;
235             } # _post_request()
236              
237             sub _put_request {
238 0     0     my ($self,$opt) = @_;
239             my $url = $lpurl . $self->{slug} . $opt->{path}
240 0           . '?api_key=' . $self->{api_key};
241              
242             my $req = HTTP::Request::Common::PUT($url,
243             'Content-Type' => 'application/json',
244 0           'Content' => $opt->{content});
245 0           my $res = $self->{ua}->request($req);
246 0 0         if ($res->is_success) {
247 0           return $res->decoded_content;
248             }
249 0           return;
250             } # _put_request();
251              
252             1; # Magic true value required at end of module
253             __END__