File Coverage

blib/lib/Slack/WebHook.pm
Criterion Covered Total %
statement 102 108 94.4
branch 32 46 69.5
condition 6 16 37.5
subroutine 25 26 96.1
pod 7 8 87.5
total 172 204 84.3


line stmt bran cond sub pod time code
1             # Copyright (c) 2019, cPanel, LLC.
2             # All rights reserved.
3             # http://cpanel.net
4             #
5             # This is free software; you can redistribute it and/or modify it under the
6             # same terms as Perl itself. See L.
7              
8             package Slack::WebHook;
9              
10 1     1   247846 use strict;
  1         9  
  1         30  
11 1     1   5 use warnings;
  1         2  
  1         37  
12              
13             # ABSTRACT: Slack WebHook with preset layout & colors for sending slack notifications
14              
15             BEGIN {
16              
17 1     1   25 our $VERSION = '0.003'; # VERSION: generated by DZP::OurPkgVersion
18             }
19              
20 1         6 use Simple::Accessor qw{
21             url
22             json
23             auto_detect_utf8
24             _http
25             _started_at
26 1     1   499 };
  1         1182  
27              
28 1     1   926 use HTTP::Tiny;
  1         45679  
  1         36  
29 1     1   704 use JSON::XS ();
  1         5351  
  1         25  
30 1     1   7 use Encode ();
  1         2  
  1         21  
31              
32 1     1   5 use constant SLACK_COLOR_START => '#2b3bd9'; # blue
  1         2  
  1         56  
33 1     1   6 use constant SLACK_COLOR_OK => '#2eb886'; # green
  1         2  
  1         45  
34 1     1   5 use constant SLACK_COLOR_INFO => '#4b42f4'; # blue
  1         2  
  1         44  
35 1     1   5 use constant SLACK_COLOR_ERROR => '#cc0000'; # red
  1         2  
  1         42  
36 1     1   6 use constant SLACK_COLOR_WARNING => '#f5ca46'; # yellowish
  1         1  
  1         1058  
