File Coverage

blib/lib/App/MonM/QNotifier.pm
Criterion Covered Total %
statement 33 134 24.6
branch 0 38 0.0
condition 0 37 0.0
subroutine 11 21 52.3
pod 10 10 100.0
total 54 240 22.5


line stmt bran cond sub pod time code
1             package App::MonM::QNotifier;
2 1     1   6 use warnings;
  1         2  
  1         27  
3 1     1   4 use strict;
  1         1  
  1         14  
4 1     1   3 use utf8;
  1         2  
  1         3  
5              
6             =encoding utf-8
7              
8             =head1 NAME
9              
10             App::MonM::QNotifier - The MonM Quick Notification Subsystem
11              
12             =head1 VERSION
13              
14             Version 1.01
15              
16             =head1 SYNOPSIS
17              
18             use App::MonM::QNotifier;
19              
20             =head1 DESCRIPTION
21              
22             This is an extension for the monm notifications
23              
24             =head2 new
25              
26             my $notifier = App::MonM::QNotifier->new(
27             config => $app->configobj,
28             );
29              
30             =head2 channel
31              
32             my $channel = $notifier->channel;
33              
34             Returns App::MonM::Channel object
35              
36             =head2 config
37              
38             my $configobj = $notifier->config;
39              
40             Returns CTK config object
41              
42             =head2 error
43              
44             my $error = $notifier->error;
45              
46             Returns error string
47              
48             $notifier->error( "error text" );
49              
50             Sets error string
51              
52             =head2 getChanelsBySendTo
53              
54             my @channels = $notifier->getChanelsBySendTo("user1, my@example.com, 123456789");
55              
56             Resolves the "SendTo" recipients and takes channels for each from it
57              
58             =head2 getGroups
59              
60             my @groups = $notifier->getGroups;
61              
62             Returns allowed groups
63              
64             =head2 getUsers
65              
66             my @users = $notifier->getUsers;
67              
68             Returns allowed users
69              
70             =head2 getUsersByGroup
71              
72             my @users = $notifier->getUsersByGroup("wheel");
73              
74             Returns users of specified group
75              
76             =head2 notify
77              
78             $notifier->notify(
79             to => ['@FooGroup, @BarGroup, testuser, foo@example.com, 11231230002'],
80             subject => "Test message",
81             message => "Text of test message",
82             before => sub {
83             my $self = shift; # App::MonM::QNotifier object (this)
84             my $message = shift; # App::MonM::Message object
85              
86             # ...
87              
88             return 1;
89             },
90             after => sub {
91             my $self = shift; # App::MonM::QNotifier object (this)
92             my $message = shift; # App::MonM::Message object
93             my $sent = shift; # Status of sending
94              
95             die ( $self->channel->error ) unless $sent;
96              
97             # ...
98              
99             return 1;
100             },
101             ) or die($notifier->error);
102              
103             Sends message (text of message) to recipients list
104              
105             The callback function "before" calls before the message sending. Must be return the true value.
106             The callback function "after" calls after the message sending. Must be return the true value
107              
108             =head2 remind
109              
110             Tries to send postponed messages
111              
112             =head1 HISTORY
113              
114             See C file
115              
116             =head1 TO DO
117              
118             See C file
119              
120             =head1 SEE ALSO
121              
122             L
123              
124             =head1 AUTHOR
125              
126             Serż Minus (Sergey Lepenkov) L Eabalama@cpan.orgE
127              
128             =head1 COPYRIGHT
129              
130             Copyright (C) 1998-2022 D&D Corporation. All Rights Reserved
131              
132             =head1 LICENSE
133              
134             This program is free software; you can redistribute it and/or
135             modify it under the same terms as Perl itself.
136              
137             See C file and L
138              
139             =cut
140              
141 1     1   32 use vars qw/$VERSION/;
  1         2  
  1         49  
142             $VERSION = '1.01';
143              
144 1     1   5 use CTK::Util qw//;
  1         2  
  1         12  
145 1     1   9 use CTK::ConfGenUtil;
  1         7  
  1         55  
