html/hlbot.pl


   1 ###########################################################################
   2 #
   3 # CopyLeft Veli Mankinen 2002
   4 # HL-log/rcon bot irssi script.
   5 #
   6 #####################
   7 #
   8 # USAGE:
   9 #
  10 # 1. copy the script to ~/.irssi/scripts/
  11 # 2. Edit the variables below.
  12 # 3. load the script: /script load hlbot
  13 # 4. Join to the channel you want this script to work on.
  14 # 5. Make sure all the users have ops in the channel (security reasons)
  15 # 6. say in channel: .rcon logadress <ip> <port>
  16 #    Where ip is the ip of the machine where this script is running and
  17 #    the port is the $listen_port you have set below
  18 # 7. say in channel: .rcon log on
  19 # 
  20 # The script should now start flooding the channel about things hapening in
  21 # the channel. Ofcourse you can and I think you should add those
  22 # log -commands to your hl server.cfg.
  23 #
  24 # You can turn the flooding of by saying: ".log off" and turn it back on
  25 # with: ".log off". ".status" tells you whether the log is on or off.
  26 # Please note that the logfile is allways on. If you don't want to gather
  27 # the log in a file then you should put "/dev/null" to the $logfile below.
  28 # 
  29 #
  30 # NOTE: There probably are few stupid things in this script and that is
  31 #       just because I don't have a clue about making irssi script.
  32 #
  33 ##
  34 
  35 
  36 use Socket;
  37 use Sys::Hostname;
  38 use IO::Handle;
  39 
  40 use Irssi;
  41 use Irssi::Irc;
  42 use vars qw($VERSION %IRSSI);
  43 
  44 ##########################[ USER VARIABLES ]########################### 
  45 
  46 my $listen_port  = 10001;              # Port to listen to
  47 my $logfile      = "logi";             # Logfile
  48 
  49 my $hlserver     = "123.123.123.123";  # Ip of your half life server
  50 my $hlport       = "28000";            # Port of your half life server
  51 my $rcon_pass    = "password";         # Rcon password of your half life server
  52 
  53 my $channel      = "#mychan";          # Channel where you want this to work
  54 
  55 #######################################################################
  56 ##############[ YOU DON'T NEED TO TOUCH BELOW THIS LINE ]##############
  57 #######################################################################
  58 
  59 $VERSION = "1.0";
  60 %IRSSI = (
  61 	authors => "Veli Mankinen",
  62 	contact => "veli\@piipiip.net",
  63 	name => "HL-log/rcon -bot",
  64 	description => "Floods the channel about things that are hapening in your hl -server. Also enables you to send rcon commands to the server from channel.",
  65 	license => "GPLv2",
  66 	url => "http://piipiip.net/",
  67 );
  68 
  69 #####################
  70 
  71 my $serv_iaddr = inet_aton($hlserver)    || die "unknown host: $hlserver\n";
  72 my $serv_paddr = sockaddr_in($hlport, $serv_iaddr); 
  73 my $challenge = "";
  74 my $rcon_msg = "";
  75 my $log_on = 1;
  76 
  77 #####################
  78 
  79 sub run_bot {	
  80 	my $server = Irssi::active_server();
  81 	
  82 	($hispaddr = recv(S, $msg, 1000, 0)) or print "$!\n";
  83 	($port, $hisiaddr) = sockaddr_in($hispaddr);
  84 	$host = inet_ntoa($hisiaddr); 
  85 
  86 	$msg =~ s/\n.$//s;
  87 	$msg =~ s/\n..$//s;
  88 	
  89 	print LOG "$host : $msg\n";
  90 
  91 	# Received logline
  92 	if ($msg =~ s/^ÿÿÿÿlog L \d\d\/\d\d\/\d{4} - \d\d:\d\d:\d\d: //) {
  93 		# We don't want to see these
  94 		if ($log_on eq 0 ||
  95 			$msg =~ /^Server cvar/ || 
  96 			$msg =~ /^\[META\]/ ||
  97 			$msg =~ /^Log file/ || 
  98 			$msg =~ /^\[ADMIN\]/) 
  99 			{ return; }
 100 		
 101 		# FORMAT THE LINE
 102 		# Don't show the rcon password.
 103 		$msg =~ s/^(Rcon: "rcon \d* )[^ ]*( .*)/$1*****$2/;
 104 		
 105 		# Print the logline
 106 		if ($msg =~ /^"/) {
 107 			$server->command("/action $channel $msg");
 108 		} else {
 109 			$server->send_raw("PRIVMSG $channel :*log* $msg");
 110 		}
 111 	} 
 112 
 113 	# Received challenge rcon reply..
 114 	elsif ($msg =~ /^ÿÿÿÿchallenge rcon (\d+)$/ && $rcon_msg) {
 115 		$challenge = $1;
 116 		$data = "ÿÿÿÿrcon $challenge $rcon_pass $rcon_msg";
 117 		defined(send(S, $data, 0, $serv_paddr)) or
 118 			$server->command("/notice $channel Error sending rcon: $!");
 119 	}
 120 
 121 	# Received rcon reply
 122 	elsif ($msg =~ s/ÿÿÿÿl//) {
 123 		# Some rcon replies have this annoying log entry in the beginning.
 124 		$msg =~ s/L \d\d\/\d\d\/\d{4} - \d\d:\d\d:\d\d: //g;
 125 		
 126 		# FORMAT THE LINE
 127 		
 128 		# Multiline rcon responses
 129 		if ($msg =~ /\n/s) {
 130 			@rows = split /\n/, $msg;
 131 			foreach $row (@rows) {
 132 				# We don't want to see these
 133 				if ($row =~ /^[\t \n]*$/ ||
 134 					$row =~ /^[ADMIN] Load/ ||
 135 					$row =~ /^[ADMIN] WARNING/ ||
 136 					$row =~ /^[ADMIN] Plugins loaded/) 
 137 					{ next; }
 138 
 139 				$server->command("/notice $channel $row");
 140 			}
 141 			
 142 		# Single line rcon responses
 143 		} else {
 144 			$server->command("/notice $channel $msg");
 145 		}
 146 	}
 147 	
 148 }
 149 
 150 ############################
 151 
 152 sub msg_command {
 153 	my ($server, $data, $nick, $mask, $target) = @_;
 154 	
 155 	# Is this the right channel?
 156 	unless ($target =~ /$channel/i) { return; }
 157 	
 158 	# Does the user have ops?
 159 	my $CHAN = $server->channel_find($channel);
 160 	my $NICK = $CHAN->nick_find($nick);
 161 	if (! $NICK->{op}) { return; }
 162 		
 163 	# Rcon command.
 164 	if ($data =~ /^\.rcon (.+)/) {
 165 		$rcon_msg = $1;
 166 		
 167         defined(send(S, "ÿÿÿÿchallenge rcon", 0, $serv_paddr)) or
 168 			$server->command("/notice $channel Error asking challenge: $!");
 169 	} 
 170 
 171 	# log on
 172 	elsif ($data =~ /^\.log on$/) {
 173 		$log_on = 1;
 174 		$server->command("/notice $channel Logging now ON");
 175 	}
 176 	
 177 	# log off
 178 	elsif ($data =~ /^\.log off$/) {
 179 		$log_on = 0;
 180 		$server->command("/notice $channel Logging now OFF");
 181 	}
 182 	
 183 	# help
 184 	elsif ($data =~ /^\.help$/) {
 185 		$server->command("/notice $channel Commands: .rcon <rcon command>, " .
 186 			".log <on/off>, .status");
 187 	}
 188 
 189 	# status
 190 	elsif ($data =~ /^\.status$/) {
 191 		my $log_status = "";
 192 		if ($log_on eq 1) { $log_status = "on"; }
 193 		else { $log_status = "off"; }
 194 		$server->command("/notice $channel Log: $log_status");
 195 	}
 196 	
 197 }
 198 
 199 #########[ MAIN ]###########
 200 
 201 # Open the logfile.
 202 open LOG, ">>$logfile" or die "Cannot open logfile!\n";
 203 LOG->autoflush(1);
 204 
 205 # Start listening the socket for udp messages.
 206 my $iaddr = gethostbyname(hostname());
 207 my $proto = getprotobyname('udp');
 208 my $paddr = sockaddr_in($listen_port, $iaddr);
 209 socket(S, PF_INET, SOCK_DGRAM, $proto)   || die "socket: $!\n";
 210 bind(S, $paddr)                          || die "bind: $!\n";
 211 $| = 1;
 212 
 213 # Set input and signals etc. irssi related stuff.
 214 Irssi::input_add(fileno(S), INPUT_READ, "run_bot", "");
 215 Irssi::signal_add_last('message public', 'msg_command');
 216 
 217