summaryrefslogtreecommitdiffstats
path: root/scripts/hlbot.pl
blob: 1d8cfd69b16cb4d84eede58ab467ca120dd26fc1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
###########################################################################
#
# CopyLeft Veli Mankinen 2002
# HL-log/rcon bot irssi script.
#
#####################
#
# USAGE:
#
# 1. copy the script to ~/.irssi/scripts/
# 2. Edit the variables below.
# 3. load the script: /script load hlbot
# 4. Join to the channel you want this script to work on.
# 5. Make sure all the users have ops in the channel (security reasons)
# 6. say in channel: .rcon logadress <ip> <port>
#    Where ip is the ip of the machine where this script is running and
#    the port is the $listen_port you have set below
# 7. say in channel: .rcon log on
# 
# The script should now start flooding the channel about things hapening in
# the channel. Ofcourse you can and I think you should add those
# log -commands to your hl server.cfg.
#
# You can turn the flooding of by saying: ".log off" and turn it back on
# with: ".log off". ".status" tells you whether the log is on or off.
# Please note that the logfile is allways on. If you don't want to gather
# the log in a file then you should put "/dev/null" to the $logfile below.
# 
#
# NOTE: There probably are few stupid things in this script and that is
#       just because I don't have a clue about making irssi script.
#
##

use strict;
use Socket;
use Sys::Hostname;
use IO::Handle;

use Irssi;
use Irssi::Irc;
use vars qw($VERSION %IRSSI);

##########################[ USER VARIABLES ]########################### 

my $listen_port  = 10001;              # Port to listen to
my $logfile      = "logi";             # Logfile

my $hlserver     = "123.123.123.123";  # Ip of your half life server
my $hlport       = "28000";            # Port of your half life server
my $rcon_pass    = "password";         # Rcon password of your half life server

my $channel      = "#mychan";          # Channel where you want this to work

#######################################################################
##############[ YOU DON'T NEED TO TOUCH BELOW THIS LINE ]##############
#######################################################################

$VERSION = "1.0";
%IRSSI = (
	authors => "Veli Mankinen",
	contact => "veli\@piipiip.net",
	name => "HL-log/rcon -bot",
	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.",
	license => "GPLv2",
	url => "http://piipiip.net/",
);

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

my $serv_iaddr = inet_aton($hlserver)    || die "unknown host: $hlserver\n";
my $serv_paddr = sockaddr_in($hlport, $serv_iaddr); 
my $challenge = "";
my $rcon_msg = "";
my $log_on = 1;

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

sub run_bot {	
	my $server = Irssi::active_server();
	my $msg;
	
	(my $hispaddr = recv(S, $msg, 1000, 0)) or print "$!\n";
	my ($port, $hisiaddr) = sockaddr_in($hispaddr);
	my $host = inet_ntoa($hisiaddr); 

	$msg =~ s/\n.$//s;
	$msg =~ s/\n..$//s;
	
	print LOG "$host : $msg\n";

	# Received logline
	if ($msg =~ s/^����log L \d\d\/\d\d\/\d{4} - \d\d:\d\d:\d\d: //) {
		# We don't want to see these
		if ($log_on eq 0 ||
			$msg =~ /^Server cvar/ || 
			$msg =~ /^\[META\]/ ||
			$msg =~ /^Log file/ || 
			$msg =~ /^\[ADMIN\]/) 
			{ return; }
		
		# FORMAT THE LINE
		# Don't show the rcon password.
		$msg =~ s/^(Rcon: "rcon \d* )[^ ]*( .*)/$1*****$2/;
		
		# Print the logline
		if ($msg =~ /^"/) {
			$server->command("/action $channel $msg");
		} else {
			$server->send_raw("PRIVMSG $channel :*log* $msg");
		}
	} 

	# Received challenge rcon reply..
	elsif ($msg =~ /^����challenge rcon (\d+)$/ && $rcon_msg) {
		$challenge = $1;
		my $data = "����rcon $challenge $rcon_pass $rcon_msg";
		defined(send(S, $data, 0, $serv_paddr)) or
			$server->command("/notice $channel Error sending rcon: $!");
	}

	# Received rcon reply
	elsif ($msg =~ s/����l//) {
		# Some rcon replies have this annoying log entry in the beginning.
		$msg =~ s/L \d\d\/\d\d\/\d{4} - \d\d:\d\d:\d\d: //g;
		
		# FORMAT THE LINE
		
		# Multiline rcon responses
		if ($msg =~ /\n/s) {
			my @rows = split /\n/, $msg;
			foreach my $row (@rows) {
				# We don't want to see these
				if ($row =~ /^[\t \n]*$/ ||
					$row =~ /^[ADMIN] Load/ ||
					$row =~ /^[ADMIN] WARNING/ ||
					$row =~ /^[ADMIN] Plugins loaded/) 
					{ next; }

				$server->command("/notice $channel $row");
			}
			
		# Single line rcon responses
		} else {
			$server->command("/notice $channel $msg");
		}
	}
	
}

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

sub msg_command {
	my ($server, $data, $nick, $mask, $target) = @_;
	
	# Is this the right channel?
	unless ($target =~ /$channel/i) { return; }
	
	# Does the user have ops?
	my $CHAN = $server->channel_find($channel);
	my $NICK = $CHAN->nick_find($nick);
	if (! $NICK->{op}) { return; }
		
	# Rcon command.
	if ($data =~ /^\.rcon (.+)/) {
		$rcon_msg = $1;
		
        defined(send(S, "����challenge rcon", 0, $serv_paddr)) or
			$server->command("/notice $channel Error asking challenge: $!");
	} 

	# log on
	elsif ($data =~ /^\.log on$/) {
		$log_on = 1;
		$server->command("/notice $channel Logging now ON");
	}
	
	# log off
	elsif ($data =~ /^\.log off$/) {
		$log_on = 0;
		$server->command("/notice $channel Logging now OFF");
	}
	
	# help
	elsif ($data =~ /^\.help$/) {
		$server->command("/notice $channel Commands: .rcon <rcon command>, " .
			".log <on/off>, .status");
	}

	# status
	elsif ($data =~ /^\.status$/) {
		my $log_status = "";
		if ($log_on eq 1) { $log_status = "on"; }
		else { $log_status = "off"; }
		$server->command("/notice $channel Log: $log_status");
	}
	
}

#########[ MAIN ]###########

# Open the logfile.
open LOG, ">>", $logfile or die "Cannot open logfile!\n";
LOG->autoflush(1);

# Start listening the socket for udp messages.
my $iaddr = gethostbyname(hostname());
my $proto = getprotobyname('udp');
my $paddr = sockaddr_in($listen_port, $iaddr);
socket(S, PF_INET, SOCK_DGRAM, $proto)   || die "socket: $!\n";
bind(S, $paddr)                          || die "bind: $!\n";

# Set input and signals etc. irssi related stuff.
Irssi::input_add(fileno(S), INPUT_READ, "run_bot", "");
Irssi::signal_add_last('message public', 'msg_command');