Stories
Slash Boxes
Comments

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Journal of rafael (2125)

Tuesday August 23, 2005
02:49 AM

Shakti, a Perl 6 bot

[ #26426 ]
Hmm, so, I wrote a very simple IRC bot in Perl 6 yesterday evening. It's a karmabot -- it implements the foo++ and bar-- commands that are familiar to purl's friends. Currently found as shakti on #mandrivafr on freenode. (Yes, karma, shakti, all that kind of stuff, we wanted to find a female sanskrit name.)

Here's the code, derived from examples/network/bot_irc.p6 in the pugs sources. Suggestions to make it more perl6ish welcome!

#!/usr/bin/pugs

use v6;

my $nick = "shakti";
my $server = "irc.freenode.net";
my $chan = "#mandrivafr";
my %karma;
my %sux = (
    php => 1,
    python => 1,
);
my %rulz = (
    perl => 1,
    perl6 => 1,
);
my $karmafile = '/tmp/shakti.dump';

sub dump_karma {
    my $fh = open($karmafile, :w) err say "Can't open $karmafile";
    $fh.say("$_:%karma{$_}") for keys %karma;
    $fh.close;
}

# load karma
my $fh = open $karmafile err die "Can't load $karmafile";
for =$fh {
    $_ .= chomp;
    my ($k, $v) = split ":", $_;
    %karma{$k} = $v;
}
$fh.close;

my $hdl = connect($server, 6667);

say "Connected to $server";

$hdl.say("NICK $nick\nUSER $nick $nick $nick $nick");
$hdl.flush;

# discard first line
my $ligne = readline($hdl);

$hdl.say("JOIN $chan");
$hdl.flush;

say "Joined $chan";

while $ligne = =$hdl {

    $ligne .= chomp;

    given $ligne {

        when rx:perl5/^PING/ {
            $hdl.say("PONG $nick");
            $hdl.flush;
        }

        when rx:perl5/^:(.*?)!.*? PRIVMSG $chan (.*)/ {
            my $nick = $0;
            my $msg = $1;
            given $msg {
                when rx:perl5/(\w+)\+\+/ {
                    if $nick eq $0 {
                        $hdl.say("PRIVMSG $chan :$nick: you can't up your own karma!");
                    }
                    else {
                        %karma{lc $0}++;
                        say "increment $0";
                        dump_karma();
                    }
                }
                when rx:perl5/(\w+)--/ {
                    %karma{lc $0}--;
                    say "decrement $0";
                    dump_karma();
                }
                when rx:perl5/\bkarma\s+(\w+)/ {
                    if $0 eq "shakti" {
                        $hdl.say("PRIVMSG $chan :I have infinite karma");
                    }
                    elsif %sux{lc $0} {
                        $hdl.say("PRIVMSG $chan :$0 has very, very bad karma");
                    }
                    elsif %rulz{lc $0} {
                        $hdl.say("PRIVMSG $chan :$0 has infinite karma");
                    }
                    elsif %karma{lc $0} {
                        $hdl.say("PRIVMSG $chan :$0 has karma of " ~ %karma{lc $0});
                    }
                    else {
                        $hdl.say("PRIVMSG $chan :$0 has neutral karma");
                    }
                    $hdl.flush;
                }
            }
        }

    };

}

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • That's quite nice, to my untrained perl5 eyes. The only thing that gives me slight difficulties is seeing ".= chomp". I'm guessing that dot is the method call operator and the line means assign the result of chomp back to $_?

    -Dom

    • That's right. I like this idiom. Maybe it looks perl5ish because my brain is still perl5ish, but in general I find perl 6 code to be quite readable.

      Meanwhile, I was pointed out a few obvious mistakes; like two variables named $nick.

  • I think you can use the named option syntax to more concisely initialize hashes where you want the values to be true:

    my %sux = (
        :php
        :python
    );

    I can't remember whether commas are needed, but I think not.

    Also, there's probably a better way of iterating through a hash's keys and values together, though I'm not sure it'll work with the statement modifier variant of for that you're using.

    Smylers