Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

POE IRC bot failing and I don't know the source of the error...

Status
Not open for further replies.

plasmatwin

Programmer
Nov 1, 2005
31
GB
Hi,

I'm frustrated at the moment because my IRC bot has stopped functioning and I don't know why. I made allot of changes without testing it and I don't know what went wrong... It gives me an error saying:
Code:
getservbyname error 99: Cannot assign requested address

I tested a simple POE irc bot on the computer and it connects perfectly, so I assume it must be a problem with my script... :/

I guess my only choice is to paste the whole script here and ask for help with debugging... I have no idea what is not working, it all looks fine to me. Bear in mind this script is still being worked on heavily so there are peices of code commented out all over the place and they might hold a clue to what I have done wrong... the actual reading of the config file that it uses works fine for the time being, something is wrong with the connection part... it is designed on a unix system and I am unsure if it will work on a win32 system or any other. Please help me... I'm a little stuck for ideas:

Code:
#!/usr/bin/perl -w



# BattleServ v0.0.1ALPHA

# Designed by Graham Lyon

# (c) Graham Lyon 2005


use strict;
use File::Basename;
use POSIX;

use POE;
use POE::Component::IRC;


# declare global config stuff here so they don't fall out of scope later on

my %config;


# find where we are located, read the config for the first time and sepperate from the terminal
$config{'scriptdir'} = &finddir;
if (!&config_rehash) { die "FATAL: Failed initial read of config\n"; }
push @INC, "$config{'scriptdir'}/$config{'moduledir'}";
#require Proc::Daemon;
#&Proc::Daemon::Init;

# write out the PID file
open(PIDFILE, ">$config{'scriptdir'}/$config{'pidfile'}");
printf PIDFILE "%d\n", getpid();
close(PIDFILE);


my $battleserv = POE::Component::IRC->spawn();

POE::Session->new(	_start			=> \&_start,

			_stop			=> \&_stop,

			_default		=> \&_default,		# this will fill up your logfile faster then you can say knife...
									# set daemon to 0 in your config file so that everthing prints to the terminal


			irc_connect		=> \&irc_connect,	# event to trigger a connection to IRC

			irc_disconnect		=> \&irc_disconnect,	# event to GRACEFULLY stop the connection to IRC

			irc_socketerr		=> \&irc_socketerr,	# deal with IRC socket errors

			irc_error		=> \&irc_error,		# error with the IRC protocol

			irc_connected		=> \&irc_connected,	# triggered when you first connect

			irc_disconnected	=> \&irc_disconnected,	# triggered when disconnected



			irc_001			=> \&irc_001,


			irc_msg			=> \&irc_msg,


			irc_ctcp_version	=> \&irc_ctcp_version,

			irc_ctcp_finger		=> \&irc_ctcp_finger,

			);

# start everything

$poe_kernel->run();

exit 0;

#################################################
# Below here is only subroutines... the script
# it's self terminates at the "exit 0;" line
# above.
#################################################



#################################################

######### Starting and stopping...

#################################################

sub _start

{

	my $kernel = $_[KERNEL];

	$battleserv->yield(register=> "all");
	&log_error("Battleserv started");
	&dumpconfig;

	$kernel->yield("irc_connect");

}



sub _stop

{

	&log_error("Received stop signal, unregistering events...");

	$battleserv->yield(unregister=> "all");

	$battleserv->yield("shutdown");
	&log_error("Battleserv stopped");

}

#################################################

######### Config subroutines

#################################################
sub config_rehash

