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 35use strict; 36use Socket; 37use Sys::Hostname; 38use IO::Handle; 39 40use Irssi; 41use Irssi::Irc; 42use vars qw($VERSION %IRSSI); 43 44##########################[ USER VARIABLES ]########################### 45 46my $listen_port = 10001; # Port to listen to 47my $logfile = "logi"; # Logfile 48 49my $hlserver = "123.123.123.123"; # Ip of your half life server 50my $hlport = "28000"; # Port of your half life server 51my $rcon_pass = "password"; # Rcon password of your half life server 52 53my $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 71my $serv_iaddr = inet_aton($hlserver) || die "unknown host: $hlserver\n"; 72my $serv_paddr = sockaddr_in($hlport, $serv_iaddr); 73my $challenge = ""; 74my $rcon_msg = ""; 75my $log_on = 1; 76 77##################### 78 79sub run_bot { 80 my $server = Irssi::active_server(); 81 my $msg; 82 83 (my $hispaddr = recv(S, $msg, 1000, 0)) or print "$!\n"; 84 my ($port, $hisiaddr) = sockaddr_in($hispaddr); 85 my $host = inet_ntoa($hisiaddr); 86 87 $msg =~ s/\n.$//s; 88 $msg =~ s/\n..$//s; 89 90 print LOG "$host : $msg\n"; 91 92 # Received logline 93 if ($msg =~ s/^����log L \d\d\/\d\d\/\d{4} - \d\d:\d\d:\d\d: //) { 94 # We don't want to see these 95 if ($log_on eq 0 || 96 $msg =~ /^Server cvar/ || 97 $msg =~ /^\[META\]/ || 98 $msg =~ /^Log file/ || 99 $msg =~ /^\[ADMIN\]/) 100 { return; } 101 102 # FORMAT THE LINE 103 # Don't show the rcon password. 104 $msg =~ s/^(Rcon: "rcon \d* )[^ ]*( .*)/$1*****$2/; 105 106 # Print the logline 107 if ($msg =~ /^"/) { 108 $server->command("/action $channel $msg"); 109 } else { 110 $server->send_raw("PRIVMSG $channel :*log* $msg"); 111 } 112 } 113 114 # Received challenge rcon reply.. 115 elsif ($msg =~ /^����challenge rcon (\d+)$/ && $rcon_msg) { 116 $challenge = $1; 117 my $data = "����rcon $challenge $rcon_pass $rcon_msg"; 118 defined(send(S, $data, 0, $serv_paddr)) or 119 $server->command("/notice $channel Error sending rcon: $!"); 120 } 121 122 # Received rcon reply 123 elsif ($msg =~ s/����l//) { 124 # Some rcon replies have this annoying log entry in the beginning. 125 $msg =~ s/L \d\d\/\d\d\/\d{4} - \d\d:\d\d:\d\d: //g; 126 127 # FORMAT THE LINE 128 129 # Multiline rcon responses 130 if ($msg =~ /\n/s) { 131 my @rows = split /\n/, $msg; 132 foreach my $row (@rows) { 133 # We don't want to see these 134 if ($row =~ /^[\t \n]*$/ || 135 $row =~ /^[ADMIN] Load/ || 136 $row =~ /^[ADMIN] WARNING/ || 137 $row =~ /^[ADMIN] Plugins loaded/) 138 { next; } 139 140 $server->command("/notice $channel $row"); 141 } 142 143 # Single line rcon responses 144 } else { 145 $server->command("/notice $channel $msg"); 146 } 147 } 148 149} 150 151############################ 152 153sub msg_command { 154 my ($server, $data, $nick, $mask, $target) = @_; 155 156 # Is this the right channel? 157 unless ($target =~ /$channel/i) { return; } 158 159 # Does the user have ops? 160 my $CHAN = $server->channel_find($channel); 161 my $NICK = $CHAN->nick_find($nick); 162 if (! $NICK->{op}) { return; } 163 164 # Rcon command. 165 if ($data =~ /^\.rcon (.+)/) { 166 $rcon_msg = $1; 167 168 defined(send(S, "����challenge rcon", 0, $serv_paddr)) or 169 $server->command("/notice $channel Error asking challenge: $!"); 170 } 171 172 # log on 173 elsif ($data =~ /^\.log on$/) { 174 $log_on = 1; 175 $server->command("/notice $channel Logging now ON"); 176 } 177 178 # log off 179 elsif ($data =~ /^\.log off$/) { 180 $log_on = 0; 181 $server->command("/notice $channel Logging now OFF"); 182 } 183 184 # help 185 elsif ($data =~ /^\.help$/) { 186 $server->command("/notice $channel Commands: .rcon <rcon command>, " . 187 ".log <on/off>, .status"); 188 } 189 190 # status 191 elsif ($data =~ /^\.status$/) { 192 my $log_status = ""; 193 if ($log_on eq 1) { $log_status = "on"; } 194 else { $log_status = "off"; } 195 $server->command("/notice $channel Log: $log_status"); 196 } 197 198} 199 200#########[ MAIN ]########### 201 202# Open the logfile. 203open LOG, ">>", $logfile or die "Cannot open logfile!\n"; 204LOG->autoflush(1); 205 206# Start listening the socket for udp messages. 207my $iaddr = gethostbyname(hostname()); 208my $proto = getprotobyname('udp'); 209my $paddr = sockaddr_in($listen_port, $iaddr); 210socket(S, PF_INET, SOCK_DGRAM, $proto) || die "socket: $!\n"; 211bind(S, $paddr) || die "bind: $!\n"; 212 213# Set input and signals etc. irssi related stuff. 214Irssi::input_add(fileno(S), INPUT_READ, "run_bot", ""); 215Irssi::signal_add_last('message public', 'msg_command'); 216 217 218