146 1     1   5 use CTK::TFVals qw/ :ALL /;
  1         1  
  1         165  
147 1     1   5 use App::MonM::Util qw/parsewords merge/;
  1         2  
  1         33  
148 1     1   324 use App::MonM::Channel;
  1         3  
  1         28  
149 1     1   347 use App::MonM::Message;
  1         3  
  1         42  
150              
151             use constant {
152 1         1057 TIMEOUT => 20, # 20 sec timeout
153 1     1   5 };
  1         2  
154              
155             sub new {
156 0     0 1   my $class = shift;
157 0           my %args = @_;
158 0   0       $args{config} ||= {};
159              
160             # Get actual user list
161 0   0       my $user_conf = $args{config}->conf('user') || {};
162 0           my @users = ();
163 0           foreach my $u (keys %$user_conf) {
164 0 0 0       next unless value($user_conf => $u, "enable") || value($user_conf => $u, "enabled");
165 0           push @users, $u;
166             }
167              
168             # Get actual group list
169 0   0       my $group_conf = $args{config}->conf('group') || {};
170 0           my @groups = ();
171 0           foreach my $g (keys %$group_conf) {
172 0 0 0       next unless value($group_conf => $g, "enable") || value($group_conf => $g, "enabled");
173 0           push @groups, $g;
174             }
175              
176             # Get group users (hash of arrays)
177 0           my %group;
178 0           foreach my $g (@groups) {
179 0   0       my $gusers = array($group_conf, $g, "user") || [];
180 0           my @grpusers = qw//;
181 0           foreach my $u (@$gusers) {
182 0           my @words = parsewords($u);
183 0 0         push @grpusers, grep {value($user_conf => $_, "enable") || value($user_conf => $_, "enabled")} @words;
  0            
184             }
185 0           $group{$g} = [(CTK::Util::_uniq(@grpusers))];
186             }
187              
188             # Get Channel defaults
189 0   0       my $channels_def = hash($args{config}->conf('channel')) || {};
190              
191             # Channel object
192 0           my $channel = App::MonM::Channel->new;
193              
194             my $self = bless {
195             error => '',
196             users => [(CTK::Util::_uniq(@users))], # Allowed users
197             groups => [(CTK::Util::_uniq(@groups))], # Allowed groups
198             group => {%group}, # group => [users]
199             config => $args{config},
200 0           ch_def => $channels_def,
201             channel => $channel,
202             }, $class;
203              
204 0           return $self;
205             }
206              
207             sub error {
208 0     0 1   my $self = shift;
209 0           my $value = shift;
210 0 0         return uv2null($self->{error}) unless defined($value);
211 0           return $self->{error} = $value;
212             }
213             sub config {
214 0     0 1   my $self = shift;
215 0           $self->{config};
216             }
217             sub channel {
218 0     0 1   my $self = shift;
219 0           $self->{channel};
220             }
221             sub getUsers {
222 0     0 1   my $self = shift;
223 0   0       my $users = $self->{users} || [];
224 0           return @$users;
225             }
226             sub getGroups {
227 0     0 1   my $self = shift;
228 0   0       my $groups = $self->{groups} || [];
229 0           return @$groups;
230             }
231             sub getUsersByGroup {
232 0     0 1   my $self = shift;
233 0           my $group = shift;
234 0 0         return () unless $group;
235 0           my $users = array($self->{group}, $group);
236 0           return @$users;
237             }
238             sub getChanelsBySendTo {
239 0     0 1   my $self = shift;
240 0   0       my $rcpts_in = shift || [];
241              
242             # Get rcpts
243 0           my @rcpts_noresolved;
244 0           foreach my $it (@$rcpts_in) {
245 0           my @words = parsewords($it);
246 0           push @rcpts_noresolved, @words;
247             }
248              
249             # Resolve all rcpts
250 0           my @users = ($self->getUsers);
251 0           my %rcpts = (); # user => notation
252 0           foreach my $it (@rcpts_noresolved) {
253 0 0         next unless $it;
254 0 0         if ($it =~ /^\@(\w+)/) {
    0          
    0          
255 0           my @us = $self->getUsersByGroup($1);
256 0           foreach my $u (@us) {
257 0           $rcpts{$u} = "user";
258             }
259             } elsif ($it =~ /\@/) {
260 0           $rcpts{$it} = "email"; # E-Mail (simple notation)
261             } elsif ($it =~ /^[\(+]*\d+/) {
262 0           $it =~ s/[^0-9]//g;
263 0           $rcpts{$it} = "number";
264             } else {
265 0 0         $rcpts{$it} = "user" if grep {$_ eq $it} @users;
  0            
266             }
267             }
268              
269             # Get Channels
270 0           my @channels = (); # Channel config sections
271 0           foreach my $it (keys %rcpts) {
272 0           my $notat = $rcpts{$it};
273 0 0         if ($notat eq 'user') {
    0          
    0          
274             # Get User node
275 0           my $usernode = node($self->config->conf("user"), $it);
276 0 0 0       next unless is_hash($usernode) && keys %$usernode;
277              
278             # Get channels
279 0           my $channels_usr = hash($usernode => "channel");
280 0           foreach my $ch_name (keys %$channels_usr) {
281 0   0       my $at = lvalue($channels_usr, $ch_name, "at") || lvalue($usernode, "at");
282 0   0       my $basedon = lvalue($channels_usr, $ch_name, "basedon") || lvalue($channels_usr, $ch_name, "baseon") || '';
283             my $ch = merge(
284 0 0 0       hash($self->{ch_def}, $basedon || $ch_name),
285             hash($channels_usr, $ch_name),
286             {$at ? (at => $at) : ()},
287             );
288 0           $ch->{chname} = $ch_name;
289 0           push @channels, $ch;
290             }
291             } elsif ($notat eq 'email') {
292 0           my $ch = merge(hash($self->{ch_def}, "SendMail"), {to => $it});
293 0           $ch->{chname} = "SendMail";
294 0           push @channels, $ch;
295             } elsif ($notat eq 'number') {
296 0           my $ch = merge(hash($self->{ch_def}, "SMSGW"), {to => $it});
297 0           $ch->{chname} = "SMSGW";
298 0           push @channels, $ch;
299             }
300             }
301              
302 0           return (@channels);
303             }
304              
305             sub notify { # send message to recipients list
306 0     0 1   my $self = shift;
307 0           my %args = @_;
308 0           $self->error("");
309 0           my $before = $args{before}; # The callback for before sending
310 0           my $after = $args{after}; # The callback for after sending
311 0           my @channels = $self->getChanelsBySendTo(array($args{to}));
312              
313             # Create messages and send its
314 0           foreach my $ch (@channels) {
315             #print App::MonM::Util::explain($ch);
316             my $message = App::MonM::Message->new(
317             to => lvalue($ch, "to"),
318             cc => lvalue($ch, "cc"),
319             bcc => lvalue($ch, "bcc"),
320             from => lvalue($ch, "from"),
321             subject => $args{subject} // '', # Message subject
322 0   0       body => $args{message} // '', # Message body
      0        
323             headers => hash($ch, "headers"),
324             contenttype => lvalue($ch, "contenttype"), # optional
325             charset => lvalue($ch, "charset"), # optional
326             encoding => lvalue($ch, "encoding"), # optional
327             attachment => node($ch, "attachment"),
328             );
329              
330             # Run before callback
331 0 0         if (ref($before) eq 'CODE') {
332 0 0         &$before($self, $message) or next;
333             }
334              
335             # Send message
336 0           my $sent = $self->channel->sendmsg($message, $ch);
337              
338             # Run after callback
339 0 0         if (ref($after) eq 'CODE') {
340 0 0         &$after($self, $message, $sent) or next;
341             }
342             }
343              
344             # returns status of operation
345 0           return 1;
346             }
347              
348             sub remind { # tries to send postponed messages
349 0     0 1   my $self = shift;
350 0           $self->error("");
351 0           return 1;
352             }
353              
354             1;
355              
356             __END__