{

	my $config = @_[0] || "$config{'scriptdir'}/battleserv.conf";
	&log_error("Loading config from \"$config\"...");

	my $seen_warning;

	my $seen_error;



	# read the config file into an array and then close it

	if (!open(CONFIG, $config))

	{

		&log_error("ERROR: Could not open config file, config not loaded");

		&log_error("Failed to load config, please check the above for possible errors");

		return 0;

	}

	my @config=<CONFIG>;

	close(CONFIG);

	chomp(@config);



	# first read through will check the config file by passing it into the hash "%check_config"

	# and then seeing if required values are there aswell as checking sanity of other values

	my %check_config;

	$check_config{'scriptdir'} = $config{'scriptdir'}; # place the scriptdir back into the config
	my @check_channels;

	foreach (@config)

	{
		if ((/^\#/) || !(/=/)) { next; }

		(my $config, my $value) = split(/=/, $_, 2);

		if ($config eq "channel")

		{
			my $dontadd = 0;
			foreach (@{ $check_config{'channels'} })
			{
				if ("$_" == "$value")
				{
					$dontadd = 1;
					$seen_warning = 1;
					&log_error("WARNING: Repeat channel in config ($value), omitting...");
					next;
				}
			}

			if (!$dontadd) { push(@{ $check_config{'channels'} }, "$value"); }

		}

		else

		{

			if ($check_config{$config}) {

				$seen_warning = 1;

				&log_error("WARNING: repeat value of $config in config file (current value: $check_config{$config}), replacing with newest value ($value)");

			}

			$check_config{$config} = "$value";

		}

	}

	my %critical_config = (	"moduledir", "modules",
				"errorlog", "error.log",
				"logfile", "battleserv.log",
				"pidfile", "battleserv.pid",
				"botnick", "BattleServ",

				"botident", "BattleServ",

				"botname", "Battle Service Bot",

				"server", "",

				"port", "6667",
				"daemon", 0,
				);

	foreach (keys(%critical_config))
	{
		if (!$check_config{$_})
		{
			if ($critical_config{$_} eq "")
			{
				$seen_error = 1;
				&log_error("ERROR: Missing config option \"$_\"");
			}
			else
			{
				$check_config{$_} = $critical_config{$_};
			}
		}
	}

	###################################################################################
	###################################################################################
	## WAAAAAAY more sanitising needs to be done here....
	###################################################################################
	###################################################################################



	if ($seen_warning) { &log_error("Warnings were flagged in the config, while this still has produced a working config there is the possibility that the config will not perform the way you expect. If the bot is not operating the way you expect then check the above for possible errors in your config."); }

	if ($seen_error) { &log_error("Failed to load config, please check the above for possible errors"); return 0; }

	# clean the global array out and copy the sane array into the clean global array
	undef %config;

	%config = %check_config;

	&log_error("Config loaded successfully");
	return 1;

}

sub dumpconfig
{
	&log_error("Config dump:");
	while (my @config = each(%config))
	{
		&log_error("$config[0] => $config[1]");
	}
	&log_error("Channels array:");
	foreach (@{ $config{'channels'} })
	{
		&log_error("$_");
	}
}

sub finddir
{
	if (dirname($0) !~ /^./) { return dirname($0); }
	elsif (`pwd`)
	{
		my $dir = `pwd`;
		chomp($dir);
		my $dir2 = $0;
		$dir2 =~ s/^.//;
		$dir = $dir . $dir2;
		return dirname($dir);
	}
	else { return 0; }
}

#################################################
######### Logging
#################################################
sub log_error
{
	if((!"$config{'errorlog'}") || (!$config{'daemon'}))
	{
		# config still hasn't loaded, we are still attached to the terminal
		print "$_[0]\n";
		return 1;
	}
	if(!open(ERROR, ">>$config{'scriptdir'}/$config{'errorlog'}"))
	{
		return 0;
	}
	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
	printf ERROR "%4d-%02d-%02d %02d:%02d:%02d",$year+1900,$mon+1,$mday,$hour,$min,$sec;
	print ERROR " => $_[0]\n";
	close(ERROR);
	return 1;
}

#################################################

######### Debug stuff...

#################################################

sub _default

{

	my ( $event, $args ) = @_[ ARG0 .. $#_ ];

	print "unhandled $event";



	my $arg_number = 0;

	foreach (@$args)

	{

		print "  ARG$arg_number = ";

		if ( ref($_) eq 'ARRAY' )

		{

			print "$_ = [", join ( ", ", @$_ ), "]\n";

		}

		else

		{

            	print "'$_'\n";

		}

		$arg_number++;

	}

	return 0;    # Don't handle signals.

}

#################################################

######### Connection related sub routines

#################################################

sub irc_connect

{

	&log_error("Connecting to $config{'server'} on port $config{'port'}...");

	$battleserv->yield(connect=> {

					nick     => $config{'botnick'},

					username => $config{'botident'},

					ircname  => $config{'botname'},

					server   => $config{'server'},

					port     => $config{'port'},

					}

					);

}



sub irc_connected

{

	&log_error("Connection to $config{'server'} on port $config{'port'} established...");

}



sub irc_disconnected

{

	&log_error("Disconnected from $_[ARG0]");

}



sub irc_socketerr

{

	&log_error("Connection to $config{'server'} on port $config{'port'} failed...");
	&log_error("reason: $_[ARG0]");

}



sub irc_error

{

	&log_error("$_[ARG0]");

}



#################################################

######### RAW 001-099

#################################################

sub irc_001world

{

	$battleserv->yield(join=>"$_") for (@{ $config{'channels'} })

}



#################################################

######### Named RAW events

#################################################

sub irc_msg

{

	if ($_[ARG2] =~ /^!quit/i)

	{

		&log_error("Recieved !quit command");

		my $nick = (split /!/, $_[ARG0])[0];

		$battleserv->yield(quit=>'yarr');

	}

}



#################################################

######### CTCP events

#################################################

sub irc_ctcp_version

{

	my $nick = (split /!/, $_[ARG0])[0];

	$battleserv->yield(ctcpreply=>$nick=>"VERSION BattleServ v0.1ALPHA designed by eviltwin");

}



sub irc_ctcp_finger

{

	my $nick = (split /!/, $_[ARG0])[0];

	$battleserv->yield(ctcpreply=>$nick=>"FINGER Battle Service bot - Admin: Graham Lyon AKA eviltwin");

}

and the config file "battleserv.conf" looks like this:
Code:
#this is a comment ;)
moduledir=modules
botnick=BattleServ

botident=BattleServ

botname=Battle Service Bot

server=[a server here]

port=6667

channel=#world

You might want to paste the code into a syntax highlighting text editor for ease of reading... sorry for the lack of comments in it...

Thanks for your time... please help me :-(
 
got a line number?

Spend an hour a week on CPAN, helps cure all known programming ailments ;-)
 
Nope, that's why I am unable to solve it myself and couldn't give a smaller snippit of the code, if you go to the connect event and specify static values rather than the ones it fetches from the config hash then it still fails, however a less complicated script does not... I sense a major rewrite coming which will not be nice for me... if you run it then it will dump the config for you to show that it has infact read the file... I just don't know why it won't work :/

The line calling the connect method is line 68 and the connect subroutine it's self is on line 256... I have no idea of the source of the bug...
 
Something I just noticed, all lines with a variable from the config in them are not printed properly, so I changed ALL the config variables out of the irc_connect subroutine and it now works perfectly. This worries me now slightly because it means that it IS the fault of the config hash... but when the config is shown to us at the beginning it looks perfect.... anyone help me on this? The reading of the config is called at line 18 and the subroutine rests on line 82. It just happens to be the biggest and most complicated subroutine in the whole thing... help [sadeyes]
 
Ok... now I feel like a complete idiot... truly, I do

Sorry to anyone I have sent on a wild goose chase trying to figure out what was wrong with this... the config file was originally written on a windows computer, thus it had CRLFs at the end of the lines, and the linux machine was reading it badly and anything that came from the config file wasn't chomp()ed properly and so not working for one reason or another. I have now fixed it and I am sorry for troubling people with this...

bye
 
Glad to see I'm not the only one who's made that mistake...
 
You may have another issue, you're using use strict which is good practice, but your config hash is declared at least twice, once global, and once in rehash_config -> this can cause problems unless you're aware of it

Well done on getting the other one ;-)

Spend an hour a week on CPAN, helps cure all known programming ailments ;-)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top