37              
38             sub _build_url {
39 1     1   144 die q[Missing URL, please set it using Slack::WebHook->new( url => ... )];
40             }
41              
42             sub _build__http {
43 2     2   34 return HTTP::Tiny->new(
44             default_headers => {
45             'Content-Type' => 'application/json; charset=UTF-8',
46             }
47             );
48             }
49              
50             sub _build_json {
51 1     1   6812 return JSON::XS->new->utf8(0)->pretty(1);
52             }
53              
54             # by default on
55 2     2   45 sub _build_auto_detect_utf8 { 1 }
56              
57             sub post {
58 4     4 1 3217 my ( $self, @opts ) = @_;
59              
60 4 50       45 die "post method only takes one argument: txt or hash ref"
61             if scalar @opts > 1;
62              
63 4         15 my $txt_or_ref = $opts[0];
64 4 100       16 my $data = ref $txt_or_ref ? $txt_or_ref : { text => $txt_or_ref };
65              
66 4         12 return $self->_http_post($data);
67             }
68              
69             sub post_start {
70 2     2 1 6422 my ( $self, @args ) = @_;
71              
72 2         10 $self->_started_at( scalar time() );
73              
74 2         81 return $self->_notify(
75             { color => SLACK_COLOR_START },
76             @args
77             );
78             }
79              
80             sub post_end {
81 2     2 1 5948 my ( $self, @args ) = @_;
82              
83 2   50     8 my $delta = int( ( time() - ( $self->_started_at() // 0 ) ) );
84              
85 2         19 my $timestr = '';
86              
87 2         9 my $hours = int( $delta / 3600 );
88 2 100       6 if ($hours) {
89 1         4 $delta -= $hours * 3600;
90 1 50       42 $timestr .= " " if length $timestr;
91 1 50       9 $timestr .= "$hours hour" . ( $hours > 1 ? 's' : '' );
92             }
93 2         7 my $minutes = int( $delta / 60 );
94 2 100       7 if ($minutes) {
95 1         3 $delta -= $minutes * 60;
96 1 50       5 $timestr .= " " if length $timestr;
97 1 50       5 $timestr .= "$minutes minute" . ( $minutes > 1 ? 's' : '' );
98             }
99 2         4 my $seconds = $delta;
100             {
101 2 100       2 $timestr .= " " if length $timestr;
  2         6  
102 2 50       8 $timestr .= "$seconds second" . ( $seconds > 1 ? 's' : '' );
103             }
104              
105 2 50       16 return $self->_notify(
106             {
107             color => SLACK_COLOR_OK,
108             $delta > 0 ? ( post_text => "\n_run time: ${timestr}_" ) : ()
109             },
110             @args
111             );
112             }
113              
114             sub post_ok {
115 2     2 1 8 my ( $self, @args ) = @_;
116              
117 2         11 return $self->_notify(
118             { color => SLACK_COLOR_OK },
119             @args
120             );
121              
122             # could also work
123             #return $self->notify_slack( @args );
124             }
125              
126             sub post_warning {
127 2     2 1 5467 my ( $self, @args ) = @_;
128              
129 2         10 return $self->_notify(
130             { color => SLACK_COLOR_WARNING },
131             @args
132             );
133             }
134              
135             sub post_error {
136 2     2 1 15887 my ( $self, @args ) = @_;
137              
138 2         11 return $self->_notify(
139             { color => SLACK_COLOR_ERROR },
140             @args
141             );
142             }
143              
144             sub post_info {
145 0     0 1 0 my ( $self, @args ) = @_;
146              
147 0         0 return $self->_notify(
148             { color => SLACK_COLOR_INFO },
149             @args
150             );
151             }
152              
153             sub _notify {
154 10     10   26 my ( $self, $defaults, @args ) = @_;
155              
156 10 50       35 die("defaults should be a Hash Ref") unless ref $defaults eq 'HASH';
157 10         15 my @user;
158              
159 10         25 my $nb_args = scalar @args;
160              
161 10 100       29 if ( $nb_args <= 1 ) {
162 5         14 @user = ( text => $args[0] );
163             }
164             else {
165              
166 5 50       14 if ( $nb_args % 2 ) {
167 0         0 my (@caller) = caller(1);
168 0   0     0 my $called_by = $caller[3] // 'unknown';
169              
170 0         0 die q[Invalid number of args from $called_by];
171             }
172              
173 5         13 @user = @args;
174             }
175              
176 10         33 return $self->notify_slack( %$defaults, @user );
177             }
178              
179             sub notify_slack {
180 10     10 0 28 my ( $self, @args ) = @_;
181              
182 10         15 my ( $color, $title, $text );
183              
184 10         14 my $nb_args = scalar @args;
185 10 50       23 die q[No arguments to notify_slack] unless $nb_args;
186              
187 10 50       23 if ( $nb_args == 1 ) {
188 0         0 $text = $args[0];
189             }
190             else {
191 10 50       23 die q[Invalid number of arguments] if $nb_args % 2;
192 10         27 my %opts = @args;
193              
194 10         19 $color = $opts{color};
195 10         16 $title = $opts{title}; # can be undefined
196 10   66     26 $text = $opts{text} // $opts{body} // $opts{content} // '';
      33        
      0        
197              
198 10 100       51 $text .= $opts{post_text} if defined $opts{post_text};
199             }
200              
201             # title can be undefined
202 10   50     23 $color //= SLACK_COLOR_OK;
203 10   50     20 $text //= '';
204              
205 10 100       47 my $data = {
206             attachments => [
207             {
208             defined $title ? ( title => $title ) : (),
209             color => $color,
210             text => $text,
211             mrkdwn_in => [qw/text title/],
212             }
213             ]
214             };
215              
216 10         24 return $self->_http_post($data);
217             }
218              
219             sub _http_post {
220 14     14   27 my ( $self, $data ) = @_;
221              
222 14 50       41 die unless ref $data eq 'HASH';
223              
224 14 50       42 if ( $self->auto_detect_utf8 ) {
225 14         109 foreach my $field (qw{text title post_text}) {
226 42 100       84 if ( defined $data->{$field} ) {
227 4 100       18 if ( !Encode::is_utf8( $data->{$field} ) ) {
228 3         11 Encode::_utf8_on( $data->{$field} );
229             }
230             }
231             }
232             }
233              
234 14         34 return $self->_http->post_form(
235             $self->url,
236             { payload => $self->json->encode($data) },
237             );
238              
239             }
240              
241             1;
242              
243             __END__