File Coverage

blib/lib/App/MonM/Notifier.pm
Criterion Covered Total %
statement 45 45 100.0
branch n/a
condition n/a
subroutine 15 15 100.0
pod n/a
total 60 60 100.0


line stmt bran cond sub pod time code
1             package App::MonM::Notifier; # $Id: Notifier.pm 64 2019-07-14 16:06:47Z abalama $
2 1     1   53727 use warnings;
  1         10  
  1         28  
3 1     1   5 use strict;
  1         1  
  1         24  
4 1     1   479 use utf8;
  1         12  
  1         4  
5              
6             =encoding utf-8
7              
8             =head1 NAME
9              
10             App::MonM::Notifier - extension for the monm notifications
11              
12             =head1 VERSION
13              
14             Version 1.02
15              
16             =head1 SYNOPSIS
17              
18             # monotifier < /path/to/message/file.txt
19             # monotifier show
20             # monotifier show
21             # monotifier remove
22             # monotifier clean
23             # monotifier truncate
24              
25             =head1 DESCRIPTION
26              
27             This is an extension for the monm notifications over different
28             communication channels
29              
30             =head1 CONFIGURATION
31              
32            
33              
34             #
35             # !!! WARNING !!!
36             #
37             # Before using the third-party database, please create the monotifier table
38             #
39              
40             #-- For SQLite DB
41             #CREATE TABLE IF NOT EXISTS `monotifier` (
42             # `id` int(11) NOT NULL COMMENT 'ID',
43             # `to` char(255) DEFAULT NULL COMMENT 'Recipient name',
44             # `channel` char(255) DEFAULT NULL COMMENT 'Recipient channel',
45             # `subject` text COMMENT 'Message subject',
46             # `message` text COMMENT 'Message content',
47             # `pubdate` int(11) DEFAULT NULL COMMENT 'Date (unixtime) of the publication',
48             # `expires` int(11) DEFAULT NULL COMMENT 'Date (unixtime) of the expire',
49             # `status` char(32) DEFAULT NULL COMMENT 'Status of transaction',
50             # `comment` char(255) DEFAULT NULL COMMENT 'Comment',
51             # `errcode` int(11) DEFAULT NULL COMMENT 'Error code',
52             # `errmsg` text COMMENT 'Error message',
53             # PRIMARY KEY (`id`),
54             # KEY `I_ID` (`id`)
55             #) ENGINE=MyISAM DEFAULT CHARSET=utf8
56              
57             # SQLite example:
58             #
59             # DSN "dbi:SQLite:dbname=/tmp/monm/monotifier.db"
60             # Set RaiseError 0
61             # Set PrintError 0
62             # Set sqlite_unicode 1
63             #
64              
65             # MySQL example:
66             #
67             # DSN "DBI:mysql:database=monotifier;host=mysql.example.com"
68             # User username
69             # Password password
70             # Set RaiseError 0
71             # Set PrintError 0
72             # Set mysql_enable_utf8 1
73             #
74              
75             # Expires and timeout values
76             Expires +1M
77             Timeout 300
78              
79            
80              
81             # User configuration
82            
83             Period 7:00-23:00
84              
85            
86             Type Email
87             To test@example.com
88            
89              
90            
91             Type Command
92             Period 8:00-22:00
93             To +1 123 458 7789
94             Command monotifiersms.pl
95            
96            
97              
98             =head2 EXAMPLE
99              
100            
101             # Global period (default for all channels)
102             Period 7:00-21:00
103              
104             # Email via SMTP
105            
106             Type Email
107              
108             # Real To and From
109             To test@example.com
110             From root@example.com
111              
112             # Options
113             #Encoding base64
114              
115             # Headers
116            
117             X-Foo foo
118             X-Bar bar
119            
120              
121             # SMTP options
122             # If there are requirements to the register of parameter
123             # names, use the Set directive, for example:
124             # By default will use section of general config file
125             Set host 192.168.0.1
126             #Set port 25
127             #Set sasl_username TeStUser
128             #Set sasl_password MyPassword
129              
130             # Local period (default for this channel only)
131             Period 7:30-16:30
132              
133             # Calendar settings for this channel
134             # Sun Mon Tue Wed Thu Fri Sat
135             # ... or:
136             # Sunday Monday Tuesday Wednesday Thursday Friday Saturday
137             Sun - # disable!
138             Mon 7:35-17:45
139             Tue 15-19
140             Wed -
141             Thu 16-18:01
142             Fri 18:01-19
143             Sat -
144              
145            
146              
147             # Simple Email example
148            
149             # Using section
150             Type Email
151             To test@example.com
152            
153              
154             # Save to file by mask
155            
156             Type File
157              
158             # Real To and From
159             To testuser
160             From root
161              
162             # Options
163             #Encoding base64
164              
165             # Headers
166            
167             X-Mailer foo
168            
169              
170             #Dir /path/to/messages/dir
171             #File [TO]_[DATETIME]_[ID].[EXT]
172              
173             Period 10:00-23:00
174             #Thu 7:45-14:25
175             #Sun -
176             #Fri 0:0-1:0
177              
178            
179              
180             # Send serialized message to STDIN of external program
181            
182             Type Command
183              
184             # Real To and From
185             To testuser
186             From root
187              
188             # Options
189             #Encoding base64
190              
191            
192             X-Foo foo
193             X-Bar bar
194            
195              
196             Command "grep MIME > t.msg"
197              
198             Period 00:00-23:59
199              
200            
201              
202            
203              
204             =head1 HISTORY
205              
206             See C file
207              
208             =head1 DEPENDENCIES
209              
210             L, L
211              
212             =head1 TO DO
213              
214             See C file
215              
216             =head1 BUGS
217              
218             * none noted
219              
220             =head1 SEE ALSO
221              
222             L
223              
224             =head1 AUTHOR
225              
226             Serż Minus (Sergey Lepenkov) L Eabalama@cpan.orgE
227              
228             =head1 COPYRIGHT
229              
230             Copyright (C) 1998-2019 D&D Corporation. All Rights Reserved
231              
232             =head1 LICENSE
233              
234             This program is free software; you can redistribute it and/or
235             modify it under the same terms as Perl itself.
236              
237             See C file and L
238              
239             =cut
240              
241 1     1   65 use vars qw/$VERSION/;
  1         1  
  1         50  
