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, this is only useful for a historic record of work done. You may find a link to the currently used concept or function in this article, if not you can contact the author to find out what has taken the place of this legacy item.
#!/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";
						}
					}
				}
			}
		}
	}
}