File Coverage

blib/lib/Bot/IRC/History.pm
Criterion Covered Total %
statement 26 69 37.6
branch 1 24 4.1
condition 0 8 0.0
subroutine 8 9 88.8
pod 0 1 0.0
total 35 111 31.5


line stmt bran cond sub pod time code
1             package Bot::IRC::History;
2             # ABSTRACT: Bot::IRC selected channel history dumped to email
3              
4 1     1   3550 use 5.014;
  1         4  
5 1     1   24 use exact;
  1         2  
  1         8  
6              
7 1     1   886 use Date::Format 'time2str';
  1         2  
  1         48  
8 1     1   490 use Date::Parse 'str2time';
  1         3236  
  1         95  
9 1     1   512 use Email::Mailer;
  1         340613  
  1         49  
10 1     1   535 use Email::Valid;
  1         53760  
  1         136  
11 1     1   474 use File::Grep 'fgrep';
  1         1520  
  1         1691  
12              
13             our $VERSION = '1.38'; # VERSION
14              
15             sub init {
16 1     1 0 6551 my ($bot) = @_;
17 1         5 my $vars = $bot->vars;
18 1 50       5 my @filter = ( ref $vars->{filter} ) ? @{ $vars->{filter} } : ( $vars->{filter} );
  0         0  
19 1         5 my $stdout_file = $bot->settings('daemon')->{stdout_file};
20              
21             $bot->hook(
22             {
23             to_me => 1,
24             text => qr/
25             ^\s*history\s+(
26             (?:
27             (?<type>on)\s+(?<date>.+?)
28             ) |
29             (?:
30             (?<type>from)\s+(?<date>.+?)\s+to\s+(?<date2>.+?)
31             ) |
32             (?:
33             (?<type>matching)\s+(?<string>.+?)
34             )
35             )\s+(?:to\s+)?(?<email>\S+)\s*$
36             /ix,
37             },
38             sub {
39 0     0   0 my ( $bot, $in, $m ) = @_;
40              
41 0 0 0     0 if ( not $in->{forum} ) {
    0 0        
    0          
    0          
    0          
    0          
42 0         0 $bot->reply_to(q{Ask me from within a specific channel.});
43             }
44 0         0 elsif ( grep { lc( $in->{forum} ) eq lc($_) } @filter ) {
45 0         0 $bot->reply_to(q{I'm not allowed to return history for this channel.});
46             }
47             elsif ( not Email::Valid->address( $m->{email} ) ) {
48 0         0 $bot->reply_to('The email address you provided does not appear to be valid.');
49             }
50             elsif ( not -f $stdout_file ) {
51 0         0 $bot->reply_to(q{Sorry. I can't seem to access a log file right now.});
52             }
53             elsif ( $m->{date} and not $m->{time_date} = str2time( $m->{date} ) ) {
54 0         0 $bot->reply_to(qq{I don't understand "$m->{date}" as a date or date/time.});
55             }
56             elsif ( $m->{date2} and not $m->{time_date2} = str2time( $m->{date2} ) ) {
57 0         0 $bot->reply_to(qq{I don't understand "$m->{date2}" as a date or date/time.});
58             }
59             else {
60 0         0 $bot->reply_to('Searching history...');
61              
62             my @matches =
63             map {
64 0         0 my $matches = $_->{matches};
65 0         0 map { $matches->{$_} } sort { $a <=> $b } keys %$matches;
  0         0  
  0         0  
66             } fgrep {
67 0         0 /^\[[^\]]*\]\s\S+\sPRIVMSG\s$in->{forum}/
68 0         0 } $stdout_file;
69              
70 0         0 my $subject;
71 0 0       0 if ( lc $m->{type} eq 'on' ) {
    0          
    0          
72 0         0 my $date = time2str( '%d/%b/%Y', $m->{time_date} );
73 0         0 my $re = qr/^\[$date/;
74 0         0 @matches = grep { $_ =~ $re } @matches;
  0         0  
75 0         0 $subject = "on date $m->{date}";
76             }
77             elsif ( lc $m->{type} eq 'from' ) {
78             @matches =
79 0         0 map { $_->{text} }
80             grep {
81             $_->{time} >= $m->{time_date} and
82             $_->{time} <= $m->{time_date2}
83 0 0       0 }
84             map {
85 0         0 /^\[([^\]]+)\]\s/;
  0         0  
86             +{
87 0         0 time => str2time($1),
88             text => $_,
89             };
90             } @matches;
91 0         0 $subject = "from $m->{date} to $m->{date2}";
92             }
93             elsif ( lc $m->{type} eq 'matching' ) {
94 0         0 @matches = grep { /$m->{string}/i } @matches;
  0         0  
95 0         0 $subject = "matching $m->{string}";
96             }
97              
98 0 0       0 if ( not @matches ) {
99 0         0 $bot->reply_to(q{I didn't find any history matching what you requested.});
100             }
101             else {
102             my $html = join( "\n", map {
103 0         0 /^\[(?<timestamp>[^\]]+)\]\s(?:\:(?<nick>[^!]+)!)?.*?PRIVMSG\s$in->{forum}\s:(?<text>.+)$/;
  0         0  
104 0         0 my $parts = {%+};
105 0   0     0 $parts->{nick} //= 'ME';
106              
107 0         0 qq{
108             <p style="text-indent: -3em; margin: 0; margin-left: 3em">
109             <i>$parts->{timestamp}</i>
110             <b>$parts->{nick}</b>
111             $parts->{text}
112             </p>
113             };
114             } @matches );
115              
116 0         0 $html =~ s|(\w+://[\w\-\.!@#$%^&*-_+=;:,]+)|<a href="$1">$1</a>|g;
117              
118             Email::Mailer->send(
119             to => $m->{email},
120             from => $m->{email},
121 0         0 subject => "IRC $in->{forum} history $subject",
122             html => $html,
123             );
124              
125             $bot->reply_to(
126 0         0 'OK. I just sent ' . $m->{email} . ' an email with ' .
127             scalar(@matches) . ' matching history lines.'
128             );
129             }
130             }
131             },
132 1         28 );
133              
134 1         23 $bot->helps( history =>
135             'Dump selected channel history to email. ' .
136             'Usage: "history on DATE EMAIL" or "history from DATE to DATE EMAIL" or "history matching STRING EMAIL".'
137             );
138             }
139              
140             1;
141              
142             __END__
143              
144             =pod
145              
146             =encoding UTF-8
147              
148             =head1 NAME
149              
150             Bot::IRC::History - Bot::IRC selected channel history dumped to email
151              
152             =head1 VERSION
153              
154             version 1.38
155              
156             =head1 SYNOPSIS
157              
158             use Bot::IRC;
159              
160             Bot::IRC->new(
161             connect => { server => 'irc.perl.org' },
162             plugins => ['History'],
163             history => { filter => ['#perl'] },
164             )->run;
165              
166             =head1 DESCRIPTION
167              
168             This L<Bot::IRC> plugin gives the bot the capability to dump channel chat
169             history to an email.
170              
171             The bot will only dump history from which the request originates. If you are
172             currently in a channel, the bot will happily dump you anything from that
173             channel's history, even prior to your joining. The idea here being that if
174             you've got access to join a channel, you have access to that channel's history.
175              
176             If you don't like this behavior, don't load this plugin.
177              
178             =head2 Requesting History
179              
180             To request channel history for the channel you're currently in:
181              
182             bot history on DATE EMAIL
183             bot history from DATE to DATE EMAIL
184             bot history matching STRING EMAIL
185              
186             =head2 Filtering Channels
187              
188             You can specify the channels to filter or disallow from history with C<vars>,
189             C<history>, C<filter>, which can be either a string or arrayref.
190              
191             Bot::IRC->new(
192             connect => { server => 'irc.perl.org' },
193             plugins => ['History'],
194             history => { filter => ['#perl'] },
195             )->run;
196              
197             =head2 SEE ALSO
198              
199             L<Bot::IRC>
200              
201             =for Pod::Coverage init
202              
203             =head1 AUTHOR
204              
205             Gryphon Shafer <gryphon@cpan.org>
206              
207             =head1 COPYRIGHT AND LICENSE
208              
209             This software is Copyright (c) 2016-2021 by Gryphon Shafer.
210              
211             This is free software, licensed under:
212              
213             The Artistic License 2.0 (GPL Compatible)
214              
215             =cut