242             $VERSION = '1.02';
243              
244 1     1   4 use feature qw/say/;
  1         2  
  1         94  
245              
246 1     1   437 use Encode;
  1         8183  
  1         57  
247 1     1   351 use Encode::Locale;
  1         2590  
  1         36  
248 1     1   6 use Carp;
  1         1  
  1         37  
249              
250 1     1   378 use Text::SimpleTable;
  1         2004  
  1         26  
251              
252 1     1   361 use App::MonM::Const;
  1         3813  
  1         52  
253 1     1   347 use App::MonM::Util qw/ explain /;
  1         140682  
  1         59  
254              
255 1     1   344 use App::MonM::Notifier::Const;
  1         2  
  1         58  
256 1     1   358 use App::MonM::Notifier::Agent;
  1         4  
  1         32  
257              
258 1     1   7 use base qw/ CTK::App /;
  1         1  
  1         378  
259              
260             use constant {
261 1         1290 ROWS_LIMIT => 1000,
262             TABLE_INFO => [(
263             [12, 'NAME'],
264             [68, 'VALUE'],
265             )],
266             TABLE_ALL => [(
267             [5, 'ID'],
268             [20, 'TO'],
269             [20, 'CHANNEL'],
270             [32, 'SUBJECT'],
271             [8, 'STATUS'],
272             [3, 'ERR'],
273             )],
274 1     1   5247 };
  1         2  
