File Coverage

blib/lib/Net/SMS/SMSPilot.pm
Criterion Covered Total %
statement 21 127 16.5
branch 0 50 0.0
condition 0 20 0.0
subroutine 7 18 38.8
pod 7 7 100.0
total 35 222 15.7


line stmt bran cond sub pod time code
1             package Net::SMS::SMSPilot;
2             # coding: UTF-8
3              
4 1     1   32211 use strict;
  1         13  
  1         42  
5 1     1   6 use warnings;
  1         2  
  1         28  
6 1     1   1062 use utf8;
  1         13  
  1         4  
7              
8             our $VERSION = '0.05';
9              
10 1     1   1277 use LWP::UserAgent;
  1         992499  
  1         44  
11 1     1   1046 use HTTP::Request::Common qw(POST);
  1         2635  
  1         87  
12 1     1   9529 use Encode;
  1         15479  
  1         111  
13              
14             #use Data::Dumper;
15              
16             # ==============================================================================
17              
18 1     1   9 use constant SMSPILOT_API_URI => 'smspilot.ru/api.php';
  1         2  
  1         2075  
19              
20             # ==============================================================================
21             # Constructor
22             sub new($%) {
23 0     0 1   my ($class, %config) = @_;
24 0 0         %config = () if !(%config);
25              
26 0 0         if (! $config{apikey}) {
27 0           return undef;
28             }
29             else {
30 0           my $self = +{};
31 0   0       $self = bless $self, ref($class) || $class;
32              
33 0           $self->_init(\%config);
34 0           return $self;
35             }
36             }
37             # ------------------------------------------------------------------------------
38             # Set up initial (passed from caller or default) values
39             sub _init
40             {
41 0     0     my $self = shift;
42 0           my ($config) = @_;
43              
44 0           $self->{secure} = 1;
45 0           $self->{charset} = 'utf8';
46 0           $self->{sender} = 'SMSPilot.Ru';
47              
48 0           for (qw(ua apikey charset secure on_error)) {
49 0 0         $self->{$_} = $config->{$_} if exists $config->{$_};
50             }
51              
52 0 0         $self->set_sender($config->{sender}) if exists $config->{sender};
53              
54 0 0         $self->{uri} = 'http'.($self->{secure}?'s':'').'://'.SMSPILOT_API_URI;
55 0           $self->{_errmsg} = '';
56              
57             }
58             # ------------------------------------------------------------------------------
59             sub _throw_error {
60 0     0     my ($self, $msg) = @_;
61              
62 0           $self->{_errmsg} = $msg;
63 0 0         if ($self->{on_error}) {
64             # Fire callback
65 0           &{$self->{on_error}}($msg);
  0            
66             }
67             }
68             # ------------------------------------------------------------------------------
69             sub error {
70 0     0 1   my $self = shift;
71 0   0       return $self->{_errmsg} || '';
72             }
73             # ------------------------------------------------------------------------------
74             # Our User-Agent
75             sub _ua {
76 0     0     my $self = shift;
77              
78 0 0         if (! defined($self->{ua})) {
79 0           $self->{ua} = LWP::UserAgent->new(
80             agent => ref($self) . '/' . $VERSION,
81             timeout => 30
82             );
83 0           $self->{ua}->env_proxy;
84             }
85              
86 0           return $self->{ua};
87             }
88             # ------------------------------------------------------------------------------
89             # Make request to API
90             sub _query($;%){
91 0     0     my ($self, %data) = @_;
92 0           my $r = undef;
93              
94 0 0         if (! $self->{apikey}) {
95 0           $self->_throw_error('APIKEY is not defined');
96             }
97             else {
98              
99 0           $data{apikey} = $self->{apikey};
100 0           (%data) = map {decode($self->{charset},$_)} (%data);
  0            
101 0           my $uri = $self->{uri};
102 0           my $response = $self->_ua->request(POST $uri,
103             Content => [%data]
104             );
105              
106 0 0         if ($response->is_success) {
107 0           my $cont = encode($self->{charset},$response->content);
108 0           $r={};
109 0           ($r->{header},$r->{content})=split(/\r?\n/,$cont,2);
110 0 0         if ($r->{header}=~/^ERROR=(\d+):\s*(.*)$/) {
111 0           $r->{error}=1;
112 0           $r->{error_code}=$1;
113 0           $r->{error_message}=$2;
114 0           $r->{success}=0;
115             } else {
116 0           $r->{success}=1;
117 0           $r->{error}=0;
118 0           $r->{error_code}='';
119 0           $r->{error_message}='';
120 0 0         if ($r->{header}=~/^SUCCESS=(.*)$/) {
121 0           $r->{success_message}=$1
122             } else {
123 0           $r->{success_message} = 'OK';
124 0           $r->{content} = $cont;
125 0           $r->{header} = '';
126             }
127             }
128 0 0         if ($r->{error}) {
129 0           $self->_throw_error('API error: '.$r->{error_code}.' '.$r->{error_message});
130             }
131             }
132             else {
133 0           $self->_throw_error('Request failed: ' . $response->status_line);
134             }
135             }
136              
137 0           return $r;
138             }
139             # ==============================================================================
140             #
141             sub send($$$){
142 0     0 1   my ($self,$to,$msg) = @_;
143 0 0         $to = join(',',@$to) if ref($to) eq 'ARRAY';
144 0           my $report = undef;
145 0           my $r = $self->_query(
146             to => $to,
147             send => $msg,
148             from => $self->{sender},
149             );
150              
151 0 0 0       if (defined($r) && $r->{success}) {
152 0           foreach (split(/\r?\n/,$r->{content})) {
153 0           my ($id,$phone,$zone,$status) = split /,/;
154              
155 0 0         if ( $r->{success_message}=~/SMS\s+SENT\s+(\d+)\/(\d+)/ ) {
156 0           ($self->{cost},$self->{balance})=($1,$2)
157             } else {
158 0           ($self->{cost},$self->{balance})=(undef,undef)
159             }
160              
161 0           push(@$report,{
162             id => $id,
163             phone => $phone,
164             zone => $zone,
165             status => $status,
166             });
167             }
168             }
169              
170 0 0         return wantarray?@$report:$report;
171             }
172             # ==============================================================================
173             #
174             sub set_sender($$){
175 0     0 1   my ($self,$sender) = @_;
176 0 0 0       if ($sender=~/^[A-Za-z\.\-\d]{3,11}$/ && $sender!~/^\d{3,9}$/) {
    0          
177 0           $self->{sender} = $sender
178             }elsif ($sender=~/^\+?\d{10,16}$/) {
179 0           $sender=~s/^\+//;
180 0           $self->{sender} = $sender;
181             } else {
182 0           $sender = undef;
183 0           $self->_throw_error('The sender can contain text in Latin script, numer'.
184             'als, symbols "-" and "." length of 3-11 characters'.
185             ' long or the number length of 10-16 numbers in int'.
186             'ernational format, "+" sign is not considered.');
187             }
188 0           return $sender;
189             }
190             # ==============================================================================
191             #
192             sub balance($;$){
193 0     0 1   my ($self,$type) = @_;
194 0           my $balance = undef;
195 0 0         $type = 'sms' if ! defined($type);
196 0           my $r=$self->_query(
197             balance => $type,
198             );
199 0 0 0       if (defined($r) && $r->{success}) {
200 0           $balance=$r->{content}
201             }
202 0           return $balance;
203             }
204              
205             # ==============================================================================
206             #
207             sub apikey_info($){
208 0     0 1   my ($self) = @_;
209 0           my $info = undef;
210 0           my $r=$self->_query();
211 0 0 0       if (defined($r) && $r->{success}) {
212 0           foreach (split(/\r?\n/,$r->{content})) {
213 0           my ($n,$v) = split(/=/,$_,2);
214 0           $info->{$n} = $v;
215             }
216 0           $info->{history}=[split(/\|/,$info->{history})];
217             }
218 0 0         return wantarray?%$info:$info;
219             }
220             # ==============================================================================
221             #
222             sub check($$){
223 0     0 1   my ($self,$id) = @_;
224 0 0         $id = join(',',@$id) if ref($id) eq 'ARRAY';
225 0           my $report = undef;
226 0           my $r = $self->_query(
227             check => $id,
228             );
229              
230 0 0 0       if (defined($r) && $r->{success}) {
231 0           foreach (split(/\r?\n/,$r->{content})) {
232 0           my ($id,$phone,$zone,$status) = split /,/;
233 0           push(@$report,{
234             id => $id,
235             phone => $phone,
236             zone => $zone,
237             status => $status,
238             });
239             }
240             }
241              
242 0 0         return wantarray?@$report:$report;
243             }
244             # ==============================================================================
245             1;
246             __END__