File Coverage

blib/lib/Net/AppNotifications.pm
Criterion Covered Total %
statement 21 129 16.2
branch 0 28 0.0
condition 0 22 0.0
subroutine 7 26 26.9
pod 0 7 0.0
total 28 212 13.2


line stmt bran cond sub pod time code
1             package Net::AppNotifications;
2              
3 1     1   26566 use strict;
  1         3  
  1         41  
4 1     1   30 use 5.008_001;
  1         3  
  1         57  
5             our $VERSION = '0.03';
6 1     1   1148 use AnyEvent::HTTP;
  1         46667  
  1         119  
7 1     1   14 use Carp;
  1         1  
  1         69  
8 1     1   1095 use URI::Escape 'uri_escape_utf8';
  1         2854  
  1         138  
9              
10 1         89 use constant POST_URI =>
11 1     1   10 q{https://www.appnotifications.com/account/notifications.xml};
  1         2  
12              
13 1         1462 use constant KEY_URI =>
14 1     1   6 q{https://www.appnotifications.com/account/user_session.xml};
  1         1  
15              
16             sub new {
17 0     0 0   my $class = shift;
18 0           my %param = @_;
19 0   0       my $notifier = bless { %param }, ref $class || $class;
20 0 0         unless ($param{key}) {
21 0           $param{key} = $class->get_key( %param );
22             }
23 0 0         croak "Key (or valid email, pass to get it) is needed" unless $param{key};
24 0           return $notifier;
25             }
26              
27             sub send {
28 0     0 0   my $notifier = shift;
29              
30 0           my %cbs;
31 0           my $key = $notifier->{key};
32 0     0     my $finish = sub {};
  0            
33 0           my %param;
34              
35 0 0         if (scalar @_ == 1) {
36 0           my $message = shift;
37 0 0 0       unless (defined $message && length $message) {
38 0           croak "Please, give me a message to push";
39             }
40 0           $param{message} = $message;
41              
42 0           my $done = AnyEvent->condvar;
43              
44             $cbs{on_posted} = sub {
45 0     0     my ($data, $hds) = @_;
46 0           $done->send;
47 0 0         croak "Something happend" unless defined $data;
48 0           };
49              
50             $cbs{on_timeout} = sub {
51 0     0     $done->send;
52 0           croak "timeout";
53 0           };
54             $cbs{on_error} = sub {
55 0     0     $done->send;
56 0           croak "Error $_[0]";
57 0           };
58              
59             $finish = sub {
60 0     0     $done->recv;
61 0           };
62             }
63             else {
64 0           %param = @_;
65              
66 0           $cbs{$_} = $param{$_} for qw{on_error on_timeout};
67              
68 0   0 0     my $early_error = $cbs{on_error} || sub { croak "$_[0]" };
  0            
69              
70 0           my $on_success = $param{on_success};
71 0 0         unless ($on_success) {
72 0           $early_error->("On success must be passed");
73 0           return;
74             }
75              
76             ## callback definitions
77             $cbs{on_posted} = sub {
78 0     0     my $data = shift;
79 0 0         unless (defined $data) {
80 0           $cbs{on_error}->("Something happened");
81 0           return;
82             }
83 0           $on_success->($data, @_);
84 0           };
85              
86             $cbs{on_error} ||= sub {
87 0     0     warn "Error: $_[0]";
88 0   0       };
89              
90             $cbs{on_timeout} ||= sub {
91 0     0     warn "Timeout: $_[0]";
92 0   0       };
93             }
94 0           my $notification_params = $notifier->normalize(%param);
95              
96 0           my $uri = POST_URI;
97 0           my $body = build_body(
98             "user_credentials" => $key,
99             %$notification_params,
100             );
101 0           $notifier->post_request($uri, $body, %cbs);
102              
103             ## wait here for synchronous calls
104 0           $finish->();
105 0           return;
106             }
107              
108             sub normalize {
109 0     0 0   my $notifier = shift;
110 0           my %param = @_;
111              
112 0           my %nparam;
113 0           my $N = "notification";
114              
115 0           my @keys = qw/
116             message message_level action_loc_key run_command
117             title long_message long_message_preview
118             icon_url subtitle
119             /;
120 0           for (@keys) {
121 0 0         next unless exists $param{$_};
122 0   0       $nparam{"${N}[$_]"} = $param{$_} || "";
123             }
124              
125 0           my $silent = 0;
126 0           my $sound = $param{sound};
127 0 0         if ($sound) {
128 0 0         unless ($sound =~ /^[1..7]$/) {
129 0           $sound = "1";
130             }
131 0           $sound .= ".caf";
132             }
133              
134 0 0         if (my $s = $param{silent}) {
135 0           $s = lc $s;
136 0 0 0       unless ($s eq 'off' or $s eq 'no' or $s eq 'false') {
      0        
137 0           $silent = 1;
138 0           $sound = undef;
139             }
140             }
141 0           $nparam{"${N}[silent]"} = $silent;
142 0   0       $nparam{"${N}[sound]"} = $sound || "";
143              
144 0           return \%nparam;
145             }
146              
147             sub post_request {
148 0     0 0   my $notifier = shift;
149 0           my ($uri, $body, %cbs) = @_;
150              
151             http_request
152             POST => $uri,
153             body => $body,
154             headers => {
155             'Content-Type' => 'application/x-www-form-urlencoded',
156             'User-Agent' => q{yann's Net::AppNotifications},
157             },
158             on_header => sub {
159 0     0     my ($hds) = @_;
160 0 0         if ($hds->{Status} ne '200') {
161 0           return $cbs{on_error}->("$hds->{Status}: $hds->{Reason}");
162             }
163 0           return 1;
164             },
165 0           $cbs{on_posted};
166             return
167 0           }
168              
169             sub get_key {
170 0     0 0   my $class = shift;
171              
172 0           my $done = AnyEvent->condvar;
173 0           my $key;
174 0     0     my $got_key = sub { $key = shift; $done->send };
  0            
  0            
175              
176 0           $class->async_get_key( @_, got_key => $got_key );
177              
178 0           $done->recv;
179 0           return $key;
180             }
181              
182             sub async_get_key {
183 0     0 0   my $class = shift;
184 0           my %param = shift;
185              
186 0 0         my $email = $param{email} or return;
187 0           my $password = $param{password};
188 0           my $uri = KEY_URI;
189              
190 0           my $body = build_body(
191             'user_session[email]' => $email,
192             'user_session[password]' => $password,
193             );
194             my %cbs = (
195             on_posted => sub {
196 0     0     my $key = shift;
197 0           $param{got_key}->($key);
198             },
199 0           );
200 0           $class->post_request($uri, $body, %cbs);
201 0           return;
202             }
203              
204             sub build_body {
205 0     0 0   my %param = @_;
206             return
207 0           join "&", map {
208 0           join "=", $_, uri_escape_utf8($param{$_})
209             }
210             keys %param;
211             }
212              
213              
214             1;
215             __END__