File Coverage

blib/lib/App/Devbot.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package App::Devbot;
2              
3 1     1   28922 use v5.14;
  1         3  
  1         55  
4 1     1   6 use strict;
  1         2  
  1         36  
5 1     1   5 use warnings;
  1         14  
  1         51  
6             our $VERSION = 0.001004;
7              
8 1     1   520 use POE;
  0            
  0            
9             use POE::Component::IRC::State;
10             use POE::Component::IRC::Plugin::AutoJoin;
11             use POE::Component::IRC::Plugin::NickServID;
12              
13             use File::Slurp qw/append_file/;
14             use IRC::Utils qw/parse_user/;
15              
16             use Getopt::Long;
17             use POSIX qw/strftime/;
18             use Regexp::Common qw /net/;
19              
20             ##################################################
21              
22             my $nick='devbot';
23             my $password;
24             my $server='irc.oftc.net';
25             my $port=6697;
26             my $ssl=1;
27             my @channels;
28             my $trace=0;
29              
30             my $log=1;
31             my $store_files=0;
32              
33             GetOptions (
34             "nick=s" => \$nick,
35             "password=s" => \$password,
36             "server=s" => \$server,
37             "port=i" => \$port,
38             "ssl!" => \$ssl,
39             "channel=s" => \@channels,
40             "log!" => \$log,
41             "store-files!" => \$store_files,
42             "trace!" => \$trace,
43             );
44              
45             my $irc;
46              
47             sub mode_char {
48             my ($channel, $nick)=@_;
49             return '~' if $irc->is_channel_owner($channel, $nick);
50             return '&' if $irc->is_channel_admin($channel, $nick);
51             return '@' if $irc->is_channel_operator($channel, $nick);
52             return '%' if $irc->is_channel_halfop($channel, $nick);
53             return '+' if $irc->has_channel_voice($channel, $nick);
54             return ' '
55             }
56              
57             sub log_event{
58             return unless $log;
59             my ($channel, @strings) = @_;
60             my $file=strftime '%F', localtime;
61             mkdir 'logs';
62             mkdir "logs/$channel";
63             append_file "logs/$channel/$file.txt", strftime ('%T ', localtime), @strings, "\n";
64             }
65              
66             sub bot_start{
67             $irc->plugin_add (NickServID => POE::Component::IRC::Plugin::NickServID->new(Password => $password)) if defined $password;
68             $irc->plugin_add (AutoJoin => POE::Component::IRC::Plugin::AutoJoin->new(
69             Channels => \@channels,
70             RejoinOnKick => 1,
71             Rejoin_delay => 10,
72             Retry_when_banned => 60,
73             ));
74              
75             $server = $1 if $server =~ /^($RE{net}{domain})$/;
76             $port = $1 if $port =~ /^([0-9]+)$/;
77              
78             $irc->yield(register => "all");
79             $irc->yield(
80             connect => {
81             Nick => $nick,
82             Username => 'devbot',
83             Ircname => "devbot $VERSION",
84             Server => $server,
85             Port => $port,
86             UseSSL => $ssl,
87             }
88             );
89             }
90              
91             sub on_public{
92             my ($fulluser, $channels, $message)=@_[ARG0, ARG1, ARG2];
93             my $nick=parse_user $fulluser;
94              
95             for (@$channels) {
96             my $mode_char=mode_char $_, $nick;
97             log_event $_, "<$mode_char$nick> $message";
98             }
99             }
100              
101             sub on_ctcp_action{
102             my ($fulluser, $channels, $message)=@_[ARG0, ARG1, ARG2];
103             my $nick=parse_user $fulluser;
104              
105             log_event $_, "* $nick $message" for @$channels;
106             }
107              
108             sub on_join{
109             my ($fulluser, $channel)=@_[ARG0, ARG1];
110             my ($nick, $user, $host)=parse_user $fulluser;
111              
112             log_event $channel, "-!- $nick [$user\@$host] has joined $channel";
113             }
114              
115             sub on_part{
116             my ($fulluser, $channel, $message)=@_[ARG0, ARG1, ARG2];
117             my ($nick, $user, $host)=parse_user $fulluser;
118              
119             log_event $channel, "-!- $nick [$user\@$host] has left $channel [$message]";
120             }
121              
122             sub on_kick{
123             my ($fulluser, $channel, $target, $message)=@_[ARG0, ARG1, ARG2, ARG3];
124             my $nick=parse_user $fulluser;
125              
126             log_event $channel, "-!- $target was kicked from $channel by $nick [$message]";
127             }
128              
129             sub on_mode{
130             my ($fulluser, $channel, @args)=@_[ARG0 .. $#_];
131             my $nick=parse_user $fulluser;
132             my $mode=join ' ', @args;
133              
134             log_event $channel, "-!- mode/$channel [$mode] by $nick";
135             }
136              
137             sub on_topic{
138             my ($fulluser, $channel, $topic)=@_[ARG0, ARG1, ARG2];
139             my $nick=parse_user $fulluser;
140              
141             log_event $channel, "-!- $nick changed the topic of $channel to: $topic" if $topic;
142             log_event $channel, "-!- Topic unset by $nick on $channel" unless $topic;
143             }
144              
145             sub on_nick{
146             my ($fulluser, $nick, $channels)=@_[ARG0, ARG1, ARG2];
147             my $oldnick=parse_user $fulluser;
148              
149             log_event $_, "-!- $oldnick is now known as $nick" for @$channels;
150             }
151              
152             sub on_quit{
153             my ($fulluser, $message, $channels)=@_[ARG0, ARG1, ARG2];
154             my ($nick, $user, $host)=parse_user $fulluser;
155              
156             log_event $_, "-!- $nick [$user\@$host] has quit [$message]" for @$channels;
157             }
158              
159             sub on_dcc_request{
160             return unless $store_files;
161             my ($fulluser, $type, $cookie, $name)=@_[ARG0, ARG1, ARG3, ARG4];
162             my $nick=parse_user $fulluser;
163             return unless $type eq 'SEND';
164             return unless $irc->nick_channels($nick);
165             return if $name =~ m,/,;
166              
167             mkdir 'files';
168             $irc->yield(dcc_accept => $cookie, "files/$name");
169             }
170              
171             sub run{
172             $irc=POE::Component::IRC::State->spawn();
173              
174             POE::Session->create(
175             inline_states => {
176             _start => \&bot_start,
177             irc_public => \&on_public,
178             irc_ctcp_action => \&on_ctcp_action,
179             irc_join => \&on_join,
180             irc_part => \&on_part,
181             irc_kick => \&on_kick,
182             irc_mode => \&on_mode,
183             irc_topic => \&on_topic,
184             irc_nick => \&on_nick,
185             irc_quit => \&on_quit,
186             irc_dcc_request => \&on_dcc_request
187             },
188             options => {
189             trace => $trace
190             }
191             );
192              
193             $poe_kernel->run();
194             }
195              
196             1;
197              
198             __END__