275              
276             __PACKAGE__->register_handler(
277             handler => "create",
278             description => "Create message",
279             code => sub {
280             ### CODE:
281             my ($self, $meta, @arguments) = @_;
282             my $toa = $self->option("username");
283             my $sbj = decode( locale => $self->option("subject") ) // '';
284             my $msg = (-t STDIN) ? '' : decode( locale => scalar(do { local $/; }) ) // '';
285             unless (length($msg)) {
286             $self->error("No message");
287             return 0;
288             }
289              
290             # Create agent instance
291             my $agent = new App::MonM::Notifier::Agent(
292             config => $self->configobj, # Config object
293             users => $toa, # undef or []
294             );
295             unless ($agent->status) {
296             $self->error($agent->error);
297             return 0;
298             }
299              
300             # Create message
301             $agent->create(
302             #to => "test", # For example!
303             subject => $sbj,
304             message => $msg,
305             ) or do {
306             $self->error($agent->error);
307             return 0;
308             };
309              
310             return 1;
311             });
312              
313             __PACKAGE__->register_handler(
314             handler => "send",
315             description => "Send created messages",
316             code => sub {
317             ### CODE:
318             my ($self, $meta, @arguments) = @_;
319              
320             # Create agent instance
321             my $agent = new App::MonM::Notifier::Agent(
322             config => $self->configobj, # Config object
323             users => $self->option("username"),
324             );
325             unless ($agent->status) {
326             $self->error($agent->error);
327             return 0;
328             }
329              
330             # Send messages
331             $agent->trysend() or do {
332             $self->error($agent->error);
333             return 0;
334             };
335              
336             return 1;
337             });
338              
339             __PACKAGE__->register_handler(
340             handler => "remove",
341             description => "Remove message by id",
342             code => sub {
343             ### CODE:
344             my ($self, $meta, @arguments) = @_;
345             my $id = shift(@arguments) || 0;
346             unless ($id) {
347             $self->error("Incorrect id");
348             return 0;
349             }
350              
351             # Create agent instance
352             my $agent = new App::MonM::Notifier::Agent(
353             config => $self->configobj, # Config object
354             );
355             unless ($agent->status) {
356             $self->error($agent->error);
357             return 0;
358             }
359              
360             # Remove messages
361             my $store = $agent->store;
362             $store->del($id) or do {
363             $self->error($store->error);
364             return 0;
365             };
366              
367             return 1;
368             });
369              
370             __PACKAGE__->register_handler(
371             handler => "show",
372             description => "Show messages",
373             code => sub {
374             ### CODE:
375             my ($self, $meta, @arguments) = @_;
376             my $id = shift(@arguments) || 0;
377              
378             # Create agent instance
379             my $agent = new App::MonM::Notifier::Agent(
380             config => $self->configobj, # Config object
381             );
382             unless ($agent->status) {
383             $self->error($agent->error);
384             return 0;
385             }
386              
387             # Get store
388             my $store = $agent->store;
389              
390             # Show message
391             if ($id) {
392             my %info = $store->get($id);
393             unless ($store->status) {
394             $self->error($store->error);
395             return 0;
396             };
397             unless ($info{id}) {
398             $self->error("Data not found");
399             return 0;
400             };
401              
402             my $tbl_hdrs = TABLE_INFO;
403             $tbl_hdrs->[1][0] = (SCREENWIDTH() - 20);
404             my $tbl = Text::SimpleTable->new(@$tbl_hdrs);
405             my $exp = $info{expires} || 0;
406             $tbl->row("ID", $id);
407             $tbl->row("TO", $info{to} // '');
408             $tbl->row("CHANNEL", $info{channel} // '');
409             $tbl->row("SUBJECT", encode( locale => $info{subject} // '' ));
410             $tbl->row("PUBDATE", $info{pubdate} ? scalar(localtime($info{pubdate})) : '');
411             $tbl->row("EXPIRES", $info{expires} ? scalar(localtime($info{expires})) : '');
412             $tbl->row("STATUS", $info{status} // '');
413             $tbl->row("COMMENT", encode( locale => $info{comment} // '' ));
414             $tbl->row("ERRCODE", $info{errcode} // 0);
415             $tbl->row("ERRMSG", encode( locale => $info{errmsg} // '' ));
416             $tbl->hr;
417             $tbl->row("SUMMARY", ($exp < time) ? JOB_EXPIRED : $info{status} // '');
418             say $tbl->draw();
419             say encode( locale => $info{message} // '' ) if $self->verbosemode;
420             return 1;
421             } else {
422             my @table = $store->getall(ROWS_LIMIT);
423             unless ($store->status) {
424             $self->error($store->error);
425             return 0;
426             };
427             unless (@table) {
428             $self->error("Data not found");
429             return 0;
430             };
431             if ($self->testmode) {
432             print(explain(\@table));
433             return 1;
434             }
435             my $tbl_hdrs = TABLE_ALL;
436             my $tbl = Text::SimpleTable->new(@$tbl_hdrs);
437             my @errors;
438             foreach my $rec (sort {$a->[0] <=> $b->[0]} @table) {
439             $tbl->row(
440             $rec->[0] // 0, # ID
441             $rec->[1] // '', # TO
442             $rec->[2] // '', # CHANNEL
443             encode( locale => $rec->[3] // '' ), # SUBJECT
444             $rec->[6] // '', # STATUS
445             $rec->[8] // 0, # ERRCODE
446             );
447             push @errors, $rec->[9] if $rec->[8];
448             }
449             say $tbl->draw();
450             if ($self->verbosemode && @errors) {
451             say(sprintf("\n%s BEGIN ERROR STACK -----", "-" x (SCREENWIDTH() - 24)));
452             print(join("\n\n", @errors));
453             say(sprintf("%s END ERROR STACK -----", "-" x (SCREENWIDTH() - 22)));
454             }
455             }
456              
457             return 1;
458             });
459              
460             __PACKAGE__->register_handler(
461             handler => "clean",
462             description => "Remove incorrect messages",
463             code => sub {
464             ### CODE:
465             my ($self, $meta, @arguments) = @_;
466              
467             # Create agent instance
468             my $agent = new App::MonM::Notifier::Agent(
469             config => $self->configobj, # Config object
470             );
471             unless ($agent->status) {
472             $self->error($agent->error);
473             return 0;
474             }
475              
476             # Remove messages
477             my $store = $agent->store;
478             $store->clean() or do {
479             $self->error($store->error);
480             return 0;
481             };
482              
483             return 1;
484             });
485              
486             __PACKAGE__->register_handler(
487             handler => "truncate",
488             description => "Remove all messages",
489             code => sub {
490             ### CODE:
491             my ($self, $meta, @arguments) = @_;
492              
493             # Create agent instance
494             my $agent = new App::MonM::Notifier::Agent(
495             config => $self->configobj, # Config object
496             );
497             unless ($agent->status) {
498             $self->error($agent->error);
499             return 0;
500             }
501              
502             # Remove messages
503             my $store = $agent->store;
504             $store->truncate() or do {
505             $self->error($store->error);
506             return 0;
507             };
508              
509             return 1;
510             });
511              
512             1;
513              
514             __END__