Initial release 0.001002
authorMarius Gavrilescu <marius@ieval.ro>
Sun, 16 Mar 2014 23:40:48 +0000 (01:40 +0200)
committerMarius Gavrilescu <marius@ieval.ro>
Sun, 16 Mar 2014 23:40:48 +0000 (01:40 +0200)
Changes [new file with mode: 0644]
MANIFEST [new file with mode: 0644]
Makefile.PL [new file with mode: 0644]
README [new file with mode: 0644]
devbot [new file with mode: 0755]
lib/App/Devbot.pm [new file with mode: 0644]
t/App-Devbot.t [new file with mode: 0644]

diff --git a/Changes b/Changes
new file mode 100644 (file)
index 0000000..056d809
--- /dev/null
+++ b/Changes
@@ -0,0 +1,8 @@
+App::Devbot (0.001) 13 Jun 2013
+  * Initial release
+App::Devbot (0.001001) 15 Jun 2013
+  * Log quits and nicks
+  * Add tests for quits and nicks
+  * Clean up tests
+App::Devbot (0.001002) 15 Jun 2013
+  * Fix typo: Compnent instead of Component
\ No newline at end of file
diff --git a/MANIFEST b/MANIFEST
new file mode 100644 (file)
index 0000000..16c0ba2
--- /dev/null
+++ b/MANIFEST
@@ -0,0 +1,7 @@
+Changes
+Makefile.PL
+MANIFEST
+README
+devbot
+t/App-Devbot.t
+lib/App/Devbot.pm
diff --git a/Makefile.PL b/Makefile.PL
new file mode 100644 (file)
index 0000000..9804782
--- /dev/null
@@ -0,0 +1,16 @@
+use 5.014002;
+use ExtUtils::MakeMaker;
+
+WriteMakefile(
+  NAME          => 'App::Devbot',
+  VERSION_FROM  => 'lib/App/Devbot.pm',
+  EXE_FILES     => [ 'devbot' ],
+  ABSTRACT_FROM => 'lib/App/Devbot.pm',
+  AUTHOR        => 'Marius Gavrilescu <marius@ieval.ro>',
+  LICENSE       => 'perl',
+  PREREQ_PM     => {
+       'POE::Component::IRC' => 6.37, #6.37 is the version in Debian squeeze. Hope devbot works with 6.37 :-).
+       'IRC::Utils'          => 0,
+       'File::Slurp'         => 0,
+  },
+);
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..a1480a5
--- /dev/null
+++ b/README
@@ -0,0 +1,31 @@
+App-Devbot version 0.001002
+=======================
+
+devbot is an IRC bot which provides various channel services that help software developers.
+
+Right now, it only provides channel logging and file storage. It might do more in the future.
+
+INSTALLATION
+
+To install this module type the following:
+
+   perl Makefile.PL
+   make
+   make test
+   make install
+
+DEPENDENCIES
+
+This module requires these other modules and libraries:
+
+  * POE::Component::IRC
+  * IRC::Utils
+  * File::Slurp
+
+COPYRIGHT AND LICENCE
+
+Copyright (C) 2013 by Marius Gavrilescu
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.14.2 or,
+at your option, any later version of Perl 5 you may have available.
diff --git a/devbot b/devbot
new file mode 100755 (executable)
index 0000000..299f9c3
--- /dev/null
+++ b/devbot
@@ -0,0 +1,87 @@
+#!/usr/bin/perl -wT
+use v5.14;
+
+use App::Devbot;
+
+App::Devbot->run;
+
+__END__
+
+=head1 NAME
+
+devbot - IRC bot which helps development
+
+=head1 SYNOPSIS
+
+    # devbot will connect to OFTC with SSL, join #mychan and log everything there. Its nickname will be 'devbot'.
+    devbot --channel "#mychan"
+
+    # devbot will connect to Freenode without SSL, join #asd and #qwe, and log everything there. Its nickname will be 'loggerbot'.
+    devbot --nick loggerbot --server chat.freenode.net --port 6667 --no-ssl --channel "#asd" --channel "#qwe"
+
+    # devbot will identify to NickServ with password 'passWORD123', join #bestchan on OFTC and store files sent by channel users.
+    devbot --nick mybot --password passWORD123 --channel '#bestchan' --no-log --store-files
+
+=head1 DESCRIPTION
+
+devbot is an IRC bot which helps developers collaborate.
+
+Right now, it only does channel logging and file storage. It might do more in the future.
+
+=head1 OPTIONS
+
+=over
+
+=item B<--nick> I<nickname>
+
+The nickname of devbot. Defaults to devbot.
+
+=item B<--password> I<password>
+
+If supplied, identify to NickServ with this password
+
+=item B<--server> I<hostname>
+
+The server to connect to. Defaults to irc.oftc.net.
+
+=item B<--port> I<port>
+
+The port to connect to. Defaults to 6697.
+
+=item B<--ssl>, B<--no-ssl>
+
+B<--ssl> enables connecting to the server with SSL, B<--no-ssl> disables this. Defaults to B<--ssl>.
+
+=item B<--channel> I<channel>
+
+Makes devbot connect to I<channel>. Can be supplied multiple times for multiple channels. Has no default value.
+
+=item B<--log>, B<--no-log>
+
+B<--log> enables logging events to 'logs/I<CHANNEL>/I<DATE>.txt'. B<--no-log> disables logging. Defaults to B<--log>.
+
+=item B<--store-files>, B<--no-store-files>
+
+B<--store-files> enables storing files received via DCC to 'files/I<FILENAME>'. Files are only accepted if the sender and devbot share a channel. B<Only use when all channel users are trusted>. B<--no-store-files> disables storing files. Defaults to <--no-store-files>.
+
+=item B<--trace>, B<--no-trace>
+
+B<--trace> enables POE::Component::IRC::State tracing. Useful for debugging. B<--no-trace> disables tracing. Defaults to B<--no-trace>.
+
+=back
+
+=head1 CAVEATS
+
+As stated above, the B<--store-files> option should only be used on private channels where every user is trusted.
+
+=head1 AUTHOR
+
+Marius Gavrilescu, E<lt>marius@ieval.roE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2013 by Marius Gavrilescu
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.14.2 or,
+at your option, any later version of Perl 5 you may have available.
diff --git a/lib/App/Devbot.pm b/lib/App/Devbot.pm
new file mode 100644 (file)
index 0000000..019bcc7
--- /dev/null
@@ -0,0 +1,266 @@
+package App::Devbot 0.001002;
+use v5.14;
+use warnings;
+
+use POE;
+use POE::Component::IRC::State;
+use POE::Component::IRC::Plugin::AutoJoin;
+use POE::Component::IRC::Plugin::NickServID;
+
+use File::Slurp qw/append_file/;
+use IRC::Utils qw/parse_user/;
+
+use Getopt::Long;
+use POSIX qw/strftime/;
+
+##################################################
+
+our $VERSION;
+
+my $nick='devbot';
+my $password;
+my $server='irc.oftc.net';
+my $port=6697;
+my $ssl=1;
+my @channels;
+my $trace=0;
+
+my $log=1;
+my $store_files=0;
+
+GetOptions (
+  "nick=s" => \$nick,
+  "password=s" => \$password,
+  "server=s" => \$server,
+  "port=i" => \$port,
+  "ssl!" => \$ssl,
+  "channel=s" => \@channels,
+  "log!" => \$log,
+  "store-files!" => \$store_files,
+  "trace!" => \$trace,
+);
+
+my $irc;
+
+sub mode_char {
+  my ($channel, $nick)=@_;
+  return '~' if $irc->is_channel_owner($channel, $nick);
+  return '&' if $irc->is_channel_admin($channel, $nick);
+  return '@' if $irc->is_channel_operator($channel, $nick);
+  return '%' if $irc->is_channel_halfop($channel, $nick);
+  return '+' if $irc->has_channel_voice($channel, $nick);
+  return ' '
+}
+
+sub log_event{
+  return unless $log;
+  my ($channel, @strings) = @_;
+  my $file=strftime '%F', localtime;
+  mkdir 'logs';
+  mkdir "logs/$channel";
+  append_file "logs/$channel/$file.txt", strftime ('%T ', localtime), @strings, "\n";
+}
+
+sub bot_start{
+  $irc->plugin_add (NickServID => POE::Component::IRC::Plugin::NickServID->new(Password => $password)) if defined $password;
+  $irc->plugin_add (AutoJoin => POE::Component::IRC::Plugin::AutoJoin->new(
+       Channels => \@channels,
+       RejoinOnKick => 1,
+       Rejoin_delay => 10,
+       Retry_when_banned => 60,
+  ));
+
+       $irc->yield(register => "all");
+  $irc->yield(
+       connect => {
+         Nick     => $nick,
+         Username => 'devbot',
+         Ircname  => "devbot $VERSION",
+         Server   => $server,
+         Port     => $port,
+         UseSSL   => $ssl,
+       }
+  );
+}
+
+sub on_public{
+  my ($fulluser, $channels, $message)=@_[ARG0, ARG1, ARG2];
+  my $nick=parse_user $fulluser;
+
+  for (@$channels) {
+       my $mode_char=mode_char $_, $nick;
+       log_event $_, "<$mode_char$nick> $message";
+  }
+}
+
+sub on_ctcp_action{
+  my ($fulluser, $channels, $message)=@_[ARG0, ARG1, ARG2];
+  my $nick=parse_user $fulluser;
+
+  log_event $_, "* $nick $message" for @$channels;
+}
+
+sub on_join{
+  my ($fulluser, $channel)=@_[ARG0, ARG1];
+  my ($nick, $user, $host)=parse_user $fulluser;
+
+  log_event $channel, "-!- $nick [$user\@$host] has joined $channel";
+}
+
+sub on_part{
+  my ($fulluser, $channel, $message)=@_[ARG0, ARG1, ARG2];
+  my ($nick, $user, $host)=parse_user $fulluser;
+
+  log_event $channel, "-!- $nick [$user\@$host] has left $channel [$message]";
+}
+
+sub on_kick{
+  my ($fulluser, $channel, $target, $message)=@_[ARG0, ARG1, ARG2, ARG3];
+  my $nick=parse_user $fulluser;
+
+  log_event $channel, "-!- $target was kicked from $channel by $nick [$message]";
+}
+
+sub on_mode{
+  my ($fulluser, $channel, @args)=@_[ARG0 .. $#_];
+  my $nick=parse_user $fulluser;
+  my $mode=join ' ', @args;
+
+  log_event $channel, "-!- mode/$channel [$mode] by $nick";
+}
+
+sub on_topic{
+  my ($fulluser, $channel, $topic)=@_[ARG0, ARG1, ARG2];
+  my $nick=parse_user $fulluser;
+
+  log_event $channel, "-!- $nick changed the topic of $channel to: $topic" if $topic;
+  log_event $channel, "-!- Topic unset by $nick on $channel" unless $topic;
+}
+
+sub on_nick{
+  my ($fulluser, $nick, $channels)=@_[ARG0, ARG1, ARG2];
+  my $oldnick=parse_user $fulluser;
+
+  log_event $_, "-!- $oldnick is now known as $nick" for @$channels;
+}
+
+sub on_quit{
+  my ($fulluser, $message, $channels)=@_[ARG0, ARG1, ARG2];
+  my ($nick, $user, $host)=parse_user $fulluser;
+
+  log_event $_, "-!- $nick [$user\@$host] has quit [$message]" for @$channels;
+}
+
+sub on_dcc_request{
+  return unless $store_files;
+  my ($fulluser, $type, $cookie, $name)=@_[ARG0, ARG1, ARG3, ARG4];
+  my $nick=parse_user $fulluser;
+  return unless $type eq 'SEND';
+  return unless $irc->nick_channels($nick);
+  return if $name =~ m,/,;
+
+  mkdir 'files';
+  $irc->yield(dcc_accept => $cookie, "files/$name");
+}
+
+sub run{
+  $irc=POE::Component::IRC::State->spawn();
+
+  POE::Session->create(
+       inline_states => {
+         _start  => \&bot_start,
+         irc_public => \&on_public,
+         irc_ctcp_action => \&on_ctcp_action,
+         irc_join => \&on_join,
+         irc_part => \&on_part,
+         irc_kick => \&on_kick,
+         irc_mode => \&on_mode,
+         irc_topic => \&on_topic,
+         irc_nick => \&on_nick,
+         irc_quit => \&on_quit,
+         irc_dcc_request => \&on_dcc_request
+       },
+       options => {
+         trace => $trace
+       }
+  );
+
+  $poe_kernel->run();
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+App::Devbot - IRC bot which helps development
+
+=head1 SYNOPSIS
+
+  use App::Devbot;
+  App::Devbot->run;
+
+=head1 DESCRIPTION
+
+App::Devbot is an IRC bot which helps developers collaborate.
+
+Right now, it only does channel logging and file storage. It might do more in the future.
+
+=head1 OPTIONS
+
+=over
+
+=item B<--nick> I<nickname>
+
+The nickname of devbot. Defaults to devbot.
+
+=item B<--password> I<password>
+
+If supplied, identify to NickServ with this password
+
+=item B<--server> I<hostname>
+
+The server to connect to. Defaults to irc.oftc.net.
+
+=item B<--port> I<port>
+
+The port to connect to. Defaults to 6697.
+
+=item B<--ssl>, B<--no-ssl>
+
+B<--ssl> enables connecting to the server with SSL, B<--no-ssl> disables this. Defaults to B<--ssl>.
+
+=item B<--channel> I<channel>
+
+Makes devbot connect to I<channel>. Can be supplied multiple times for multiple channels. Has no default value.
+
+=item B<--log>, B<--no-log>
+
+B<--log> enables logging events to 'logs/I<CHANNEL>/I<DATE>.txt'. B<--no-log> disables logging. Defaults to B<--log>.
+
+=item B<--store-files>, B<--no-store-files>
+
+B<--store-files> enables storing files received via DCC to 'files/I<FILENAME>'. Files are only accepted if the sender and devbot share a channel. B<Only use when all channel users are trusted>. B<--no-store-files> disables storing files. Defaults to <--no-store-files>.
+
+=item B<--trace>, B<--no-trace>
+
+B<--trace> enables POE::Component::IRC::State tracing. Useful for debugging. B<--no-trace> disables tracing. Defaults to B<--no-trace>.
+
+=back
+
+=head1 CAVEATS
+
+As stated above, the B<--store-files> option should only be used on private channels where every user is trusted.
+
+=head1 AUTHOR
+
+Marius Gavrilescu, E<lt>marius@ieval.roE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2013 by Marius Gavrilescu
+
+This library is free software; you can redistribute it and/or modify
+it under the same terms as Perl itself, either Perl version 5.14.2 or,
+at your option, any later version of Perl 5 you may have available.
diff --git a/t/App-Devbot.t b/t/App-Devbot.t
new file mode 100644 (file)
index 0000000..02b67d4
--- /dev/null
@@ -0,0 +1,53 @@
+#!/usr/bin/perl -w
+use v5.14;
+use warnings;
+no warnings 'redefine';
+
+use Test::More tests => 11;
+BEGIN { use_ok('App::Devbot') };
+
+use POE;
+
+sub call_poe{
+  my ($func, @args)=@_;
+  my @arglist;
+  $arglist[ARG0 + $_]=$args[$_] for 0 .. $#args;
+  $func->(@arglist)
+}
+
+sub set_test{
+  my ($expected, $testname) = @_;
+  *App::Devbot::log_event = sub { shift; is "@_", $expected, $testname };
+}
+
+*App::Devbot::mode_char = sub { ' ' };
+
+set_test '< nick> Hello, world!', 'public';
+call_poe \&App::Devbot::on_public, 'nick!user@host', ['#channel'], 'Hello, world!';
+
+set_test '* nick nicked', 'action';
+call_poe \&App::Devbot::on_ctcp_action, 'nick!user@host', ['#channel'], 'nicked';
+
+set_test '-!- nick [user@host] has joined #channel', 'join';
+call_poe \&App::Devbot::on_join, 'nick!user@host', '#channel';
+
+set_test '-!- nick [user@host] has left #channel [Leaving!]', 'part';
+call_poe \&App::Devbot::on_part, 'nick!user@host', '#channel', 'Leaving!';
+
+set_test '-!- idiot was kicked from #channel by nick [no reason]', 'kick';
+call_poe \&App::Devbot::on_kick, 'nick!user@host', '#channel', 'idiot', 'no reason';
+
+set_test '-!- mode/#channel [+oo mgv mgvx] by ChanServ', 'mode';
+call_poe \&App::Devbot::on_mode, 'ChanServ!user@host', '#channel', '+oo', 'mgv', 'mgvx';
+
+set_test '-!- nick changed the topic of #channel to: Go away!', 'topic set';
+call_poe \&App::Devbot::on_topic, 'nick!user@host',  '#channel', 'Go away!';
+
+set_test '-!- Topic unset by nick on #channel', 'topic unset';
+call_poe \&App::Devbot::on_topic, 'nick!user@host', '#channel', '';
+
+set_test '-!- nick is now known as newnick', 'nick';
+call_poe \&App::Devbot::on_nick, 'nick!user@host', 'newnick', ['#channel'];
+
+set_test '-!- nick [user@host] has quit [Quitting]', 'quit';
+call_poe \&App::Devbot::on_quit, 'nick!user@host', 'Quitting', ['#channel'];
This page took 0.019232 seconds and 4 git commands to generate.