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