#!/usr/bin/perl
BEGIN {
local $_ = $0;
s#\\#/#g; # those ass backwards \'s annoy me
m#.*/#;
push @INC, $& . "lib";
}
$|++;
use strict;
use warnings;
use Carp qw(croak);
use Socket;
use IRC::Sock;
use IRC::Parser;
my $IRC = IRC::Sock->spawn(Host => 'irc.icq.com:6667');
my $Parser = IRC::Parser->new;
print $IRC "NICK ubu\nUSER bob \"\" \"\" :unf\n";
while(<$IRC>) {
my($origin, $command, $target, $args, $text) = $Parser->break;
my($nick, $host) = split /!/, $origin if defined $origin;
print $target . "; (" . $command . ")" . $text . "\n" if $text;
print $IRC "PONG :" . $text . "\n" if($command eq 'PING') ;
print $IRC "JOIN #bored\n" if $command eq '005';
if (defined $nick) {
if ($nick eq 'stacey' && $text =~ /^die\s*(.*)/) { print $IRC "QUIT " . $1 . "\n"; }
}
}
package IRC::Parser;
use strict;
use warnings;
# ok, the idea here..
# plugin always takes precedence, this way any protocol fixes for any ircd..
# can be easily added, defined..
# IRC does not need parsed twice, I really could give a fuck if someone thinks they
# NEED TO in some special case.. so if they define a plugin, handle the line there!! simple enough..
# and I can't see any need in defining a protocol fix twice, so I'm not iterating through a list of them
# not that it'd be anymore difficult, just it'd be pointless to do so.
sub new {
my $class = shift;
bless {
origin => undef,
command => undef,
target => undef,
args => undef,
text => undef,
raw => undef
}, $class;
}
# ?origin? - command - ?target? - ?arguments? - ?text?
sub break {
my $self = shift;
(local $_ = ($self->{raw} = shift || $_)) =~ s/[\r\n]$//g;
if(@{ $self }{qw(origin command target args text)} = $_ =~ /^
(?:\x3a(\S+)\x20+)?
(\d{3}|[A-Za-z]+)
(?:
\x20+
((?!\x3a)\S+)
\x20*
(
(?:\x20*(?!\x3a)\S+)*
)
)?
\x20*
\x3a?
(.*)
$/x) { # gotta love that gibberish, IRC is a ludicrous protocol
my @broken = ($1, ($self->{command} = uc($2)), $3, $4, $5);
wantarray() ? @broken : \@broken;
} else { warn "Failed to parse ($_); string does not conform to IRC protocol."; }
}
1;
package IRC::Sock;
use strict;
use warnings;
BEGIN {
local $_ = $0;
s#\\#/#g; # those ass backwards \'s annoy me
m#.*/#;
push @INC, $& . "lib"
}
use Socket;
use base 'IO::Handle';
use Carp qw(croak);
sub new {
@_ == 1
or croak 'usage: ' . __PACKAGE__ . '->new';
my $Sock = (!ref $_[0] ? shift : ref shift)->SUPER::new;
$Sock->autoflush(1);
$Sock
}
# IRC::Sock->spawn(
# Host => 'severed.org[:80]',
# );
sub spawn {
@_ >= 2
or croak 'usage: ' . __PACKAGE__ . '->connect(ADDRESS, PORT|SERVICE)';
my $Class = shift;
my $Sock = $Class->new;
$Sock->connect(@_);
$Sock
}
sub connect {
my($E, $Sock, %ar) = (undef, shift, @_);
my($proto, $host, $port) = $ar{Host} =~ m#^(?:(\w+)://)?((?!/).*\.[a-z]+)(?:[:/](\d+))?#i;
$port = getservbyname($proto, 'tcp')
if defined $proto && !defined $port;
socket($Sock, AF_INET, SOCK_STREAM, getprotobyname('tcp'))
or croak "Cannot create socket! ($!)";
my $iaddr = inet_aton($host)
or croak "Cannot resolve host.";
# $Sock->blocking(1);
connect($Sock, sockaddr_in($port || 6667, $iaddr)) || undef
}
1;