Skip to content

Instantly share code, notes, and snippets.

@run4flat
Created January 22, 2012 04:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save run4flat/1655640 to your computer and use it in GitHub Desktop.
Save run4flat/1655640 to your computer and use it in GitHub Desktop.
piddlebot!
#!/usr/bin/perl
# This is a simple IRC bot that just rot13 encrypts public messages.
# It responds to "rot13 <text to encrypt>".
use warnings;
use strict;
use POE;
use POE::Component::IRC::State;
use constant CHANNEL => '#pdl';
# Load the current piddlebot functions:
use piddlebot;
my $last_modified = (stat('piddlebot.pm'))[9];
# Create the component that will represent an IRC network.
our ($irc) = POE::Component::IRC::State->spawn();
our $my_nick = 'liddle_piddle_bot';
# Make sure the bot gets operator status
use POE::Component::IRC::Plugin::CycleEmpty;
$irc->plugin_add('CycleEmpty', POE::Component::IRC::Plugin::CycleEmpty->new());
# Create the bot session using methods in the main package, which are
# defined below. Note that irc_public, irc_message, and irc_join are just
# stubs that ensure the latest piddlebot.pm has been loaded, and then calls
# the latest do* response function. This way, I can make updates to the bot
# without having to restart it.
POE::Session->create(
package_states => [
main => [ qw(_start irc_001 irc_join irc_public irc_msg) ]
]
);
# Run the bot!
$poe_kernel->run();
#!!!!!!!!!!!!!! No lexicals below this point !!!!!!!!!!!!!!#
# The bot session has started. Register this bot with the "magnet"
# IRC component. Select a nickname. Connect to a server.
sub _start {
$irc->yield(register => "all");
$irc->yield(
connect => {
Nick => $my_nick,
Server => 'irc.perl.org',
Port => '6667',
}
);
}
# A function that ensures that the latest piddlebot.pm is in use:
sub ensure_up_to_date {
my $latest_modified = (stat('piddlebot.pm'))[9];
do 'piddlebot.pm' if $last_modified < $latest_modified;
}
# The bot has successfully connected to a server. Join a channel.
sub irc_001 {
$irc->yield(join => CHANNEL);
}
############# Modifiable Callbacks #############
# The bot has received a public message. Reload the latest and
sub irc_public {
ensure_up_to_date;
goto &do_public_response;
}
# The bot has received a public message. Parse it for commands, and
# respond to interesting things.
sub irc_msg {
ensure_up_to_date;
goto &do_private_response;
}
sub irc_join {
ensure_up_to_date;
goto &do_join;
}
############# Response and Logging Functions #############
# Save the message to the logfile:
sub log_it {
open my $logfile, '>>', 'pdl.log';
my $ts = scalar localtime;
print $logfile " [$ts] ", @_;
print $logfile "\n" if (substr($_[-1], -1) ne "\n");
}
sub say_it {
$irc->yield(privmsg => CHANNEL, join('', @_));
log_it(@_);
}
use strict;
use warnings;
our ($irc, $my_name);
# Load the channel ops file:
open my $fh, '<', 'pdl-channel-ops.txt';
my %ops;
while(my $line = <$fh>) {
chomp $line;
$ops{$line}++;
}
close $fh;
# Sub to write the verifications file out to disk:
sub write_out {
open $fh, '>', 'pdl-channel-ops.txt';
foreach my $nick (keys %ops) {
print $fh "$nick\n";
}
close $fh;
}
sub private_message {
my $nick = shift;
for my $line (@_) {
$irc->yield(privmsg => $nick, $line);
}
}
############# Doers #############
sub do_public_response {
my ($kernel, $who, $where, $msg) = @_[KERNEL, ARG0, ARG1, ARG2];
my $nick = (split /!/, $who)[0];
log_it("<$nick> $msg\n");
# Construct hyperlink if cpan is requested:
if ($msg =~ /^cpan (.+)/) {
say_it("http://p3rl.org/$1");
}
# Construct a link to the docs on the web site:
elsif ($msg =~ /^help (.+)/) {
my $to_find = $1;
(my $location = $to_find) =~ s{::}{/}g;
say_it("$nick: http://pdl.perl.org/?docs=$location&title=PDL::$to_find");
}
elsif ($msg =~ /^paste/) {
say_it("$nick: http://scsys.co.uk:8001/");
}
elsif ($msg =~ /^liddle_piddle_bot.+?trust (\S+)/) {
my $to_op = $1;
chomp $to_op;
if ($ops{$nick}) {
# Op the person:
$irc->yield(mode => '#pdl +o', $to_op);
# Add the ident as a trusted nick
$ops{$to_op}++;
write_out();
# Send the new user their temporary password:
private_message($to_op
, "Welcome, $to_op, to the inner sanctum. To learn more about what this means, please read"
, "https://github.com/PDLPorters/pdl/wiki/PDL-IRC"
);
}
else {
say_it("Silly $nick: only trusted users can tell me to trust someone");
}
}
}
sub do_private_response {
my ($who, $message) = @_[ARG0, ARG2];
my $nick = (split /!/, $who)[0];
private_message($nick, "https://github.com/PDLPorters/pdl/wiki/PDL-IRC");
}
sub do_join {
my ($who, $channel) = @_[ARG0, ARG1];
my $nick = (split /!/, $who)[0];
# send a cute message if we were the one joining:
if ($nick eq $irc->nick_name()) {
say_it("Hi everybody, I'm back!");
}
# Make an op if they're recognized:
elsif ($ops{$nick}) {
$irc->yield(mode => '#pdl +o', $nick);
say_it("Welcome back, $nick");
}
else {
say_it("Welcome, $nick");
}
}
1;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment