File Coverage

blib/lib/App/MonM/QNotifier.pm
Criterion Covered Total %
statement 33 133 24.8
branch 0 38 0.0
condition 0 37 0.0
subroutine 11 20 55.0
pod 9 9 100.0
total 53 237 22.3


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