Irc.pl

From Organic Design wiki
Legacy.svg Legacy: This article describes a concept that has been superseded in the course of ongoing development on the Organic Design wiki. Please do not develop this any further or base work on this concept, now this page is for historic record only.
#!/usr/bin/perl
# Code to connect to an IRC channel
# Started: 2008-06-20

use IO::Socket;
use IO::Select;

$user    = 'odserver';
$pass    = '********';
$channel = '#organicdesign';

$sock = IO::Socket::INET->new(
	PeerAddr => 'irc.freenode.net',
	PeerPort => 6667,
	Proto    => 'tcp'
) or die "could not make the connection";

while (<$sock>) {
	if (/(NOTICE AUTH).*(checking ident)/i) {
		print $sock "NICK $user\nUSER $user 0 0 :odbot.pl\n";
		last;
	}
}

while (<$sock>) {

	# if the server asks for a ping
	print $sock "PONG :".(split(/ :/, $_))[1] if /^PING/;

	# end of MOTD section
	if (/ (376|422) /) {
		print $sock "NICKSERV :identify $user $pass\n";
		last;
	}
}

# Wait for a few secs and join the channel
sleep 3;
print $sock "JOIN $channel\n";

# Main channel activity oop
my %streams = ();
my $buffer = '';
my $select = new IO::Select $sock;
while (1) {
	for my $handle ($select->can_read(1)) {
		my $stream = fileno $handle;

		if (sysread $handle, my $data, 100) {

			# Append the data to the appropriate stream
			$streams{$stream} = exists($streams{$stream}) ? $streams{$stream}.$data : $data;

			# Remove and process any complete messages in the stream
			if ($streams{$stream} =~ s/^(.*\r?\n)//s) {
				for (split /\r?\n/, $1) {

					($command, $text) = split(/ :/, $_);

					# Respond to pings if any
					if ($command eq 'PING') {
						$text =~ s/[\r\n]//g;
						print $handle "PONG $text\n";
						next;
					}

					# Extract info and tidy
					($nick, $type, $chan) = split(/ /, $_);
					($nick, $host) = split(/!/, $nick);
					$nick =~ s/://;
					$text =~ s/[:\r\n]+//;

					# Process if the line is a message in the channel
					if ($chan eq $channel) {
						$ts = localtime();
						$ts = $1 if $ts =~ /(\d\d:\d\d:\d\d)/;
						print "($ts) $nick: $text\n";

						# Respond if message is known
						if ($text =~ /(^|\W)$user(\W|$)/i) {
							$msg = "Yo $nick, you talking to me?";
							print $handle "PRIVMSG $channel :$msg\n";
							print "($ts) $user: $msg\n";
						}
					}
				}
			}
		}
	}
}