... | ... |
@@ -3,21 +3,23 @@ |
3 | 3 |
use strict; |
4 | 4 |
use warnings; |
5 | 5 |
|
6 |
-use Net::XMPP; |
|
7 | 6 |
use DBI; |
8 | 7 |
use POSIX qw/ceil strftime/; |
8 |
+use HiPi::Huawei::E3531; |
|
9 |
+use HiPi::Huawei::Errors; |
|
9 | 10 |
|
10 | 11 |
use open ':utf8'; |
11 | 12 |
use open ':std'; |
12 | 13 |
use utf8; |
13 |
-#use Data::Dumper; |
|
14 |
+ |
|
15 |
+use Data::Dumper; |
|
14 | 16 |
|
15 | 17 |
use threads; |
16 | 18 |
use threads::shared; |
17 | 19 |
use Thread::Queue; |
20 |
+use Thread::Semaphore; |
|
18 | 21 |
|
19 |
-$ENV{PWD} = "" if not defined $ENV{PWD}; |
|
20 |
-my $scriptconf = $ENV{PWD} . "/$0"; |
|
22 |
+my $scriptconf = $0; |
|
21 | 23 |
$scriptconf =~ s/\.pl$//; |
22 | 24 |
$scriptconf =~ s/$/.conf/; |
23 | 25 |
if (-r $scriptconf) { |
... | ... |
@@ -34,146 +36,46 @@ else { |
34 | 36 |
} |
35 | 37 |
|
36 | 38 |
$SIG{INT}=\&terminate; |
37 |
-#my $next_sms :shared; # utilisé pour le top du procahin envoi |
|
38 |
-my $debugLevel = 0; |
|
39 |
- |
|
40 |
-my $phone_status : shared = ""; |
|
41 | 39 |
|
42 |
-my $from_gtalksms_queue = Thread::Queue->new; |
|
43 |
-my $to_gtalksms_queue = Thread::Queue->new; |
|
40 |
+my $inbox_sms_queue = Thread::Queue->new; |
|
41 |
+my $outbox_sms_queue = Thread::Queue->new; |
|
44 | 42 |
my $mail_queue = Thread::Queue->new; |
45 | 43 |
|
46 |
-my $bot = &xmpp_login($cfg::config{xmpp}->{hostName}, |
|
47 |
- $cfg::config{xmpp}->{portNumber}, |
|
48 |
- $cfg::config{xmpp}->{userName}, |
|
49 |
- $cfg::config{xmpp}->{passWord}, |
|
50 |
- $cfg::config{xmpp}->{componentName}, |
|
51 |
- $cfg::config{xmpp}->{resource}, |
|
52 |
- $cfg::config{xmpp}->{tls}, |
|
53 |
- 1, "", 0, |
|
54 |
- $cfg::config{DEBUG}); |
|
44 |
+my $mutex = Thread::Semaphore->new(); |
|
45 |
+STDERR->autoflush(); |
|
55 | 46 |
|
56 |
-$SIG{INT} = sub { $bot->Disconnect; }; |
|
47 |
+my $mail = threads->new(\&send_mail); |
|
57 | 48 |
|
58 |
-my $mail = threads->new(\&ssmtp_send_mail); |
|
49 |
+my $inbox_sms = threads->new(\&inbox_sms_parse); |
|
59 | 50 |
|
60 |
-my $from_gtalksms = threads->new(\&from_gtalksms_parse); |
|
51 |
+my $outbox_sms = threads->new(\&hilink_send_sms); |
|
61 | 52 |
|
62 |
-my $to_gtalksms = threads->new(\&xmpp_send_sms); |
|
63 |
- |
|
64 |
-sub debug_print { |
|
65 |
- print STDERR "sendxmpp: " . (join ' ', @_) . "\n" |
|
66 |
- if (@_ && ($cfg::config{DEBUG} ||$cfg::config{VERBOSE})); |
|
67 |
-} |
|
53 |
+my $hlink = HiPi::Huawei::E3531->new(); |
|
68 | 54 |
|
69 | 55 |
sub log_bot { |
70 |
-# open(LOGFILE,'>>', 'bot.log'); |
|
71 |
-# print LOGFILE sprintf("[%s] %s\n",strftime("%Y-%m-%d %H:%M:%S", localtime), shift); |
|
72 |
- print sprintf("[%s] %s\n",strftime("%Y-%m-%d %H:%M:%S", localtime), shift); |
|
73 |
-# close LOGFILE; |
|
74 |
-} |
|
75 |
- |
|
76 |
-sub xmpp_logout($) { |
|
77 |
- # HACK |
|
78 |
- # messages may not be received if we log out too quickly... |
|
79 |
- sleep 1; |
|
80 |
- |
|
81 |
- my $cnx = shift; |
|
82 |
- $cnx->Disconnect(); |
|
83 |
- xmpp_check_result ('Disconnect',0); # well, nothing to check, really |
|
56 |
+ $mutex->down(); |
|
57 |
+ print STDERR sprintf("%s\n", shift); |
|
58 |
+ $mutex->up(); |
|
84 | 59 |
} |
85 | 60 |
|
86 | 61 |
sub terminate () { |
87 |
- my $cnx = shift; |
|
88 |
- debug_print "caught TERM"; |
|
89 |
- xmpp_logout($cnx); |
|
62 |
+ log_bot($mail_queue->pending() . " mails en attente d'envoi !") if ($mail_queue->pending() > 0); |
|
63 |
+ $mail->exit(); |
|
64 |
+ log_bot($inbox_sms_queue->pending() . " SMS en attente de traitement !") if ($inbox_sms_queue->pending() > 0); |
|
65 |
+ $inbox_sms->exit(); |
|
66 |
+ log_bot($outbox_sms_queue->pending() . " SMS en attente d'envoi !") if ($outbox_sms_queue->pending() > 0); |
|
67 |
+ $outbox_sms->exit(); |
|
68 |
+ log_bot("arrêt"); |
|
90 | 69 |
exit 0; |
91 | 70 |
} |
92 | 71 |
|
93 |
-sub error_exit { |
|
94 |
- my ($err,$cnx) = @_; |
|
95 |
- print STDERR "$err\n"; |
|
96 |
- xmpp_logout ($cnx) |
|
97 |
- if ($cnx); |
|
98 |
- exit 1; |
|
99 |
-} |
|
100 |
- |
|
101 |
-sub xmpp_check_result { |
|
102 |
- my ($txt, $res, $cnx)=@_; |
|
103 |
- |
|
104 |
- error_exit ("Error '$txt': result undefined") |
|
105 |
- unless (defined $res); |
|
106 |
- |
|
107 |
- # res may be 0 |
|
108 |
- if ($res == 0) { |
|
109 |
- debug_print "$txt"; |
|
110 |
- # result can be true or 'ok' |
|
111 |
- } |
|
112 |
- elsif ((@$res == 1 && $$res[0]) || $$res[0] eq 'ok') { |
|
113 |
- debug_print "$txt: " . $$res[0]; |
|
114 |
- # otherwise, there is some error |
|
115 |
- } |
|
116 |
- else { |
|
117 |
- my $errmsg = $cnx->GetErrorCode() || '?'; |
|
118 |
- error_exit ("Error '$txt': " . join (': ',@$res) . "[$errmsg]", $cnx); |
|
119 |
- } |
|
120 |
-} |
|
121 |
- |
|
122 |
-sub xmpp_login ($$$$$$$$$$$) { |
|
123 |
- my ($host, $port, $user, $pw, $comp, $res, $tls, $no_tls_verify, $tls_ca_path, $ssl, $debug) = @_; |
|
124 |
- my $cnx = new Net::XMPP::Client(debuglevel=>0); |
|
125 |
- error_exit "could not create XMPP client object: $!" unless ($cnx); |
|
126 |
- |
|
127 |
- my $ssl_verify = 0x01; |
|
128 |
- if ($no_tls_verify) { $ssl_verify = 0x00; } |
|
129 |
- debug_print "ssl_verify: $ssl_verify"; |
|
130 |
- |
|
131 |
- debug_print "tls_ca_path: $tls_ca_path"; |
|
132 |
- |
|
133 |
- my @res; |
|
134 |
- my $arghash = { |
|
135 |
- hostname => $host, |
|
136 |
- port => $port, |
|
137 |
- tls => $tls, |
|
138 |
- ssl_verify => $ssl_verify, |
|
139 |
- ssl_ca_path => $tls_ca_path, |
|
140 |
- ssl => $ssl, |
|
141 |
- connectiontype => 'tcpip', |
|
142 |
- componentname => $comp |
|
143 |
- }; |
|
144 |
- |
|
145 |
- delete $arghash->{port} unless $port; |
|
146 |
- if ($arghash->{port}) { |
|
147 |
- @res = $cnx->Connect(%$arghash); |
|
148 |
- error_exit ("Could not connect to '$host' on port $port: $@") unless @res; |
|
149 |
- } else { |
|
150 |
- @res = $cnx->Connect(%$arghash); |
|
151 |
- error_exit ("Could not connect to server '$host': $@") unless @res; |
|
152 |
- } |
|
153 |
- |
|
154 |
- xmpp_check_result("Connect",\@res,$cnx); |
|
155 |
- |
|
156 |
- if ($comp) { |
|
157 |
- my $sid = $cnx->{SESSION}->{id}; |
|
158 |
- $cnx->{STREAM}->{SIDS}->{$sid}->{hostname} = $comp |
|
159 |
- } |
|
160 |
- |
|
161 |
- @res = $cnx->AuthSend(#'hostname' => $host, |
|
162 |
- 'username' => $user, |
|
163 |
- 'password' => $pw, |
|
164 |
- 'resource' => $res); |
|
165 |
- xmpp_check_result('AuthSend',\@res,$cnx); |
|
166 |
- |
|
167 |
- return $cnx; |
|
168 |
-} |
|
169 |
- |
|
170 | 72 |
sub sql_request ($) { |
171 |
- my $request = shift; |
|
73 |
+ my $msg = shift; |
|
172 | 74 |
my @result; |
173 | 75 |
my $dbh = DBI->connect($cfg::config{db}->{driver}, $cfg::config{db}->{user}, $cfg::config{db}->{password}, {'RaiseError' => 1}); |
174 | 76 |
$dbh->{'mysql_enable_utf8'} = 1; |
175 | 77 |
$dbh->do(qq{SET NAMES "utf8"}); |
176 |
- my $sth = $dbh->prepare($request); |
|
78 |
+ my $sth = $dbh->prepare($msg); |
|
177 | 79 |
$sth->execute(); |
178 | 80 |
if (defined($sth->{NUM_OF_FIELDS})) { |
179 | 81 |
while (my $ref = $sth->fetchrow_hashref()) { |
... | ... |
@@ -186,19 +88,19 @@ sub sql_request ($) { |
186 | 88 |
} |
187 | 89 |
|
188 | 90 |
sub massive_send_sms { |
189 |
- my $request = shift; |
|
190 |
- if ($to_gtalksms_queue->pending() > 0) { |
|
191 |
- $to_gtalksms_queue->insert(0, [$request->{phone}, "un envoi massif est déjà en cours, lancé par " . $cfg::config{last_sender} . ", reste " . $to_gtalksms_queue->pending() . ", annulation"]); |
|
91 |
+ my $msg = shift; |
|
92 |
+ if ($outbox_sms_queue->pending() > 0) { |
|
93 |
+ $outbox_sms_queue->insert(0, [$msg->{Phone}, "un envoi massif est déjà en cours, lancé par " . $cfg::config{last_sender} . ", reste " . $outbox_sms_queue->pending() . ", annulation"]); |
|
192 | 94 |
return; |
193 | 95 |
} |
194 |
- $cfg::config{last_sender} = $request->{phone_owner}; |
|
195 |
- my @results = sql_request("SELECT phone, firstname, gender FROM " . $cfg::config{table} . " WHERE " . $cfg::config{group_prefix} . $request->{table} . " > '0'"); |
|
96 |
+ $cfg::config{last_sender} = $msg->{PhoneOwner}; |
|
97 |
+ my @results = sql_request("SELECT phone, firstname, gender FROM " . $cfg::config{table} . " WHERE " . $cfg::config{group_prefix} . $msg->{groupe} . " > '0'"); |
|
196 | 98 |
my $qty = scalar(@results); |
197 | 99 |
my $start_msg = "envoi de " . $qty . " SMS (fin prévue entre ". strftime("%H:%M", localtime(time() + $qty * 60)) . " et " . strftime("%H:%M", localtime(time() + $qty * 90)) . ")"; |
198 |
- $to_gtalksms_queue->enqueue([$request->{phone}, $start_msg]); |
|
100 |
+ $outbox_sms_queue->enqueue([$msg->{Phone}, $start_msg]); |
|
199 | 101 |
foreach my $contact (@results) { |
200 | 102 |
$contact->{phone} =~ s/[\s\.]//g; |
201 |
- $_ = $request->{body}; |
|
103 |
+ $_ = $msg->{Content}; |
|
202 | 104 |
s/\@prénom/$contact->{firstname}/g; |
203 | 105 |
if ($contact->{gender} eq 'F') { |
204 | 106 |
s/\@\(\s*(\w+)\s*,\s*\w+\s*\)/$1/g; |
... | ... |
@@ -206,64 +108,21 @@ sub massive_send_sms { |
206 | 108 |
else { |
207 | 109 |
s/\@\(\s*\w+\s*,\s*(\w+)\s*\)/$1/g; |
208 | 110 |
} |
209 |
- $to_gtalksms_queue->enqueue([$contact->{phone}, $_]) |
|
111 |
+ $outbox_sms_queue->enqueue([$contact->{phone}, $_]) |
|
210 | 112 |
} |
211 |
- $to_gtalksms_queue->enqueue([$request->{phone}, "envoi des SMS terminé !"]); |
|
113 |
+ $outbox_sms_queue->enqueue([$msg->{Phone}, "envoi des SMS terminé !"]); |
|
212 | 114 |
} |
213 | 115 |
|
214 |
-sub control_sms_flow { |
|
215 |
- my ($body, $max, $interval) = @_; |
|
216 |
- my $flow_control="/home/sms/flow.control"; |
|
217 |
-# use bytes; # les caractères UTF-8 peuvent être codés sur plus d'un octet |
|
218 |
-# my $nbr = ceil(length($$body)/140); # taille d'un SMS 140 octets |
|
219 |
- my $nbr = 1; |
|
220 |
-# no bytes; |
|
221 |
- while (1) { |
|
222 |
- my $left = $max; |
|
223 |
- my $t = time; |
|
224 |
- open (FILE, "<", $flow_control); |
|
225 |
- my @lines = <FILE>; |
|
226 |
- close FILE; |
|
227 |
- open(FILE, ">", $flow_control); |
|
228 |
- foreach my $line (@lines) { |
|
229 |
- $line =~ /(\d+)/; |
|
230 |
- my $ts = $1; |
|
231 |
- if ($ts + $interval > $t) { |
|
232 |
- $left--; |
|
233 |
- print FILE $line; |
|
234 |
- } |
|
235 |
- } |
|
236 |
- close FILE; |
|
237 |
- log_bot(" ---> to send: $nbr; left: $left"); |
|
238 |
- last if $nbr < $left; |
|
239 |
- sleep 60; |
|
240 |
- } |
|
241 |
- open (FILE,">>", $flow_control); |
|
242 |
- for (my $i = 0; $i < $nbr; $i++) { print FILE time, "\n"; } |
|
243 |
- close FILE; |
|
244 |
-} |
|
116 |
+sub send_mail { |
|
117 |
+ while (my $msg = $mail_queue->dequeue) { |
|
118 |
+ defined($msg->{to}) or $msg->{to} = $cfg::config{mail}; |
|
119 |
+ open(MAIL, "|msmtp $msg->{to}"); |
|
120 |
+ print MAIL "Subject: $msg->{Subject}\n"; |
|
121 |
+ print MAIL "Reply-To: $msg->{Email}\n" if ($msg->{Email} ne ''); |
|
245 | 122 |
|
246 |
-sub xmpp_send { |
|
247 |
- my $msg = shift; |
|
248 |
- $bot->MessageSend( |
|
249 |
- to => $cfg::config{xmpp}->{phoneBuddy}, |
|
250 |
- from => $cfg::config{xmpp}->{userName} . "@" . $cfg::config{xmpp}->{hostName}, |
|
251 |
- resource => $cfg::config{xmpp}->{resource}, |
|
252 |
- type => 'chat', |
|
253 |
- body => $$msg |
|
254 |
- ); |
|
255 |
-} |
|
256 |
- |
|
257 |
-sub ssmtp_send_mail { |
|
258 |
- while (my $request = $mail_queue->dequeue) { |
|
259 |
- defined($request->{to}) or $request->{to} = $cfg::config{mail}; |
|
260 |
- open(MAIL, "|/usr/lib/sendmail -t"); |
|
261 |
- print MAIL "Subject: $request->{subject}\n"; |
|
262 |
- print MAIL "To: $request->{to}\n"; |
|
263 |
- print MAIL "Reply-To: $request->{email}\n" if ($request->{email} ne ''); |
|
264 |
- print MAIL "$request->{body}\n"; |
|
123 |
+ print MAIL "$msg->{Content}\n"; |
|
265 | 124 |
close(MAIL); |
266 |
- log_bot("mail envoyé à $request->{to}"); |
|
125 |
+ log_bot("mail envoyé à $msg->{to}"); |
|
267 | 126 |
} |
268 | 127 |
} |
269 | 128 |
|
... | ... |
@@ -275,27 +134,38 @@ sub wait_open_time ($$) { |
275 | 134 |
} |
276 | 135 |
} |
277 | 136 |
|
278 |
-sub xmpp_send_sms { |
|
279 |
- while (my $ref = $to_gtalksms_queue->dequeue) { |
|
137 |
+sub hilink_send_sms { |
|
138 |
+ my $sendbox = HiPi::Huawei::E3531->new(); |
|
139 |
+ while (1) { |
|
140 |
+ my $sms = $outbox_sms_queue->dequeue_timed(10, 1); |
|
141 |
+ next if ! defined $sms; |
|
280 | 142 |
wait_open_time($cfg::config{close_hour}, $cfg::config{begin_hour}); # pas d'envoi entre 21h et 8h |
281 |
-# TODO lock($next_sms); |
|
282 |
-# TODO $next_sms = $$ref[0]; |
|
283 |
- xmpp_send(\"sms:$$ref[0]:$$ref[1]"); |
|
284 |
- log_bot("envoi à $$ref[0] : $$ref[1]"); |
|
285 |
- sleep 60 + int(rand(30)); # en attendant la maîtrise de cond_wait et cond_signal: cond_signal() called on unlocked variable at ./bot line 348 |
|
286 |
-# TODO cond_wait($next_sms); # attend le top |
|
143 |
+ |
|
144 |
+ if ($sendbox->{code}) { |
|
145 |
+ log_bot('sendbox new: ' . HiPi::Huawei::Errors->get_error_message($sendbox->{code})); |
|
146 |
+ } |
|
147 |
+ else { |
|
148 |
+ my $reponse = $sendbox->send_sms($$sms[0], , $$sms[1]); |
|
149 |
+ if ($reponse->{code}) { |
|
150 |
+ log_bot('send_sms: ' . HiPi::Huawei::Errors->get_error_message($reponse->{code})); |
|
151 |
+ } |
|
152 |
+ |
|
153 |
+ log_bot("envoi à $$sms[0] : $$sms[1]"); |
|
154 |
+ } |
|
155 |
+ sleep 60 + int(rand(30)); |
|
287 | 156 |
} |
157 |
+ log_bot('fin du thread outbox_sms'); |
|
288 | 158 |
} |
289 | 159 |
|
290 | 160 |
sub is_authorized { |
291 |
- my ($request) = @_; |
|
292 |
- my @results = sql_request("SELECT * FROM $cfg::config{table} WHERE phone = '$request->{phone}'"); |
|
161 |
+ my ($msg) = @_; |
|
162 |
+ my @results = sql_request("SELECT * FROM $cfg::config{table} WHERE phone = '$msg->{Phone}'"); |
|
293 | 163 |
if (scalar(@results) == 1) { |
294 | 164 |
my $_results = $results[0]; |
295 | 165 |
foreach my $column (keys(%$_results)) { |
296 | 166 |
if ($column =~ /^$cfg::config{group_prefix}/) { |
297 | 167 |
if ($results[0]->{$column} == 2) { |
298 |
- $request->{address} = $results[0]->{address}; |
|
168 |
+ $msg->{address} = $results[0]->{address}; |
|
299 | 169 |
return 1; # true |
300 | 170 |
} |
301 | 171 |
} |
... | ... |
@@ -308,21 +178,21 @@ sub is_authorized { |
308 | 178 |
} |
309 | 179 |
|
310 | 180 |
sub authorized_on_table { |
311 |
- my %request = @_; |
|
312 |
- my $table_name = $cfg::config{group_prefix} . $request{groupe}; |
|
313 |
- my @results = sql_request("SELECT * FROM $cfg::config{table} WHERE phone = '$request{id}'"); |
|
181 |
+ my %msg = @_; |
|
182 |
+ my $table_name = $cfg::config{group_prefix} . $msg{groupe}; |
|
183 |
+ my @results = sql_request("SELECT * FROM $cfg::config{table} WHERE phone = '$msg{id}'"); |
|
314 | 184 |
if (scalar(@results) == 1) { |
315 | 185 |
if (! defined($results[0]->{$table_name})) { |
316 |
- $request{error} = "le groupe $request{groupe} n'existe pas"; |
|
317 |
- $to_gtalksms_queue->insert(0, [$request{id}, $request{error}]); |
|
186 |
+ $msg{error} = "le groupe $msg{groupe} n'existe pas"; |
|
187 |
+ $outbox_sms_queue->insert(0, [$msg{id}, $msg{error}]); |
|
318 | 188 |
return 0; # false |
319 | 189 |
} |
320 | 190 |
} |
321 |
- @results = sql_request("SELECT $table_name FROM $cfg::config{table} WHERE phone = '$request{id}'"); |
|
191 |
+ @results = sql_request("SELECT $table_name FROM $cfg::config{table} WHERE phone = '$msg{id}'"); |
|
322 | 192 |
if (scalar(@results) == 1) { |
323 | 193 |
if ($results[0]->{$table_name} != 2) { |
324 |
- $request{error} = "désolé, écrire au groupe $request{groupe} n'est pas autorisé pour toi"; |
|
325 |
- $to_gtalksms_queue->insert(0, [$request{id}, $request{error}]); |
|
194 |
+ $msg{error} = "désolé, écrire au groupe $msg{groupe} n'est pas autorisé pour toi"; |
|
195 |
+ $outbox_sms_queue->insert(0, [$msg{id}, $msg{error}]); |
|
326 | 196 |
return 0; # false |
327 | 197 |
} |
328 | 198 |
else { |
... | ... |
@@ -332,10 +202,10 @@ sub authorized_on_table { |
332 | 202 |
} |
333 | 203 |
|
334 | 204 |
sub react_on_message { |
335 |
- my ($hashref , $request) = @_; |
|
205 |
+ my ($hashref , $msg) = @_; |
|
336 | 206 |
for my $regex (keys(%$hashref)) { |
337 |
- if ($request->{body} =~ m/$regex/i) { |
|
338 |
- $request->{body} =~ s/$regex//i; |
|
207 |
+ if ($msg->{Content} =~ m/$regex/i) { |
|
208 |
+ $msg->{Content} =~ s/$regex//i; |
|
339 | 209 |
$hashref->{$regex}(); |
340 | 210 |
return 1; # true |
341 | 211 |
} |
... | ... |
@@ -343,166 +213,126 @@ sub react_on_message { |
343 | 213 |
return 0; # false |
344 | 214 |
} |
345 | 215 |
|
346 |
-sub messageCB { |
|
347 |
- my ($sid, $msg) = @_; |
|
348 |
- $from_gtalksms_queue->enqueue($msg) if $msg->DefinedBody(); |
|
349 |
-} |
|
350 |
- |
|
351 |
-sub from_gtalksms_parse { |
|
352 |
- while (my $msg = $from_gtalksms_queue->dequeue) { |
|
353 |
- my %request = (body => $msg->GetBody); |
|
354 |
- my %part_from_gtalksms = ( |
|
355 |
- $cfg::gtalksms{from} => sub { # Message de +33612345678 : |
|
356 |
- $request{phone} = "0" . $1; |
|
357 |
- $request{phone_owner} = ''; |
|
358 |
- $request{email} = ''; |
|
359 |
- my @results = sql_request("SELECT * FROM " . $cfg::config{table} . " WHERE phone = '$request{phone}'"); |
|
360 |
- my $number_of_candidates = @results; |
|
361 |
- $number_of_candidates == 0 and return; |
|
362 |
- $request{phone_owner} .= '('; |
|
363 |
- foreach (@results) { |
|
364 |
- $request{phone_owner} .= "$_->{firstname} $_->{lastname}"; |
|
365 |
- --$number_of_candidates > 0 and $request{phone_owner} .= ' ou '; |
|
366 |
- $request{email} = $_->{email}; |
|
367 |
- } |
|
368 |
- $request{phone_owner} .= ')'; |
|
369 |
- log_bot("message de $request{phone} $request{phone_owner}"); |
|
370 |
- }, |
|
371 |
- $cfg::gtalksms{"delivered"} => sub { # SMS "un contenu de SMS" pour 0612345678 délivré. |
|
372 |
- log_bot("message $1 délivré pour $2"); |
|
373 |
-# TODO cond_signal($next_sms); |
|
374 |
- }, |
|
375 |
- $cfg::gtalksms{forget} => sub { # Le destinataire par défaut est 0612345678: inutile |
|
376 |
- return; |
|
377 |
- }, |
|
378 |
- ); |
|
379 |
- |
|
380 |
- my %sms_action = ( |
|
381 |
- "create flag" => sub { |
|
382 |
- my ($flag) = @_; |
|
383 |
- my $gid = getgrnam("sms-action"); |
|
384 |
- mkdir $cfg::sms_action{flagdir}; |
|
385 |
- chmod 0770, $cfg::sms_action{flagdir}; |
|
386 |
- chown $>, $gid, $cfg::sms_action{flagdir}; |
|
387 |
- |
|
388 |
- open(FLAG, ">" . $cfg::sms_action{flagdir} . "/" . $cfg::sms_action{flag}); |
|
389 |
- chmod 0660, $cfg::sms_action{flagdir} . "/" . $cfg::sms_action{flag}; |
|
390 |
- chown $>, $gid, $cfg::sms_action{flagdir} . "/" . $cfg::sms_action{flag}; |
|
391 |
- |
|
392 |
- print FLAG $$flag if defined $flag; |
|
393 |
- close FLAG; |
|
394 |
- }, |
|
395 |
- "start action" => sub { |
|
396 |
- # 0 = false |
|
397 |
- return ! system("sudo /bin/systemctl start action.service"); |
|
398 |
- }, |
|
399 |
- "get locker" => sub { |
|
400 |
- open FLAG, $cfg::sms_action{flagdir} . "/" . $cfg::sms_action{flag}; |
|
401 |
- my $locker = ''; |
|
402 |
- my $intro_ = ''; |
|
403 |
- while (<FLAG>) { |
|
404 |
- if (/^firstname:(.+)$/) { |
|
405 |
- $locker = " par " . $1; |
|
406 |
- } |
|
407 |
- if (/^intro:(.+)$/) { |
|
408 |
- $intro_ = " de test ($1)"; |
|
409 |
- } |
|
410 |
- } |
|
411 |
- close FLAG; |
|
412 |
- return "l'envoi " . $intro_ . " est déjà prévu" . $locker . ", abandon"; |
|
413 |
- }, |
|
414 |
- ); |
|
216 |
+sub inbox_sms_parse { |
|
217 |
+ while (my $msg = $inbox_sms_queue->dequeue) { |
|
415 | 218 |
|
416 | 219 |
my %part_from_user = ( |
417 |
- $cfg::user{"stop"} => sub { |
|
418 |
- log_bot("arrêt demandé par $request{phone} $request{phone_owner}"); |
|
419 |
- $bot->Disconnect(); |
|
420 |
- }, |
|
421 | 220 |
$cfg::user{"message de groupe"} => sub { |
422 |
- $request{table} = lc $1; |
|
423 |
- if (authorized_on_table(groupe => $request{table}, id => $request{phone})) { |
|
424 |
- &massive_send_sms(\%request); |
|
221 |
+ $msg->{groupe} = lc $1; |
|
222 |
+ if (authorized_on_table(groupe => $msg->{groupe}, id => $msg->{Phone})) { |
|
223 |
+ &massive_send_sms(\%$msg); |
|
425 | 224 |
} |
426 | 225 |
}, |
427 | 226 |
$cfg::user{"message pour un destinataire"} => sub { |
428 |
- $to_gtalksms_queue->enqueue([$1, $2]); |
|
227 |
+ $outbox_sms_queue->enqueue([$1, $msg->{Content}]); |
|
429 | 228 |
}, |
430 | 229 |
$cfg::user{"ping"} => sub { |
431 |
- my $envoi_en_cours = ""; |
|
432 |
- if ($to_gtalksms_queue->pending() > 0) { |
|
433 |
- $envoi_en_cours = "\nenvoi en cours de traitement " . $cfg::config{last_sender}; |
|
434 |
- } |
|
435 |
- log_bot("envoi d'un pong à $request{phone} $request{phone_owner}"); |
|
436 |
- $to_gtalksms_queue->insert(0, [$request{phone}, "pong ($phone_status)" . $envoi_en_cours]); |
|
437 |
- }, |
|
438 |
- $cfg::user{"test intro pour action"} => sub { |
|
439 |
- my $intro = $1; |
|
440 |
- if (! -r $cfg::sms_action{flag_prefix} . $intro . $cfg::sms_action{flag_suffix}) { |
|
441 |
- $to_gtalksms_queue->enqueue([$request{phone}, "l'intro $intro n'existe pas, abandon"]); |
|
442 |
- return; |
|
443 |
- } |
|
444 |
- if (-r $cfg::sms_action{flagdir} . "/" . $cfg::sms_action{flag}) { |
|
445 |
- $to_gtalksms_queue->enqueue([$request{phone}, $sms_action{"get locker"}()]); |
|
446 |
- } |
|
447 |
- else { |
|
448 |
- log_bot("demande envoi du mail des actions avec intro $intro depuis $request{phone} $request{phone_owner} à $request{address}"); |
|
449 |
- my $flag_content = "to:" . $request{address} . "\nintro:" . $intro . "\nfirstname:" . $request{phone} . " " . $request{phone_owner}; |
|
450 |
- $sms_action{"create flag"}(\$flag_content); |
|
451 |
- if ($sms_action{"start action"}()) { |
|
452 |
- $to_gtalksms_queue->enqueue([$request{phone}, "le mail de test des actions avec intro $intro envoyé à $request{address}"]); |
|
453 |
- } |
|
454 |
- else { |
|
455 |
- $to_gtalksms_queue->enqueue([$request{phone}, "problème: le mail de test des actions avec intro $intro pour $request{address}, n'est probablement pas parti"]); |
|
456 |
- } |
|
457 |
- } |
|
458 |
- }, |
|
459 |
- $cfg::user{"envoi normal pour action"} => sub { |
|
460 |
- if (-r $cfg::sms_action{flagdir} . "/" . $cfg::sms_action{flag}) { |
|
461 |
- $to_gtalksms_queue->enqueue([$request{phone}, $sms_action{"get locker"}()]); |
|
462 |
- } |
|
463 |
- else { |
|
464 |
- log_bot("demande envoi du mail des actions depuis $request{phone} $request{phone_owner}"); |
|
465 |
- $sms_action{"create flag"}(); |
|
466 |
- if ($sms_action{"start action"}()) { |
|
467 |
- $to_gtalksms_queue->enqueue([$request{phone}, "le mail des actions est parti"]); |
|
468 |
- } |
|
469 |
- else { |
|
470 |
- $to_gtalksms_queue->enqueue([$request{phone}, "problème: le mail des actions n'est probablement pas parti"]); |
|
230 |
+ my $envoi_en_cours = ''; |
|
231 |
+ if ($outbox_sms_queue->pending() > 0) { |
|
232 |
+ for (my $queue_id = $outbox_sms_queue->pending(); $queue_id >= 0; $queue_id--) { |
|
233 |
+ log_bot(Dumper($outbox_sms_queue->peek($queue_id))); |
|
471 | 234 |
} |
235 |
+ $envoi_en_cours = "\nenvoi en cours de traitement (reste " . $outbox_sms_queue->pending() . ") "; |
|
236 |
+ $envoi_en_cours .= "par $cfg::config{last_sender}" if defined($cfg::config{last_sender}); |
|
472 | 237 |
} |
238 |
+ log_bot("envoi d'un pong à $msg->{Phone} $msg->{PhoneOwner} $envoi_en_cours"); |
|
239 |
+ $outbox_sms_queue->insert(0, [$msg->{Phone}, "pong" . $envoi_en_cours]); |
|
473 | 240 |
}, |
474 | 241 |
); |
475 | 242 |
|
476 |
- if (react_on_message(\%part_from_gtalksms, \%request)) { |
|
477 |
- if (defined $request{phone} and !(is_authorized(\%request) and react_on_message(\%part_from_user, \%request))) { |
|
478 |
- $request{subject} = "SMS recu de $request{phone} $request{phone_owner}"; |
|
479 |
- $mail_queue->enqueue(\%request); |
|
480 |
- } |
|
243 |
+ $msg->{Phone} =~ s/^\+33/0/; |
|
244 |
+ $msg->{Email} = ''; |
|
245 |
+ |
|
246 |
+ my @results = sql_request("SELECT * FROM " . $cfg::config{table} . " WHERE phone = '$msg->{Phone}'"); |
|
247 |
+ my $number_of_candidates = @results; |
|
248 |
+ $number_of_candidates == 0 and return; |
|
249 |
+ $msg->{PhoneOwner} = '('; |
|
250 |
+ foreach (@results) { |
|
251 |
+ $msg->{PhoneOwner} .= "$_->{firstname} $_->{lastname}"; |
|
252 |
+ --$number_of_candidates > 0 and $msg->{PhoneOwner} .= ' ou '; |
|
253 |
+ $msg->{Email} = $_->{email}; |
|
481 | 254 |
} |
482 |
- else { |
|
483 |
- log_bot("message de type inconnu: $request{body}") unless $request{body} eq ""; |
|
255 |
+ $msg->{PhoneOwner} .= ')'; |
|
256 |
+ $msg->{Subject} = "SMS recu de $msg->{Phone} $msg->{PhoneOwner}"; |
|
257 |
+ |
|
258 |
+ if (defined $msg->{Phone} and !(is_authorized(\%$msg) and react_on_message(\%part_from_user, \%$msg))) { |
|
259 |
+ log_bot("message de $msg->{Phone} $msg->{PhoneOwner}"); |
|
260 |
+ $mail_queue->enqueue(\%$msg); |
|
484 | 261 |
} |
485 | 262 |
|
486 |
- undef %request; |
|
263 |
+ undef $msg; |
|
487 | 264 |
} |
488 | 265 |
} |
489 | 266 |
|
490 |
-$from_gtalksms->detach; # gère la file des événements produits par GTalkSMS |
|
491 |
-$to_gtalksms->detach; # gère la file des envois de SMS par GTalkSMS |
|
492 |
-$mail->detach; # gère la file des mails |
|
493 |
-$bot->SetMessageCallBacks(message => \&messageCB); |
|
267 |
+$inbox_sms->detach; # gère la file des événements produits par GTalkSMS |
|
268 |
+log_bot("inbox thread ok"); |
|
269 |
+$outbox_sms->detach; # gère la file des envois de SMS par GTalkSMS |
|
270 |
+log_bot("outbox thread ok"); |
|
271 |
+$mail->detach; # gère la file des mails |
|
272 |
+log_bot("mail thread ok"); |
|
494 | 273 |
|
495 |
-$bot->PresenceSend(); |
|
496 |
-my $roster = $bot->Roster; |
|
497 |
-$roster->add($cfg::config{xmpp}->{phoneBuddy}); |
|
274 |
+my $loop = 0; |
|
275 |
+log_bot("robot prêt"); |
|
276 |
+while ( 1 ) { |
|
498 | 277 |
|
499 |
-while(defined($bot->Process())) { |
|
500 |
- $bot->RosterGet(); |
|
501 |
- my $status = $roster->query($cfg::config{xmpp}->{phoneBuddy},'resources'); |
|
502 |
- if ($status) { |
|
503 |
- $phone_status = $status->{GTalkSMS}->{status} =~ s/^GTalkSMS - //r; |
|
278 |
+ $loop++; |
|
279 |
+ |
|
280 |
+ my $notifications = $hlink->check_notifications(); |
|
281 |
+ if ($notifications->{code}) { |
|
282 |
+ log_bot('check_notifications: ' . HiPi::Huawei::Errors->get_error_message($notifications->{code})); |
|
504 | 283 |
} |
505 |
- else { |
|
506 |
- $phone_status = ""; |
|
284 |
+#TODO elsif ($notifications->{OnlineUpdateStatus} != 10) { |
|
285 |
+#TODO trouver les significations |
|
286 |
+#TODO } |
|
287 |
+ elsif ($notifications->{UnreadMessage}) { |
|
288 |
+ my $inbox = $hlink->get_inbox(); |
|
289 |
+ if ($inbox->{code}) { |
|
290 |
+ log_bot('get_inbox: ' . HiPi::Huawei::Errors->get_error_message($inbox->{code})); |
|
291 |
+ } |
|
292 |
+ elsif (defined $inbox->{Count} and $inbox->{Count} > 0) { |
|
293 |
+# log_bot($inbox->{Count} . " messages dans inbox"); |
|
294 |
+ for (my $i = 0; $i < $inbox->{Count}; $i++) { |
|
295 |
+# log_bot("id " . $inbox->{Messages}[$i]->{Index} . ", status: " . $inbox->{Messages}[$i]->{Smstat}); |
|
296 |
+ if ($inbox->{Messages}[$i]->{Smstat}) { # message lu |
|
297 |
+ my $delete = $hlink->delete_sms($inbox->{Messages}[$i]->{Index}); |
|
298 |
+ if ($delete->{code}) { |
|
299 |
+ log_bot('delete_sms: ' . HiPi::Huawei::Errors->get_error_message($delete->{code})); |
|
300 |
+ } |
|
301 |
+# log_bot("id " . $inbox->{Messages}[$i]->{Index} . " deleted"); |
|
302 |
+ } |
|
303 |
+ else { |
|
304 |
+ $inbox_sms_queue->enqueue($inbox->{Messages}[$i]); |
|
305 |
+# log_bot("id " . $inbox->{Messages}[$i]->{Index} . " enqueued"); |
|
306 |
+ my $read = $hlink->set_sms_read($inbox->{Messages}[$i]->{Index}); |
|
307 |
+ if ($read->{code}) { |
|
308 |
+ log_bot('set_sms_read: ' . HiPi::Huawei::Errors->get_error_message($read->{code})); |
|
309 |
+ } |
|
310 |
+# log_bot("id " . $inbox->{Messages}[$i]->{Index} . " marked as read") if defined $inbox->{Messages}[$i]->{Index}; |
|
311 |
+ } |
|
312 |
+ } |
|
313 |
+ } |
|
314 |
+ } |
|
315 |
+ |
|
316 |
+#on vérifie toutes les 30 secondes |
|
317 |
+ sleep 30; |
|
318 |
+ log_bot('outbox_sms not running') unless ($outbox_sms->is_running()); |
|
319 |
+ next if ($loop % 20); |
|
320 |
+ $loop = 0; |
|
321 |
+ |
|
322 |
+# nettoyage des envoyés toutes les 10 minutes |
|
323 |
+ my $outbox = $hlink->get_outbox(); |
|
324 |
+ if ($outbox->{code}) { |
|
325 |
+ log_bot('get_outbox: ' . HiPi::Huawei::Errors->get_error_message($outbox->{code})); |
|
326 |
+ } |
|
327 |
+ elsif (defined $outbox->{Count} and $outbox->{Count} > 1) { |
|
328 |
+# log_bot($outbox->{Count} . " messages dans outbox"); |
|
329 |
+# on conserve le dernier envoyé |
|
330 |
+ for (my $i = 1; $i < $outbox->{Count}; $i++) { |
|
331 |
+ my $delete = $hlink->delete_sms($outbox->{Messages}[$i]->{Index}); |
|
332 |
+ if ($delete->{code}) { |
|
333 |
+ log_bot('delete_sms: ' . HiPi::Huawei::Errors->get_error_message($delete->{code})); |
|
334 |
+ } |
|
335 |
+# log_bot("id " . $outbox->{Messages}[$i]->{Index} . " deleted"); |
|
336 |
+ } |
|
507 | 337 |
} |
508 | 338 |
} |
... | ... |
@@ -5,49 +5,20 @@ use open ':std'; |
5 | 5 |
use utf8; |
6 | 6 |
|
7 | 7 |
%config = ( |
8 |
- xmpp => { |
|
9 |
- hostName => '192.168.xxx.xxx', # @IP serveur XMPP |
|
10 |
- portNumber => 5222, # port XMPP (en général 5222) |
|
11 |
- componentName => '192.168.xxx.xxx', # @IP serveur sms |
|
12 |
- userName => 'xxxxxxx', # user XMPP |
|
13 |
- passWord => 'xxxxxxx', # password de l'utilisateur |
|
14 |
- resource => 'xxxxxxx', # une ressource (cf RFC XMPP) |
|
15 |
- tls => 1, |
|
16 |
- connectionType => 'tcpip', |
|
17 |
- phoneBuddy => 'xxxxx@192.168.xxx.xxx', # le contact GTalkSMS sur XMPP (utilisateur@IP_serveur_XMPP) |
|
18 |
- }, |
|
19 |
- db => { |
|
20 |
- driver => "DBI:mysql:database=xxxxx;host=xxxxxx", # database: le nom de la bdd, host: l'hôte de la bdd, type: le type de bdd (sqlite, mysql, ...) |
|
21 |
- user => "xxxxxxx", # utilisateur de la base de donnée |
|
22 |
- password => "xxxxxxx", # son mot de passe |
|
23 |
- }, |
|
24 |
- DEBUG => 0, |
|
25 |
- VERBOSE => 0, |
|
26 |
- mail => 'xxxxxxx@xxxxxxx.xxx', # pour l'envoi des mails |
|
8 |
+ db => { # config du connecteur |
|
9 |
+ driver => "DBI:XXXXX:database=XXXXX;host=XXXXXXXXX", |
|
10 |
+ user => "XXXXXX", |
|
11 |
+ password => "XXXXXXXXXX", |
|
12 |
+ }, |
|
13 |
+ table => 'XXXXXXXX', # le nom de la table qui contient les infos |
|
14 |
+ group_prefix => 'XXXXXXXXX', # le préfixe des colonnes de groupes |
|
15 |
+ close_hour => 'XX', # mise en pause des envois de SMS à XX heures |
|
16 |
+ begin_hour => 'XX', # reprise des envois de SMS à XX heures |
|
17 |
+ mail => 'XXXXXXXX@XXXXXXXXXXXX', # envoi de mails (avec msmtp) à cette adresse |
|
27 | 18 |
); |
28 | 19 |
|
29 |
-# spécifique pour la liaison avec l'appli action |
|
30 |
-%sms_action = ( |
|
31 |
- flag_prefix => '/var/www/owncloud/data/xxxxxxxxxx/files/xxxxxx', |
|
32 |
- flag_suffix => '.html', |
|
33 |
- flagdir => '/xxxx/xxxxxx', |
|
34 |
- flag => 'xxxxxx', |
|
35 |
-); |
|
36 |
- |
|
37 |
-%gtalksms = ( |
|
38 |
- "from" => '^Message\s+de\s+\+33([67]\d{8})\s+:\W*', |
|
39 |
- "delivered" => '^SMS "(.+)" pour (0\d{9}) délivré\.$', |
|
40 |
- "forget" => '^Le destinataire par défaut est (\+33|0)\d{9}$', |
|
41 |
- |
|
42 |
-); |
|
43 |
- |
|
44 |
-%user = ( |
|
45 |
- "stop" => '^\s*stoppe le bousin\s*$', |
|
46 |
- "message de groupe" => '^\s*envoi\s+[aà]\s+(\w+)\s*:\W*', |
|
47 |
- "message pour un destinataire" => '^\s*sms\s+pour\s+(0\d{9})\s*:(.+)$', |
|
48 |
- "copie d'une base" => '^\s*copie\s+(\w+)\s+en\s+(\w+)(.*)$', |
|
49 |
- "ajout d'une entrée dans un base" => '^\s*ajoute\s+dans\+(\w+)\s*:\n', |
|
50 |
- "ping" => '^\s*ping\s*$', |
|
51 |
- "test intro pour action" => '^\s*test\s+intro\s+(\w+)\s*$', |
|
52 |
- "envoi normal pour action" => '^\s*action\s*$', |
|
20 |
+%user = ( # chaque clé correspond à une expression régulière qui sera testée sur le SMS reçu |
|
21 |
+ "message de groupe" => '^\s*envoi\s+[aà]\s+(\w+)\s*:\W*', |
|
22 |
+ "message pour un destinataire" => '^\s*sms\s+pour\s+(0\d{9})\s*:\W*', |
|
23 |
+ "ping" => '^\s*ping\s*$', |
|
53 | 24 |
); |