· 8 years ago · Jun 02, 2018, 01:48 AM
1#!/usr/bin/perl
2
3use warnings;
4use strict;
5
6################################################################################
7# #
8# operfilter.pl - xchat filter and oper communication script for UnrealdIRCd #
9# users. Helpop ChatOps GlobOps NaChat AdChat LocOps. #
10# #
11# Copyright (C) 2008 Sergio Luis <sergio at 0xffffff.org> #
12# Jeff Wooldridge <jefferoos at gmail.com> #
13# #
14# operfiler.pl is free software; you can redistribute it and/or modify #
15# it under the terms of the GNU General Public License as published by #
16# the Free Software Foundation; either version 2 of the License, or #
17# (at your option) any later version. #
18# #
19# operfilter.pl is distributed in the hope that it will be useful, #
20# but WITHOUT ANY WARRANTY; without even the implied warranty of #
21# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
22# GNU General Public License for more details. #
23# #
24# You should have received a copy of the GNU General Public License #
25# along with this program; if not, write to the Free Software #
26# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #
27# #
28################################################################################
29
30
31
32# Many credits goes to Sergio for the help and support.
33
34
35my $rTimer = 10000;
36my $debug = 1;
37my $debugTab = "-Debug";
38# registering the script withing xchat
39Xchat::register("IRCop Windows/Filter for Xchat", "0.3", "Script for IRCops or Helpers", \&unload);
40# hooking the notices received from the server
41my $server_notice_hook = Xchat::hook_print("Server Notice", \&server_notice_handler);
42
43# hooking any non-command
44Xchat::hook_command("", \&non_command_handler);
45Xchat::hook_command("me", \&non_command_handler);
46
47Xchat::hook_command("notinchan", \¬_in_chan);
48
49Xchat::hook_command("who", \&who_command_handler);
50
51Xchat::hook_print( "Users On Channel", \&users_on_channel );
52
53Xchat::hook_print("Part", \&eat_parts_from_clients);
54
55Xchat::hook_print("Change Nick",\&eat_quit_on_tab);
56Xchat::hook_print("Quit",\&eat_quit_on_tab);
57
58# Used to block annoying errors when fake rooms are created and used.
59Xchat::hook_server("401", \&block_raws);
60Xchat::hook_server("334", \&block_raws);
61
62# If you are a non-oper but recieve helpop messages change the %global_settings to
63# cb => \&helpop_who_handler and who => "#help"
64
65my %global_settings = (
66 helpop => {identifier => "HelpOp", tab => "-HelpOp", command => "helpop", who => "#help", cb => \&helpop_who_handler,},
67 chatops => {identifier => "ChatOps", tab => "-ChatOps", command => "chatops", who => "+m-m oO S", cb => \&std_who_handler,},
68 nachat => {identifier => "NetAdmin.Chat", tab => "-NAChat", command => "nachat", who => "+m-m N S", cb => \&std_who_handler,},
69 locops => {identifier => "LocOps", tab => "-LocOps", command => "locops", who => "+m-m o S", cb => \&std_who_handler,},
70 global => {identifier => "Global", tab => "-GlobOps", command => "globops", who => "+m o", cb => \&std_who_handler,},
71 adchat => {identifier => "AdminChat", tab => "-AdChat", command => "adchat", who => "+m-m aA S", cb => \&std_who_handler,},
72 clients => {identifier => "Client", tab => "-Clients", who => "+n \*", cb => \&std_who_handler,},
73 idle => {tab => "-NotInChan", who => "+i \*", cb => \&idle_who_handler,},
74);
75
76my $nicks_tab = "-NickChange";
77my $globals_tab = "-Global";
78my $services_tab = "-Services";
79
80
81# this routine deals with the notices received from the server. in our case, we are interested
82# in helpop/chatops notices
83sub server_notice_handler($) {
84 my ( $notice, $server )= @{$_[0]};
85
86 # Remote and local client connection notices
87 if ( $notice =~ s/^\*\*\* Notice -- (Client) (exiting|connecting)(?::|.*?): (.*?) // ) {
88 my $identifier = $1;
89 my $exit_connect = $2;
90 my $nick = $3;
91
92 # Gets hash info
93 my $settings = &get_settings_by_key("identifier", $identifier);
94 return Xchat::EAT_NONE if not defined($settings);
95
96 # Your current nickname on the specified server
97 my $mynick = Xchat::get_info("nick");
98
99 # when the tab on the server isnt found...
100 unless(Xchat::find_context($settings->{tab}, $server)) {
101
102 # Opens up a fake channel room and gives it some basic channel modes
103 Xchat::command("recv :$mynick!blah\@blah.net JOIN :$settings->{tab}");
104 Xchat::command("recv :$server 324 $mynick $settings->{tab} +CLIENTS");
105 Xchat::command("recv :$server 329 $mynick $settings->{tab} 0");
106
107 # Used to make the userlist of the channel
108 Xchat::command("timer 1 who $settings->{who}");
109 }
110
111 # Exiting clients
112 if ( $exit_connect eq "exiting" ) {
113 # local and remote notices are not the same so this was done.
114 my ($nick_, $host) = split( /!/, $nick, 2);
115 &on_client_tab( $server, $settings->{tab}, "\cC2\cB[E]\cO", "\cB$nick_\cO $host $notice" ) if defined($host);
116 &on_client_tab( $server, $settings->{tab}, "\cC2\cB[E]\cO", "\cB$nick_\cO $notice" ) if not defined($host);
117
118 # When a client exits the server, it removes the user from -Clients userlist.
119 Xchat::command("recv :$nick_\!meow\@blah.com PART $settings->{tab}");
120 }
121 # Connecting clients
122 else {
123 &on_client_tab( $server, $settings->{tab}, "\cC3\cB[C]\cO", "\cB$nick\cO $notice" );
124
125 # When a new person connects, adds them to the userlist
126 Xchat::command("recv :$server 353 $mynick = $settings->{tab} :$mynick $nick" );
127 }
128 }
129
130 # prints events from services *** Global -- from NickServ: blah
131 elsif ( $notice =~ s/^\*\*\* Global \-\- from (\w+Serv|.*?\.(net|org|com)): // ) {
132 my $nickname = $1;
133 &on_query_new_tab_print( $server, $services_tab, $nickname, $notice );
134 }
135
136 # Captures numerous forms of Oper communication through Server Notices (Unreal IRCd)
137 elsif ($notice =~ /^\*\*\* (HelpOp|ChatOps|LocOps|Global|NetAdmin.Chat|AdminChat) \-\- from (.*?)(?: \(HelpOp\):|:)\s(.*)$/) {
138 my $identifier = $1;
139 my $nick = $2;
140 my $text = $3;
141
142 # Gets settings depending on what kind of server notice it was.
143 my $settings = &get_settings_by_key("identifier", $identifier);
144
145 # End of routine if the tab settings were not found.
146 return Xchat::EAT_NONE if not defined($settings);
147
148 # Your current nick on that server.
149 my $mynick = Xchat::get_info("nick");
150
151 # creating the tab and some chan modes in case tab does not yet exist
152 unless(Xchat::find_context($settings->{tab}, $server)) {
153 Xchat::command("recv :$mynick!blah\@blah.net JOIN :$settings->{tab}");
154 Xchat::command("recv :$server 324 $mynick $settings->{tab} +RAWR");
155 Xchat::command("recv :$server 329 $mynick $settings->{tab} 0");
156 #Xchat::command("timer 1 who $settings->{who}");
157
158 # milliseconds
159 #Xchat::hook_timer( $rTimer,
160 # sub {
161 # unless(Xchat::find_context($settings->{tab}, $server)) {
162 # Xchat::print("$settings->{tab} $server unless loop");
163 # return Xchat::REMOVE;
164 # }
165 # Xchat::print("timer 1 who $settings->{who}", $debugTab, $server);
166 # return Xchat::KEEP;
167 # }
168 #);
169 }
170
171 # Tells xchat where you want the channel message to be printed.
172 Xchat::set_context($settings->{tab}, $server);
173
174 # The elsifs decide which type of Text Event to be printed.
175 if ( $nick eq $mynick && $text =~ s/^me\s// ) {
176 Xchat::emit_print( "Your Action", $nick, $text );
177 } elsif ( $text =~ s/^me\s// && $text !~ /$mynick/i ) {
178 Xchat::emit_print( "Channel Action", $nick, $text );
179 } elsif ( $text =~ s/^me\s// && $text =~ /$mynick/i ) {
180 Xchat::emit_print( "Channel Action Hilight", $nick, $text );
181 } elsif ( $nick eq $mynick ) {
182 Xchat::emit_print( "Your Message", $nick, $text );
183 } elsif ( $text !~ /$mynick/i ) {
184 Xchat::emit_print( "Channel Message", $nick, $text );
185 } elsif ( $text =~ /$mynick/i ) {
186 Xchat::emit_print( "Channel Msg Hilight", $nick, $text );
187 }
188 }
189
190 # Nick changes and forced nick changes etc...
191 elsif ($notice =~ /^\*\*\* Notice \-\- (.*?) \((.*?)\) has (?:changed his\/her nickname|been forced to change his\/her nickname) to\s(.*)/) {
192 my $nickname = $1;
193 my $hostaddress = $2;
194 my $nickchange = $3;
195
196 # Used to update the -Clients Userlist if a nick is changed.
197 Xchat::command("recv :$nickname!$hostaddress NICK :$nickchange");
198
199 &on_query_new_tab_print( $server, $nicks_tab, $nickname, "is now \cB$nickchange\cO $hostaddress" );
200 }
201
202 #catches epiring network bans *** Expiring G:Line hostmask blah time or w/e
203 elsif ( $notice =~ s/^\*\*\* (Expiring) (Global Z:Line|Shun|G:Line) // ) {
204 my $nickname = $1;
205 my $line = $2;
206 &on_query_new_tab_print( $server, $globals_tab, $nickname, "\cB$line\cO $notice" );
207 }
208
209 elsif ($notice =~ s/^\*\*\* (OperOverride|Flood) \-\- // ) {
210 my $nickname = $1;
211 &on_query_new_tab_print( $server, $globals_tab, $nickname, $notice);
212 }
213
214 #catches spamfilter event... [Spamfilter] rest of stuff...
215 elsif ($notice =~ /\[Spamfilter\] (.*?)$/ ) {
216 my $line = $1;
217 &on_query_new_tab_print( $server, $globals_tab, "\cBSPAM\cO", $line );
218 }
219
220 elsif ( $notice =~ s/^\*\*\* (Spamfilter) // ) {
221 my $nickname = $1;
222 &on_query_new_tab_print( $server, $globals_tab, $nickname, $notice );
223 }
224
225 # *** G:Line has been added for hostmask reason blah <-- server bans
226 elsif ( $notice =~ s/^\*\*\* (.*?) added for // ) {
227 my $bantype = $1;
228 &on_query_new_tab_print( $server, $globals_tab, "Added", "\cB$bantype\cO for $notice" );
229 }
230
231 elsif ( $notice =~ /^Stats \'.*?\' requested by/ ) {
232 &on_query_new_tab_print( $server, $globals_tab, "Stats", $notice );
233 }
234
235 # When someone does a /whois on you
236 elsif ( $notice =~ /^\*\*\* (.*?) \((.*?)\@(.*?)\) did a \/whois on you\./ ) {
237 my $nick = $1;
238 my $username = $2;
239 my $ip = $3;
240 my $random = &random_whois_msg();
241 Xchat::command("notice $nick $nick: $random you /whois'd me your address is $ip")if ($username !~ /java/i );
242 }
243
244 # When someone opers up.
245 elsif ( $notice =~ /\] is now .*? \((?:O|N|A|a)\)$/ ) {
246 return Xchat::EAT_XCHAT;
247 }
248
249 # TS Control
250 elsif ( $notice =~ s/^\*\*\* Notice -- (TS Control) - //) {
251 my $nickname = $1;
252 &on_query_new_tab_print( $server, $services_tab, $nickname, $notice );
253 }
254
255 # When an unknown oper attempts to oper up or something.
256 elsif ($notice =~ /^Failed OPER attempt by (.*?) \(.*?(\@.*?)\) \[unknown oper\]$/) {
257 my $nickname = $1;
258 my $ip = $2;
259 my $mynick = Xchat::get_info("nick");
260 Xchat::command("notice $nickname $nickname: Stop Attempting to OPER UP or you will recieve consequences. type /msg $mynick SORRY if this was accidental.");
261 }
262
263 # Regex explains it all
264 elsif ( $notice =~ s/^(Forbidding|Failed) // ) {
265 my $nickname = $1;
266 &on_query_new_tab_print( $server, $globals_tab, $nickname, $notice );
267 }
268
269 elsif ( $notice =~ /^(.*?) (?:Link|Possible) / ) {
270 my $nickname = $1;
271 &on_query_new_tab_print( $server, $services_tab, $nickname, $notice );
272 }
273
274 # If there are any other Services Server notices or soemthing forgotten
275 elsif ( $notice =~ s/^(\w+Serv) // ) {
276 my $nickname = $1;
277 &on_query_new_tab_print( $server, $services_tab, $nickname, $notice );
278 }
279
280 #elsif ($notice =~ /regexhere/ ) {
281 # ...
282 #}
283
284 else {
285 return Xchat::EAT_NONE;
286 }
287 return Xchat::EAT_XCHAT;
288}
289
290# Basically made so I didnt have to put that into every single elsif statement
291sub on_query_new_tab_print {
292 # assigns data directly from serv_notice i.e. &on_query_new_tab_print(DATA);
293 my ( $server, $tab, $nick, $text ) = @_;
294 unless (Xchat::find_context( $tab, $server )) {
295
296 # Command variable "-nofocus" works only on 2.6.6 and up versions of xchat I believe,
297 # remove if you get a -nofocus error
298 Xchat::command( "query -nofocus " . $tab );
299 }
300 Xchat::set_context( $tab, $server );
301 Xchat::emit_print("Channel Message", $nick, $text);
302}
303
304sub on_client_tab {
305 # assigns data directly from serv_notice i.e. &on_query_new_tab_print(DATA);
306 my ( $server, $tab, $nick, $text ) = @_;
307 Xchat::set_context( $tab, $server );
308 Xchat::emit_print("Channel Message", $nick, $text);
309}
310
311# blocks some annoying servernotices after creation of fake channels
312sub block_raws {
313 return Xchat::EAT_XCHAT;
314}
315
316# this routine deals with any non command. here we are interested in things typed inside the helper/chatops tab.
317sub non_command_handler($$) {
318 # getting the text from the 2nd argument of this routine
319 my $text = shift(@{$_[1]});
320 my $channel = Xchat::get_info("channel");
321 my $settings = &get_settings_by_key("tab", $channel);
322 return Xchat::EAT_NONE if not defined($settings);
323
324 # checking whether we are in the helper/chatops tab
325 if ( lc($channel) eq lc($settings->{tab}) ) {
326
327 # sending helpop command to the server
328 Xchat::command($settings->{command} . " :" . $text);
329 # prevents xchat from seeing this event
330 return Xchat::EAT_XCHAT;
331 }
332 return Xchat::EAT_NONE;
333}
334
335
336sub not_in_chan {
337 return Xchat::EAT_NONE if defined($_[0][1]);
338
339 my $server = Xchat::get_info('server');
340 my $mynick = Xchat::get_info('nick');
341
342 Xchat::command("recv :$mynick!blah\@blah.net JOIN :-NotInChan") unless Xchat::find_context("-NotInChan",$server);
343 Xchat::command("timer 1 who +i \*");
344 return Xchat::EAT_XCHAT;
345}
346
347
348# /Who command hooks for special rooms
349my $hook;
350my $unhook;
351
352# Used to assure correct tabing.
353my $what_tab;
354
355sub who_command_handler {
356 my $settings = &get_settings_by_key("who", $_[1][1]);
357 return Xchat::EAT_NONE if not defined($settings);
358 my $server = Xchat::get_info("server");
359
360 if ($_[1][1] eq $settings->{who}) {
361 $what_tab = $settings->{tab};
362 $hook = Xchat::hook_server("352", $settings->{cb});
363 }
364 return Xchat::EAT_NONE;
365}
366
367sub std_who_handler {
368 &make_userlist($_[0][0], $_[0][2], $_[0][7]);
369 return Xchat::EAT_XCHAT;
370}
371sub helpop_who_handler {
372 # Just checks channel prefixes of the specified room from the /who Helpop command
373 &make_userlist($_[0][0], $_[0][2], $_[0][7]) if ($_[0][8] =~ /\@|\%|\&/);
374 return Xchat::EAT_XCHAT;
375}
376
377sub idle_who_handler {
378 &make_userlist($_[0][0], $_[0][2], $_[0][7]) if ($_[0][3] !~ /^#/);
379 return Xchat::EAT_XCHAT;
380}
381
382sub make_userlist {
383 my ($server, $mynick, $nick) = @_;
384 # Adds name to userlist one by one, sadly not all at once...
385 Xchat::command("recv :$server 353 $mynick = $what_tab :$mynick $nick");
386 $unhook = Xchat::hook_server( "315", \&unhook );
387}
388
389# EATS some annoying text event on fake channels
390sub users_on_channel {
391 my $channel = $_[0][0];
392 my $settings = &get_settings_by_key("tab", $channel);
393 return Xchat::EAT_XCHAT if ( lc($channel) eq lc($settings->{tab}) );
394 return Xchat::EAT_NONE;
395}
396
397# Unhooks created hooks
398sub unhook {
399 Xchat::unhook($hook);
400 # Stops hook function of server code 315 aka End of /who list.
401 Xchat::unhook($unhook);
402 return Xchat::EAT_XCHAT;
403}
404
405# Stops printing text event "Part" in clients tab
406sub eat_parts_from_clients {
407 my $channel = $_[0][2];
408 return Xchat::EAT_XCHAT if ( $channel eq "-Clients");
409 return Xchat::EAT_NONE;
410}
411sub eat_quit_on_tab {
412 return Xchat::EAT_XCHAT if ("-Clients" eq Xchat::get_info("channel"));
413 # pass other events along
414 return Xchat::EAT_NONE;
415}
416
417#handles the global hashes
418sub get_settings_by_key($) {
419 my ($type, $item) = @_;
420 foreach my $key (keys %global_settings) {
421 if (defined($type) && defined($item) && (defined($global_settings{$key}->{$type}) && ( $global_settings{$key}->{$type} eq $item)) ) {
422 return $global_settings{$key};
423 }
424 }
425 return undef;
426}
427
428# Server notice toggle.
429sub unhook_server_notice {
430 if ( $_[1][1] eq "on" ) {
431 $server_notice_hook = Xchat::hook_print("Server Notice", \&server_notice_handler);
432 }
433 elsif ( $_[1][1] eq "off" ) {
434 Xchat::unhook($server_notice_hook);
435 }
436 return Xchat::EAT_XCHAT;
437}
438
439sub random_whois_msg {
440 my @msg = ("meow", "eek", "grr", "ohai", "O_O", "blargh", "pshhh", "meh", "whoa", "ONOEZ", "quack");
441 return $msg [rand scalar @msg];
442}
443
444
445
446# Adds a menu :o
447Xchat::command("MENU -p5 ADD Oper");
448Xchat::command("MENU \-k4,101 -t1 ADD \"Oper\/Filter Enabled\" \"filter on\" \"filter off\"");
449Xchat::command("MENU ADD \"Oper/Userlist\"");
450Xchat::command("MENU ADD \"Oper/Userlist/HelpOp\" \"who #help\"");
451Xchat::command("MENU ADD \"Oper/Userlist/ChatOps\" \"who +m-m oO S\"");
452Xchat::command("MENU ADD \"Oper/Userlist/LocOps\" \"who +m-m o S\"");
453Xchat::command("MENU ADD \"Oper/Userlist/GlobOps\" \"who +m o\"");
454Xchat::command("MENU ADD \"Oper/Userlist/AdChat\" \"who +m-m aA S\"");
455Xchat::command("MENU ADD \"Oper/Userlist/NaChat\" \"who +m-m N S\"");
456Xchat::command("MENU ADD \"Oper/Userlist/Clients\" \"who +n \*\"");
457Xchat::command("MENU ADD \"Oper/Userlist/IDLE\" \"notinchan\"");
458
459
460sub unload {
461 # Deletes the Oper Menu
462 Xchat::command("MENU -p5 DEL Oper");
463 Xchat::print("\cBOper Script unloaded..." );
464 Xchat::hook_timer( $rTimer,
465 sub {
466 Xchat::print("timer 1 who #help");
467 return Xchat::KEEP;
468 }
469 );
470}
471Xchat::print("\cBOper Thingy Loaded..");