initial commit
|
1 |
#!/usr/bin/perl |
2 | ||
3 |
use strict; |
|
4 |
use warnings; |
|
5 | ||
6 |
use DBI; |
|
7 |
use POSIX qw/ceil strftime/; |
|
changement de moyen de commu...
|
8 |
use HiPi::Huawei::E3531; |
9 |
use HiPi::Huawei::Errors; |
|
initial commit
|
10 | |
11 |
use open ':utf8'; |
|
12 |
use open ':std'; |
|
13 |
use utf8; |
|
changement de moyen de commu...
|
14 | |
fix problème avec dequeue co...
|
15 |
#use Data::Dumper; |
initial commit
|
16 | |
17 |
use threads; |
|
18 |
use threads::shared; |
|
19 |
use Thread::Queue; |
|
changement de moyen de commu...
|
20 |
use Thread::Semaphore; |
initial commit
|
21 | |
changement de moyen de commu...
|
22 |
my $scriptconf = $0; |
initial commit
|
23 |
$scriptconf =~ s/\.pl$//; |
24 |
$scriptconf =~ s/$/.conf/; |
|
25 |
if (-r $scriptconf) { |
|
26 |
package cfg; |
|
27 |
unless (my $return = do $scriptconf) { |
|
28 |
warn "couldn't parse $scriptconf: $@" if $@; |
|
29 |
warn "couldn't do $scriptconf: $!" unless defined $return; |
|
30 |
warn "couldn't run $scriptconf" unless $return; |
|
31 |
} |
|
32 |
} |
|
33 |
else { |
|
34 |
print "pas de config\n"; |
|
35 |
exit; |
|
36 |
} |
|
37 | ||
38 |
$SIG{INT}=\&terminate; |
|
39 | ||
changement de moyen de commu...
|
40 |
my $inbox_sms_queue = Thread::Queue->new; |
41 |
my $outbox_sms_queue = Thread::Queue->new; |
|
initial commit
|
42 |
my $mail_queue = Thread::Queue->new; |
43 | ||
changement de moyen de commu...
|
44 |
my $mutex = Thread::Semaphore->new(); |
45 |
STDERR->autoflush(); |
|
initial commit
|
46 | |
changement de moyen de commu...
|
47 |
my $mail = threads->new(\&send_mail); |
initial commit
|
48 | |
changement de moyen de commu...
|
49 |
my $inbox_sms = threads->new(\&inbox_sms_parse); |
initial commit
|
50 | |
changement de moyen de commu...
|
51 |
my $outbox_sms = threads->new(\&hilink_send_sms); |
initial commit
|
52 | |
changement de moyen de commu...
|
53 |
my $hlink = HiPi::Huawei::E3531->new(); |
initial commit
|
54 | |
55 |
sub log_bot { |
|
changement de moyen de commu...
|
56 |
$mutex->down(); |
57 |
print STDERR sprintf("%s\n", shift); |
|
58 |
$mutex->up(); |
|
initial commit
|
59 |
} |
60 | ||
61 |
sub terminate () { |
|
changement de moyen de commu...
|
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"); |
|
initial commit
|
69 |
exit 0; |
70 |
} |
|
71 | ||
72 |
sub sql_request ($) { |
|
changement de moyen de commu...
|
73 |
my $msg = shift; |
initial commit
|
74 |
my @result; |
75 |
my $dbh = DBI->connect($cfg::config{db}->{driver}, $cfg::config{db}->{user}, $cfg::config{db}->{password}, {'RaiseError' => 1}); |
|
76 |
$dbh->{'mysql_enable_utf8'} = 1; |
|
77 |
$dbh->do(qq{SET NAMES "utf8"}); |
|
changement de moyen de commu...
|
78 |
my $sth = $dbh->prepare($msg); |
initial commit
|
79 |
$sth->execute(); |
80 |
if (defined($sth->{NUM_OF_FIELDS})) { |
|
81 |
while (my $ref = $sth->fetchrow_hashref()) { |
|
82 |
push @result, $ref; |
|
83 |
} |
|
84 |
} |
|
85 |
$sth->finish(); |
|
86 |
$dbh->disconnect(); |
|
87 |
return @result; |
|
88 |
} |
|
89 | ||
90 |
sub massive_send_sms { |
|
changement de moyen de commu...
|
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"]); |
|
simplification table + répon...
|
94 |
return; |
95 |
} |
|
changement de moyen de commu...
|
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'"); |
|
simplification table + répon...
|
98 |
my $qty = scalar(@results); |
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)) . ")"; |
|
changement de moyen de commu...
|
100 |
$outbox_sms_queue->enqueue([$msg->{Phone}, $start_msg]); |
simplification table + répon...
|
101 |
foreach my $contact (@results) { |
102 |
$contact->{phone} =~ s/[\s\.]//g; |
|
changement de moyen de commu...
|
103 |
$_ = $msg->{Content}; |
simplification table + répon...
|
104 |
s/\@prénom/$contact->{firstname}/g; |
105 |
if ($contact->{gender} eq 'F') { |
|
106 |
s/\@\(\s*(\w+)\s*,\s*\w+\s*\)/$1/g; |
|
réponse prioritaire au ping ...
|
107 |
} |
simplification table + répon...
|
108 |
else { |
109 |
s/\@\(\s*\w+\s*,\s*(\w+)\s*\)/$1/g; |
|
initial commit
|
110 |
} |
changement de moyen de commu...
|
111 |
$outbox_sms_queue->enqueue([$contact->{phone}, $_]) |
initial commit
|
112 |
} |
changement de moyen de commu...
|
113 |
$outbox_sms_queue->enqueue([$msg->{Phone}, "envoi des SMS terminé !"]); |
initial commit
|
114 |
} |
115 | ||
changement de moyen de commu...
|
116 |
sub send_mail { |
fix problème avec dequeue co...
|
117 |
while (1) { |
118 |
my $msg = $mail_queue->dequeue_timed(10, 1); |
|
119 |
next if ! defined $msg; |
|
changement de moyen de commu...
|
120 |
defined($msg->{to}) or $msg->{to} = $cfg::config{mail}; |
121 |
open(MAIL, "|msmtp $msg->{to}"); |
|
122 |
print MAIL "Subject: $msg->{Subject}\n"; |
|
123 |
print MAIL "Reply-To: $msg->{Email}\n" if ($msg->{Email} ne ''); |
|
initial commit
|
124 | |
changement de moyen de commu...
|
125 |
print MAIL "$msg->{Content}\n"; |
initial commit
|
126 |
close(MAIL); |
changement de moyen de commu...
|
127 |
log_bot("mail envoyé à $msg->{to}"); |
initial commit
|
128 |
} |
129 |
} |
|
130 | ||
131 |
sub wait_open_time ($$) { |
|
132 |
my ($close_hour, $open_hour) = @_; |
|
fix: heures silencieuses
|
133 |
my @lt = localtime; |
134 |
while ($lt[2] >= $close_hour or $lt[2] <= $open_hour) { |
|
initial commit
|
135 |
sleep 1800; |
136 |
} |
|
137 |
} |
|
138 | ||
changement de moyen de commu...
|
139 |
sub hilink_send_sms { |
140 |
my $sendbox = HiPi::Huawei::E3531->new(); |
|
141 |
while (1) { |
|
142 |
my $sms = $outbox_sms_queue->dequeue_timed(10, 1); |
|
143 |
next if ! defined $sms; |
|
simplification table + répon...
|
144 |
wait_open_time($cfg::config{close_hour}, $cfg::config{begin_hour}); # pas d'envoi entre 21h et 8h |
changement de moyen de commu...
|
145 | |
146 |
if ($sendbox->{code}) { |
|
147 |
log_bot('sendbox new: ' . HiPi::Huawei::Errors->get_error_message($sendbox->{code})); |
|
148 |
} |
|
149 |
else { |
|
150 |
my $reponse = $sendbox->send_sms($$sms[0], , $$sms[1]); |
|
151 |
if ($reponse->{code}) { |
|
152 |
log_bot('send_sms: ' . HiPi::Huawei::Errors->get_error_message($reponse->{code})); |
|
153 |
} |
|
154 | ||
155 |
log_bot("envoi à $$sms[0] : $$sms[1]"); |
|
156 |
} |
|
157 |
sleep 60 + int(rand(30)); |
|
initial commit
|
158 |
} |
changement de moyen de commu...
|
159 |
log_bot('fin du thread outbox_sms'); |
initial commit
|
160 |
} |
161 | ||
162 |
sub is_authorized { |
|
changement de moyen de commu...
|
163 |
my ($msg) = @_; |
164 |
my @results = sql_request("SELECT * FROM $cfg::config{table} WHERE phone = '$msg->{Phone}'"); |
|
sms/action: envoi du mail de...
|
165 |
if (scalar(@results) == 1) { |
simplification table + répon...
|
166 |
my $_results = $results[0]; |
167 |
foreach my $column (keys(%$_results)) { |
|
168 |
if ($column =~ /^$cfg::config{group_prefix}/) { |
|
169 |
if ($results[0]->{$column} == 2) { |
|
changement de moyen de commu...
|
170 |
$msg->{address} = $results[0]->{address}; |
simplification table + répon...
|
171 |
return 1; # true |
172 |
} |
|
173 |
} |
|
174 |
} |
|
175 |
return 0; # false |
|
sms/action: envoi du mail de...
|
176 |
} |
177 |
else { |
|
simplification table + répon...
|
178 |
return 0; # false |
sms/action: envoi du mail de...
|
179 |
} |
initial commit
|
180 |
} |
181 | ||
182 |
sub authorized_on_table { |
|
changement de moyen de commu...
|
183 |
my %msg = @_; |
184 |
my $table_name = $cfg::config{group_prefix} . $msg{groupe}; |
|
185 |
my @results = sql_request("SELECT * FROM $cfg::config{table} WHERE phone = '$msg{id}'"); |
|
simplification table + répon...
|
186 |
if (scalar(@results) == 1) { |
187 |
if (! defined($results[0]->{$table_name})) { |
|
changement de moyen de commu...
|
188 |
$msg{error} = "le groupe $msg{groupe} n'existe pas"; |
189 |
$outbox_sms_queue->insert(0, [$msg{id}, $msg{error}]); |
|
simplification table + répon...
|
190 |
return 0; # false |
initial commit
|
191 |
} |
192 |
} |
|
changement de moyen de commu...
|
193 |
@results = sql_request("SELECT $table_name FROM $cfg::config{table} WHERE phone = '$msg{id}'"); |
simplification table + répon...
|
194 |
if (scalar(@results) == 1) { |
195 |
if ($results[0]->{$table_name} != 2) { |
|
changement de moyen de commu...
|
196 |
$msg{error} = "désolé, écrire au groupe $msg{groupe} n'est pas autorisé pour toi"; |
197 |
$outbox_sms_queue->insert(0, [$msg{id}, $msg{error}]); |
|
simplification table + répon...
|
198 |
return 0; # false |
initial commit
|
199 |
} |
simplification table + répon...
|
200 |
else { |
201 |
return 1; # true |
|
initial commit
|
202 |
} |
203 |
} |
|
204 |
} |
|
205 | ||
206 |
sub react_on_message { |
|
changement de moyen de commu...
|
207 |
my ($hashref , $msg) = @_; |
initial commit
|
208 |
for my $regex (keys(%$hashref)) { |
changement de moyen de commu...
|
209 |
if ($msg->{Content} =~ m/$regex/i) { |
210 |
$msg->{Content} =~ s/$regex//i; |
|
initial commit
|
211 |
$hashref->{$regex}(); |
212 |
return 1; # true |
|
213 |
} |
|
214 |
} |
|
215 |
return 0; # false |
|
216 |
} |
|
217 | ||
changement de moyen de commu...
|
218 |
sub inbox_sms_parse { |
fix problème avec dequeue co...
|
219 |
while (1) { |
220 |
my $msg = $inbox_sms_queue->dequeue_timed(10, 1); |
|
221 |
next if ! defined $msg; |
|
signal d'envoi immédiat du m...
|
222 | |
initial commit
|
223 |
my %part_from_user = ( |
passage des regex dans le fi...
|
224 |
$cfg::user{"message de groupe"} => sub { |
changement de moyen de commu...
|
225 |
$msg->{groupe} = lc $1; |
226 |
if (authorized_on_table(groupe => $msg->{groupe}, id => $msg->{Phone})) { |
|
227 |
&massive_send_sms(\%$msg); |
|
simplification table + répon...
|
228 |
} |
initial commit
|
229 |
}, |
passage des regex dans le fi...
|
230 |
$cfg::user{"message pour un destinataire"} => sub { |
changement de moyen de commu...
|
231 |
$outbox_sms_queue->enqueue([$1, $msg->{Content}]); |
initial commit
|
232 |
}, |
passage des regex dans le fi...
|
233 |
$cfg::user{"ping"} => sub { |
changement de moyen de commu...
|
234 |
my $envoi_en_cours = ''; |
235 |
if ($outbox_sms_queue->pending() > 0) { |
|
fix problème avec dequeue co...
|
236 |
# for (my $queue_id = $outbox_sms_queue->pending(); $queue_id >= 0; $queue_id--) { |
237 |
# log_bot(Dumper($outbox_sms_queue->peek($queue_id))); |
|
238 |
# } |
|
changement de moyen de commu...
|
239 |
$envoi_en_cours = "\nenvoi en cours de traitement (reste " . $outbox_sms_queue->pending() . ") "; |
240 |
$envoi_en_cours .= "par $cfg::config{last_sender}" if defined($cfg::config{last_sender}); |
|
sms/action: envoi du mail de...
|
241 |
} |
changement de moyen de commu...
|
242 |
log_bot("envoi d'un pong à $msg->{Phone} $msg->{PhoneOwner} $envoi_en_cours"); |
243 |
$outbox_sms_queue->insert(0, [$msg->{Phone}, "pong" . $envoi_en_cours]); |
|
sms/action: envoi du mail de...
|
244 |
}, |
initial commit
|
245 |
); |
246 | ||
changement de moyen de commu...
|
247 |
$msg->{Phone} =~ s/^\+33/0/; |
248 |
$msg->{Email} = ''; |
|
249 | ||
250 |
my @results = sql_request("SELECT * FROM " . $cfg::config{table} . " WHERE phone = '$msg->{Phone}'"); |
|
251 |
my $number_of_candidates = @results; |
|
252 |
$number_of_candidates == 0 and return; |
|
253 |
$msg->{PhoneOwner} = '('; |
|
254 |
foreach (@results) { |
|
255 |
$msg->{PhoneOwner} .= "$_->{firstname} $_->{lastname}"; |
|
256 |
--$number_of_candidates > 0 and $msg->{PhoneOwner} .= ' ou '; |
|
257 |
$msg->{Email} = $_->{email}; |
|
initial commit
|
258 |
} |
changement de moyen de commu...
|
259 |
$msg->{PhoneOwner} .= ')'; |
260 |
$msg->{Subject} = "SMS recu de $msg->{Phone} $msg->{PhoneOwner}"; |
|
261 | ||
262 |
if (defined $msg->{Phone} and !(is_authorized(\%$msg) and react_on_message(\%part_from_user, \%$msg))) { |
|
263 |
log_bot("message de $msg->{Phone} $msg->{PhoneOwner}"); |
|
264 |
$mail_queue->enqueue(\%$msg); |
|
initial commit
|
265 |
} |
266 | ||
changement de moyen de commu...
|
267 |
undef $msg; |
initial commit
|
268 |
} |
269 |
} |
|
270 | ||
changement de moyen de commu...
|
271 |
$inbox_sms->detach; # gère la file des événements produits par GTalkSMS |
272 |
log_bot("inbox thread ok"); |
|
273 |
$outbox_sms->detach; # gère la file des envois de SMS par GTalkSMS |
|
274 |
log_bot("outbox thread ok"); |
|
275 |
$mail->detach; # gère la file des mails |
|
276 |
log_bot("mail thread ok"); |
|
initial commit
|
277 | |
changement de moyen de commu...
|
278 |
my $loop = 0; |
279 |
log_bot("robot prêt"); |
|
280 |
while ( 1 ) { |
|
initial commit
|
281 | |
changement de moyen de commu...
|
282 |
$loop++; |
283 | ||
284 |
my $notifications = $hlink->check_notifications(); |
|
285 |
if ($notifications->{code}) { |
|
286 |
log_bot('check_notifications: ' . HiPi::Huawei::Errors->get_error_message($notifications->{code})); |
|
simplification table + répon...
|
287 |
} |
changement de moyen de commu...
|
288 |
#TODO elsif ($notifications->{OnlineUpdateStatus} != 10) { |
289 |
#TODO trouver les significations |
|
290 |
#TODO } |
|
291 |
elsif ($notifications->{UnreadMessage}) { |
|
292 |
my $inbox = $hlink->get_inbox(); |
|
293 |
if ($inbox->{code}) { |
|
294 |
log_bot('get_inbox: ' . HiPi::Huawei::Errors->get_error_message($inbox->{code})); |
|
295 |
} |
|
296 |
elsif (defined $inbox->{Count} and $inbox->{Count} > 0) { |
|
297 |
# log_bot($inbox->{Count} . " messages dans inbox"); |
|
298 |
for (my $i = 0; $i < $inbox->{Count}; $i++) { |
|
299 |
# log_bot("id " . $inbox->{Messages}[$i]->{Index} . ", status: " . $inbox->{Messages}[$i]->{Smstat}); |
|
300 |
if ($inbox->{Messages}[$i]->{Smstat}) { # message lu |
|
301 |
my $delete = $hlink->delete_sms($inbox->{Messages}[$i]->{Index}); |
|
302 |
if ($delete->{code}) { |
|
303 |
log_bot('delete_sms: ' . HiPi::Huawei::Errors->get_error_message($delete->{code})); |
|
304 |
} |
|
305 |
# log_bot("id " . $inbox->{Messages}[$i]->{Index} . " deleted"); |
|
306 |
} |
|
307 |
else { |
|
308 |
$inbox_sms_queue->enqueue($inbox->{Messages}[$i]); |
|
309 |
# log_bot("id " . $inbox->{Messages}[$i]->{Index} . " enqueued"); |
|
310 |
my $read = $hlink->set_sms_read($inbox->{Messages}[$i]->{Index}); |
|
311 |
if ($read->{code}) { |
|
312 |
log_bot('set_sms_read: ' . HiPi::Huawei::Errors->get_error_message($read->{code})); |
|
313 |
} |
|
314 |
# log_bot("id " . $inbox->{Messages}[$i]->{Index} . " marked as read") if defined $inbox->{Messages}[$i]->{Index}; |
|
315 |
} |
|
316 |
} |
|
317 |
} |
|
318 |
} |
|
319 | ||
320 |
#on vérifie toutes les 30 secondes |
|
321 |
sleep 30; |
|
322 |
log_bot('outbox_sms not running') unless ($outbox_sms->is_running()); |
|
323 |
next if ($loop % 20); |
|
324 |
$loop = 0; |
|
325 | ||
326 |
# nettoyage des envoyés toutes les 10 minutes |
|
327 |
my $outbox = $hlink->get_outbox(); |
|
328 |
if ($outbox->{code}) { |
|
329 |
log_bot('get_outbox: ' . HiPi::Huawei::Errors->get_error_message($outbox->{code})); |
|
330 |
} |
|
331 |
elsif (defined $outbox->{Count} and $outbox->{Count} > 1) { |
|
332 |
# log_bot($outbox->{Count} . " messages dans outbox"); |
|
333 |
# on conserve le dernier envoyé |
|
334 |
for (my $i = 1; $i < $outbox->{Count}; $i++) { |
|
335 |
my $delete = $hlink->delete_sms($outbox->{Messages}[$i]->{Index}); |
|
336 |
if ($delete->{code}) { |
|
337 |
log_bot('delete_sms: ' . HiPi::Huawei::Errors->get_error_message($delete->{code})); |
|
338 |
} |
|
339 |
# log_bot("id " . $outbox->{Messages}[$i]->{Index} . " deleted"); |
|
340 |
} |
|
simplification table + répon...
|
341 |
} |
initial commit
|
342 |
} |