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