Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

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