File Coverage

blib/lib/Webservice/Sendy/API.pm
Criterion Covered Total %
statement 23 177 12.9
branch 2 84 2.3
condition 0 37 0.0
subroutine 7 15 46.6
pod 5 10 50.0
total 37 323 11.4


line stmt bran cond sub pod time code
1             package Webservice::Sendy::API;
2              
3 1     1   395343 use v5.10;
  1         6  
4 1     1   6 use strict;
  1         20  
  1         42  
5              
6 1     1   943 use HTTP::Tiny;
  1         60807  
  1         70  
7 1     1   1180 use JSON qw/decode_json/;
  1         11620  
  1         4  
8 1     1   650 use Util::H2O::More qw/baptise ddd HTTPTiny2h2o h2o ini2h2o o2d/;
  1         7747  
  1         2133  
9              
10             our $VERSION = '0.8';
11              
12             sub new {
13 1     1 0 595 my $pkg = shift;
14 1         7 my $params = { @_, ua => HTTP::Tiny->new };
15 1         97 my $self = baptise $params, $pkg, qw/config/;
16 1 50       132 if (not $self->config) {
17 0         0 my $HOME = (getpwuid($<))[7];
18 0         0 $self->config("$HOME/.sendy.ini");
19             }
20 1 50       8 if (not -e $self->config) {
21 0         0 die sprintf "Webservice::Sendy::API requires a configuration file! (looking for, '%s')\n", $self->config;
22             }
23             # update config field with contents of the config file
24 1         22 $self->config(ini2h2o $self->config);
25 1         2081 return $self;
26             }
27              
28             sub form_data {
29 1     1 0 1085 my $self = shift;
30             return {
31 1         3 api_key => $self->config->defaults->api_key,
32             @_,
33             };
34             }
35              
36             sub create_campaign {
37 0     0 1   my $self = shift;
38 0           my $params = {@_};
39              
40 0           my @required = qw/from_name from_email reply_to title subject html_text
41             list_ids brand_id track_opens track_clicks send_campaign/;
42 0           my @optional = qw/plain_text segment_ids exclude_list_ids query_string schedule_date_time schedule_timezone/;
43              
44 0           h2o $params, @required, @optional;
45              
46             # FATAL error if title, subject, and html_text is not provided; the other fields
47             # required by the API can use defaults in the configuration file, listed after
48             # the check:
49              
50             # look up hash for defaults to use
51 0 0         my $required_defaults = h2o {
    0          
52             title => undef,
53             subject => undef,
54             html_text => undef,
55             from_name => $self->config->campaign->from_name,
56             from_email => $self->config->campaign->from_email,
57             reply_to => $self->config->campaign->reply_to,
58             brand_id => $self->config->defaults->brand_id,
59             list_ids => $self->config->defaults->list_id,
60             track_clicks => ($params->no_track_clicks) ? 0 : 1, # --no_track_clicks
61             track_opens => ($params->no_track_opens) ? 0 : 1, # --no_track_opens
62             send_campaign => 0,
63             };
64              
65              
66 0           my $required_options = {};
67 0           foreach my $param (keys %$required_defaults) {
68 0 0 0       if (not defined $params->$param and defined $required_defaults->$param) {
    0 0        
69 0           $params->$param($required_defaults->$param);
70             }
71             # FATAL for anything in $required_defaults set to 'undef'
72             elsif (not defined $params->$param and not defined $required_defaults->$param) {
73 0           die sprintf "[campaign] Missing '%s' flag; creation requires: %s'\n", $param, join(",", keys %$required_defaults);
74             }
75 0           $required_options->{$param} = $params->$param;
76             }
77              
78             # processing other white-listed options in @optional
79 0           my $other_options = {};
80 0           foreach my $opt (@optional) {
81 0 0         if (defined $params->$opt) {
82 0           $other_options->{$opt} = $params->$opt;
83             }
84             }
85              
86 0           my $form_data = $self->form_data(%$required_options, %$other_options);
87 0           my $URL = sprintf "%s/api/campaigns/create.php", $self->config->defaults->base_url;
88 0           my $resp = h2o $self->ua->post_form($URL, $form_data);
89              
90             # report Error
91 0 0 0       if ($resp->content and $resp->content =~ m/Already|missing|not|valid|Unable/i) {
92 0           my $msg = $resp->content;
93 0           $msg =~ s/\.$//g;
94 0           die sprintf "[campaign] Server replied: %s!\n", $msg;
95             }
96              
97             # report general failure (it is not clear anything other than HTTP Status of "200 OK" is returned)
98 0 0         if (not $resp->success) {
99 0           die sprintf("Server Replied: HTTP Status %s %s\n", $resp->status, $resp->reason);
100             }
101              
102 0           return $resp->content;
103             }
104              
105             sub subscribe {
106 0     0 1   my $self = shift;
107 0           my $params = {@_};
108 0           my @required = qw/email list_id/;
109 0           my @optional = qw/name country ipaddress referrer gdpr silent hp/;
110 0           h2o $params, @required, @optional;
111              
112             #NOTE - Util::H2O::More::ini2h2o needs a "autoundef" option! Workaround is use of "exists" and ternary
113 0 0         if (not $params->list_id) {
114 0           $params->list_id('');
115 0 0         if ($self->config->defaults->{list_id}) {
116 0           $params->list_id($self->config->defaults->list_id);
117             }
118             }
119 0 0         die "email required!\n" if not $params->email;
120              
121             # processing other white-listed options
122 0           my $other_options = {};
123 0           foreach my $opt (@optional) {
124 0 0         if (defined $params->$opt) {
125 0           $other_options->{$opt} = $params->$opt;
126             }
127             }
128              
129 0           my $form_data = $self->form_data(list => $params->list_id, email => $params->email, boolean => "true", %$other_options);
130 0           my $URL = sprintf "%s/subscribe", $self->config->defaults->base_url;
131 0           my $resp = h2o $self->ua->post_form($URL, $form_data);
132              
133             # report Error
134 0 0 0       if ($resp->content and $resp->content =~ m/Already|missing|not|valid|Bounced|suppressed/i) {
135 0           my $msg = $resp->content;
136 0           $msg =~ s/\.$//g;
137 0           die sprintf "[subscribe] Server replied: %s!\n", $msg;
138             }
139              
140             # report general failure (it is not clear anything other than HTTP Status of "200 OK" is returned)
141 0 0         if (not $resp->success) {
142 0           die sprintf("Server Replied: HTTP Status %s %s\n", $resp->status, $resp->reason);
143             }
144              
145 0 0         return sprintf "%s %s %s\n", ($resp->content eq "1")?"Subscribed":$resp->content, $params->list_id, $params->email;
146             }
147              
148             #NOTE: this call is different from "delete_subscriber" in that it just marks the
149             # subscriber as unsubscribed; "delete_subscriber" fully removes it from the list (in the DB)
150             #NOTE: this call uses a different endpoint than the others ...
151             sub unsubscribe {
152 0     0 1   my $self = shift;
153 0           my $params = {@_};
154              
155             #NOTE - Util::H2O::More::ini2h2o needs a "autoundef" option! Workaround is use of "exists" and ternary
156 0           my $list_id = $params->{list_id};
157 0 0         if (not $list_id) {
158 0           $list_id = '';
159 0 0         if ($self->config->defaults->{list_id}) {
160 0           $list_id = $self->config->defaults->list_id;
161             }
162             }
163 0           my $email = $params->{email};
164 0 0         die "email required!\n" if not $email;
165              
166 0           my $form_data = $self->form_data(list => $list_id, email => $email, boolean => "true");
167 0           my $URL = sprintf "%s/unsubscribe", $self->config->defaults->base_url;
168 0           my $resp = h2o $self->ua->post_form($URL, $form_data);
169              
170             # report Error
171 0 0 0       if ($resp->content and $resp->content =~ m/Some|valid|not/i) {
172 0           my $msg = $resp->content;
173 0           $msg =~ s/\.$//g;
174 0           die sprintf "[unsubscribe] Server replied: %s!\n", $msg;
175             }
176              
177             # report general failure (it is not clear anything other than HTTP Status of "200 OK" is returned)
178 0 0         if (not $resp->success) {
179 0           die sprintf("Server Replied: HTTP Status %s %s\n", $resp->status, $resp->reason);
180             }
181              
182 0 0         return sprintf "%s %s %s\n", ($resp->content == 1)?"Unsubscribed":$resp->content, $list_id, $email;
183             }
184              
185             #NOTE: this call is different from "unsubscribe" in that it deletes the subscriber
186             # "unsubscribe" simply marks them as unsubscribed
187             sub delete_subscriber {
188 0     0 0   my $self = shift;
189 0           my $params = {@_};
190              
191             #NOTE - Util::H2O::More::ini2h2o needs a "autoundef" option! Workaround is use of "exists" and ternary
192 0           my $list_id = $params->{list_id};
193 0 0         if (not $list_id) {
194 0           $list_id = '';
195 0 0         if ($self->config->defaults->{list_id}) {
196 0           $list_id = $self->config->defaults->list_id;
197             }
198             }
199 0           my $email = $params->{email};
200 0 0         die "email required!\n" if not $email;
201              
202 0           my $form_data = $self->form_data(list_id => $list_id, email => $email);
203 0           my $URL = sprintf "%s/api/subscribers/delete.php", $self->config->defaults->base_url;
204 0           my $resp = h2o $self->ua->post_form($URL, $form_data);
205              
206             # report Error
207 0 0 0       if ($resp->content and $resp->content =~ m/No|valid|List|not/i) {
208 0           my $msg = $resp->content;
209 0           $msg =~ s/\.$//g;
210 0           die sprintf "[delete] Server replied: %s!\n", $msg;
211             }
212              
213             # report general failure (it is not clear anything other than HTTP Status of "200 OK" is returned)
214 0 0         if (not $resp->success) {
215 0           die sprintf("Server Replied: HTTP Status %s %s\n", $resp->status, $resp->reason);
216             }
217              
218 0 0         return sprintf "%s %s %s\n", ($resp->content == 1)?"Deleted":$resp->content, $list_id, $email;
219             }
220              
221             sub get_subscription_status {
222 0     0 0   my $self = shift;
223 0           my $params = {@_};
224              
225             #NOTE - Util::H2O::More::ini2h2o needs a "autoundef" option! Workaround is use of "exists" and ternary
226 0           my $list_id = $params->{list_id};
227 0 0         if (not $list_id) {
228 0           $list_id = '';
229 0 0         if ($self->config->defaults->{list_id}) {
230 0           $list_id = $self->config->defaults->list_id;
231             }
232             }
233 0           my $email = $params->{email};
234 0 0         die "email required!\n" if not $email;
235              
236 0           my $form_data = $self->form_data(list_id => $list_id, email => $email);
237 0           my $URL = sprintf "%s/api/subscribers/subscription-status.php", $self->config->defaults->base_url;
238 0           my $resp = h2o $self->ua->post_form($URL, $form_data);
239              
240             # catch "Not Subscribed"
241 0 0         if ($resp->content eq "Email does not exist in list") {
242 0           return sprintf "Not Subscribed %s %s\n", $list_id, $email;
243             }
244              
245             # report Error
246 0 0 0       if ($resp->content and $resp->content =~ m/No|vlaid|not/i) {
247 0           my $msg = $resp->content;
248 0           $msg =~ s/\.$//g;
249 0           die sprintf "[status] Server replied: %s!\n", $msg;
250             }
251              
252             # report general failure (it is not clear anything other than HTTP Status of "200 OK" is returned)
253 0 0         if (not $resp->success) {
254 0           die sprintf("Server Replied: HTTP Status %s %s\n", $resp->status, $resp->reason);
255             }
256              
257 0           return sprintf "%s %s %s\n", $resp->content, $list_id, $email;
258             }
259              
260             sub get_active_subscriber_count {
261 0     0 0   my $self = shift;
262 0           my $params = {@_};
263              
264             #NOTE - Util::H2O::More::ini2h2o needs a "autoundef" option! Workaround is use of "exists" and ternary
265 0           my $list_id = $params->{list_id};
266 0 0         if (not $list_id) {
267 0           $list_id = '';
268 0 0         if ($self->config->defaults->{list_id}) {
269 0           $list_id = $self->config->defaults->list_id;
270             }
271             }
272              
273 0           my $form_data = $self->form_data( list_id => $list_id);
274 0           my $URL = sprintf "%s/api/subscribers/active-subscriber-count.php", $self->config->defaults->base_url;
275 0           my $resp = h2o $self->ua->post_form($URL, $form_data);
276              
277             # report Error
278 0 0 0       if ($resp->content and $resp->content =~ m/No|valid|not/i) {
279 0           my $msg = $resp->content;
280 0           $msg =~ s/\.$//g;
281 0           die sprintf "[count] Server replied: %s!\n", $msg;
282             }
283              
284             # report general failure (it is not clear anything other than HTTP Status of "200 OK" is returned)
285 0 0         if (not $resp->success) {
286 0           die sprintf("Server Replied: HTTP Status %s %s\n", $resp->status, $resp->reason);
287             }
288              
289 0   0       return sprintf "%s %s\n", $resp->content // -1, $list_id;
290             }
291              
292             sub get_brands() {
293 0     0 1   my $self = shift;
294 0           my $form_data = $self->form_data();
295 0           my $URL = sprintf "%s/api/brands/get-brands.php", $self->config->defaults->base_url;
296 0           my $resp = h2o $self->ua->post_form($URL, $form_data);
297              
298             # report Error
299 0 0 0       if ($resp->content and $resp->content =~ m/No|valid/i) {
300 0           my $msg = $resp->content;
301 0           $msg =~ s/\.$//g;
302 0           die sprintf "[brands] Server replied: %s!\n", $msg;
303             }
304              
305             # report general failure (it is not clear anything other than HTTP Status of "200 OK" is returned)
306 0 0         if (not $resp->success) {
307 0           die sprintf("Server Replied: HTTP Status %s %s\n", $resp->status, $resp->reason);
308             }
309              
310 0           $resp = HTTPTiny2h2o o2d $resp;
311 0           return $resp->content;
312             }
313              
314             sub get_lists {
315 0     0 1   my $self = shift;
316 0           my $params = {@_};
317 0   0       my $form_data = $self->form_data( brand_id => $params->{brand_id} // $self->config->defaults->brand_id // 1);
      0        
318 0           my $URL = sprintf "%s/api/lists/get-lists.php", $self->config->defaults->base_url;
319 0           my $resp = h2o $self->ua->post_form($URL, $form_data);
320              
321             # report Error
322 0 0 0       if ($resp->content and $resp->content =~ m/No|valid|not/i) {
323 0           my $msg = $resp->content;
324 0           $msg =~ s/\.$//g;
325 0           die sprintf "[lists] Server replied: %s!\n", $msg;
326             }
327              
328             # report general failure (it is not clear anything other than HTTP Status of "200 OK" is returned)
329 0 0         if (not $resp->success) {
330 0           die sprintf("Server Replied: HTTP Status %s %s\n", $resp->status, $resp->reason);
331             }
332              
333 0           $resp = HTTPTiny2h2o o2d $resp;
334 0           return $resp->content;
335             }
336              
337             777
338              
339             __END__