#!/usr/bin/perl -w # Author: rubin@afternet.org irc.afternet.org/#afternet # The structure for this script comes from who.perl by quinton(sp?) # The who formatting function was changed from the above also # Stole the undernet snomask code from ARCNet by SmallOne # I deem this script Opensource, under the GPL available at # http://www.gnu.org # # This is a sort of do-all script intended to make xchat "how i like it". When # I first tried xchat after using ircii for MANY years, I like it, but had some # serious issues with some things, which this script attempts to fix. # For example: # * Notices are sent to active window, instead of the network window. # * Wallops look like wallops are supposed to look: !from! msg # * /w gives a list of who'se in the current channel # * who out put from the server is formatted like ircii only colorfull. # * lusers count is totaled # * will be adding more soon, this is only a first release. # # ------------------------------------------------------------------------------------ $orical_name = "Orical for X-Chat"; $orical_version = "0.9"; $O = "\00311(\00312O\00311)\003"; #--- IRC::print "$O\t\n"; IRC::print "$O\t\00311 /\00312 __ \00311\\ \003\n"; IRC::print "$O\t\00311 | \00312 / \\\00311 | ___ ___ __ \003\n"; IRC::print "$O\t\00311 | \00312| |\00311 | |__| | / /\\ | \003\n"; IRC::print "$O\t\00311 | \00312 \\__/\00311 | | \\ _|_ \\__ /--\\ |__ \003\n"; IRC::print "$O\t\00311 \\ / \0039IRC Script \003\n"; IRC::print "$O\t\00311 `----' \00313version $orical_version \00311For X-chat\003\n"; IRC::print "$O\t\00311 http://www.rdrop.com/~rubin/irc/ \003\n"; IRC::print "$O\t\n"; $version = IRC::get_info(0); # get a string of the form 1.2.0 or 1.3.3 $version =~ s/\.//g; if ($version >= 120) { IRC::register("Orical Script", $orical_version, "", ""); } IRC::add_message_handler("251", "IRC::Xchat::Orical::lusers1_handler"); # there are x users and y invi.. IRC::add_message_handler("352", "IRC::Xchat::Orical::who_handler"); # /who IRC::add_message_handler("315", "IRC::Xchat::Orical::who_end_handler"); # /who end IRC::add_message_handler("364", "IRC::Xchat::Orical::links_handler"); # /links output IRC::add_message_handler("365", "IRC::Xchat::Orical::links_end_handler"); # /links end IRC::add_message_handler("367", "IRC::Xchat::Orical::banlist_handler"); # /mode #foo +b reply IRC::add_message_handler("368", "IRC::Xchat::Orical::banlist_end_handler"); # 368 - end of banlist IRC::add_message_handler("NOTICE", "IRC::Xchat::Orical::notice_handler"); # Notices IRC::add_message_handler("PRIVMSG", "IRC::Xchat::Orical::privmsg_handler"); # msgs IRC::add_message_handler("WALLOPS", "IRC::Xchat::Orical::wallops_handler"); # wallops IRC::add_message_handler("005", "IRC::Xchat::Orical::map_handler"); # /map output IRC::add_message_handler("007", "IRC::Xchat::Orical::map_end_handler"); # end of map #IRC::add_message_handler("008", "IRC::Xchat::ARCNet::sno_mask_handler"); #ircu server notice mask handler package IRC::Xchat::Orical; $O = "\00311(\00312O\00311)\003"; # map output, with some color added sub map_handler { local($cmds) = @_; if($cmds =~ /\:\S+\s+005\s+\S+\s+\:(.*)/) { $line = $1; if($line =~ /(.*?\-)(\S+)/) { $format = $1; $server = $2; IRC::print "$O\t\00311$format\003$server"; return 1; } } return 0; } # Suppress end of map msg sub map_end_handler { return 1; } # output from /links, nicely formatted. # Not really happy with the formatting yet but it'll do for now. sub links_handler { local($cmds) = @_; if($cmds =~ /\:\S+\s+\S+\s+\S+\s+(\S+)\s+(\S+)\s+\:(.*)/) { $server = $1; $uplink = $2; $rest = $3; if($rest =~ /(\d+)\s+(\S+)\s+(\[\S+\])\s+(.+)/) { IRC::print "$O\0034$4\t\0038- \00313$2\0036$3\003:"; } my $line = sprintf("%25s\t\0038-->\00311 %-30s\003", $server, $uplink); IRC::print "$O$line"; return 1; } return 0; } # Suppress end of links message sub links_end_handler { return 1; } sub banlist_handler { local($cmd) = @_; if($cmd =~ /\S+\s+367\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\d+).*/) { $nick = $1; $chan = $2; $ban = $3; $setby = $4; $time = $5; if($UBA_PENDING =~ /$chan/i) #case insensitive match on $chan { IRC::send_raw "MODE $chan -b $ban\n"; return 1; } IRC::print "$O\0036$chan\t\0037$ban\003 set by \00311$setby\003 on \00311$time\003"; return 1; } return 0; } # num 368 - end of ban list # If we did a uba, it temporarily changes the ban list handler, # this turns it back off. Otherwise future /bans commands will # inadvertantly remove those bans. sub banlist_end_handler { #:Agora.us.AfterNet.org 368 Rubin #afternet :End of Channel Ban List local($cmds) = @_; if($cmds =~ /.*\s+368\s+\S+\s+(\#\S+)\s+.*/) { $chan = $1; if($chan =~ /$UBA_PENDING/i) { undef($UBA_PENDING); return 1; } } return 0; } # The server numerics for sno_mask to report it in a human readable form :) # ** This is causing sometimes crashes; dont use it till its fixed. sub sno_mask_handler { return 0; local($line) = @_; #:se1.arcnet.vapor.com 008 SmallBBL 4 :: Server notice mask (0x4) #This is the line we want to parse and get the notice mask id $line =~ m/:(.*) 008 (.+?) (.+?) :: (.*)/; $myserver=$1; #The server we are connected to $mynick=$2; #The current nickname $id=$3; #SNO_MASK id $servercrap=$4; #We dont need the rest of the line undef $string_literal; # undefine some stuff that might cause trouble if previously defined undef @string_array; # the list of all the elements we're searching for @id_mask = (16384 , 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1); # Declare a hash for the values $attribute_hash = {}; # Now put each value into the attribute hash $attribute_hash->{1} = "SNO_OLDSNO"; $attribute_hash->{2} = "SNO_SERVKILL"; $attribute_hash->{4} = "SNO_OPERKILL"; $attribute_hash->{8} = "SNO_HACK2"; $attribute_hash->{16} = "SNO_HACK3"; $attribute_hash->{32} = "SNO_UNAUTH"; $attribute_hash->{64} = "SNO_TCPCOMMON"; $attribute_hash->{128} = "SNO_TOOMANY"; $attribute_hash->{256} = "SNO_HACK4"; $attribute_hash->{512} = "SNO_GLINE"; $attribute_hash->{1024} = "SNO_NETWORK"; $attribute_hash->{2048} = "SNO_IPMISMATCH"; $attribute_hash->{4096} = "SNO_THROTTLE"; $attribute_hash->{8192} = "SNO_OLDREALOP"; $attribute_hash->{16384} = "SNO_CONNEXIT"; foreach $mask_element (@id_mask) { $tested_id = $id - $mask_element; if ( $tested_id >= 0 ) { push ( @string_array , $attribute_hash->{$mask_element} ); $id = $id - $mask_element; } } # @string_array will now hold a list of all the text elements present $string_literal = join( "|" , @string_array ); # This leave $string_literal defined as a '|' delimited list of all the notice strings IRC::print "*** Server notice mask is now $string_literal\n"; # Here we print the stuff :) return 1; } # format wallops sub wallops_handler { local($cmds) = @_; if( $cmds =~ /\:(\S+)\s+WALLOPS\s+\:(.+)/ ) { $source = $1; $msg = $2; if( $source =~ /(\S+)\!\S+.+/ ) { $source = $1; } IRC::print "\00311!\00313$source\00311!\003\t$msg\n"; } return 1; } # numberic 251 1st line lusers reply sub lusers1_handler { local($cmds) = @_; if($cmds =~ /.*\:\D+(\d+)\D+(\d+)\D+(\d+)/) { $norm = $1; $invis = $2; $servers = $3; $tot = $norm + $invis; IRC::print "-\00310-\00311-\003\tThere are \00311$norm\003 users and \00311$invis\003 invisible on $servers servers"; IRC::print "\00311(\00312O\00311)\003\tTotal Users: \00311$tot\003"; } return 1; } # Put notices in active window sub notice_handler { local($cmds) = @_; $cmds =~ /\:(\S+)\s+NOTICE\s+(\S+)\s+\:(.*)/; $source = $1; $target = $2; $msg = $3; if($source =~ /(.+)\!(.+)\@(.+)/) { $nick = $1; $user = $2; $host = $3; IRC::print "\0032-\00313$nick\0032-\003\t$msg\n"; } else # Must be a server { # *** Notice -- X2.AfterNET.Services addin... if($msg =~ /\001.*\001/) # a CTCP { return 0; } if($msg =~ /\*\*\*\s+Notice\s+\-\-\s+(.+)/ ) { $servnotice = $1; IRC::print "\00311(\00312O\00311)\003\t\0038$servnotice\n"; } # else if( $msg =~ / /) # { # } else { $myserver = IRC::get_info(3); # current server if($myserver =~ /$source/) { IRC::print "-\00310-\00311-\003\t\0038$msg\n"; } else { IRC::print "-$source-\t\0038$msg\n"; } } } return 1; } sub privmsg_handler { local($cmds) = @_; #IRC::print "privmsg_handler: $cmds\n"; return 0; } ########################### ##### End of on_stuff ##### ########################### ########################### ##### Beg of aliases ###### ########################### # commands (and aliases) IRC::add_command_handler("w", "IRC::Xchat::Orical::w_cmd_handler"); # /w IRC::add_command_handler("who", "IRC::Xchat::Orical::who_cmd_handler"); # /who IRC::add_command_handler("wi", "IRC::Xchat::Orical::wi_cmd_handler"); # /wi IRC::add_command_handler("wii", "IRC::Xchat::Orical::wii_cmd_handler"); # /wii IRC::add_command_handler("mode", "IRC::Xchat::Orical::mode_cmd_handler"); # /mode IRC::add_command_handler("luser", "IRC::Xchat::Orical::luser_cmd_handler"); # /lusers abbrev IRC::add_command_handler("wallop", "IRC::Xchat::Orical::wallop_cmd_handler");# /wallops abbrev IRC::add_command_handler("ohelp", "IRC::Xchat::Orical::ohelp_cmd_handler"); # /ohelp IRC::add_command_handler("snomask", "IRC::Xchat::Orical::sno_mask_cmd"); # /snomask from SmallOne IRC::add_command_handler("snomode", "IRC::Xchat::Orical::sno_mask_cmd"); # alias to snomask IRC::add_command_handler("umode", "IRC::Xchat::Orical::umode_cmd"); # /umode +g-s 23 etc IRC::add_command_handler("bans", "IRC::Xchat::Orical::bans_cmd"); # /bans IRC::add_command_handler("gone", "IRC::Xchat::Orical::gone_cmd"); # /gone IRC::add_command_handler("back", "IRC::Xchat::Orical::back_cmd"); # /back IRC::add_command_handler("uba", "IRC::Xchat::Orical::uba_cmd"); # /uba [chan] IRC::add_command_handler("k", "IRC::Xchat::Orical::k_cmd"); IRC::add_command_handler("kb", "IRC::Xchat::Orical::kb_cmd"); IRC::add_command_handler("b", "IRC::Xchat::Orical::b_cmd"); IRC::add_command_handler("ub", "IRC::Xchat::Orical::ub_cmd"); IRC::add_command_handler("repeat", "IRC::Xchat::Orical::repeat_cmd"); IRC::add_command_handler("sheep", "IRC::Xchat::Orical::sheep_cmd"); IRC::add_command_handler("snl", "IRC::Xchat::Orical::snl_cmd"); IRC::add_command_handler("yawn", "IRC::Xchat::Orical::yawn_cmd"); IRC::add_command_handler("sammich", "IRC::Xchat::Orical::sammich_cmd"); IRC::add_command_handler("rose", "IRC::Xchat::Orical::rose_cmd"); IRC::add_command_handler("spam", "IRC::Xchat::Orical::spam_cmd"); # Spam sub spam_cmd { local($cmds) = @_; if($cmds) { IRC::command "/msg $cmds " . '%B,dP""8a "888888b, d8b "888b ,888" '; IRC::command "/msg $cmds " . '%B88b " 888 d88 dPY8b 88Y8b,8888 '; IRC::command "/msg $cmds " . '%B`"Y8888a 888ad8P\'dPaaY8b 88 Y88P888 '; IRC::command "/msg $cmds " . '%Ba, Y88 888 dP Y8b 88 YP 888 '; IRC::command "/msg $cmds " . '%B`"8ad8P\'a888a a88a *a888aa88a a888a '; } else { IRC::print "$O\tSyntax: \0038Spam\003 "; } return 1; } # @-'-,- rose sub rose_cmd { local($cmds) = @_; if($cmds) { IRC::command "/me offers $cmds a Rose \0034\@\0033-'-,-\003"; } else { IRC::print "$O\tSyntax: \0038ROSE\003 "; } return 1; } # yawn sub yawn_cmd { IRC::command "/me *yawns*"; return 1; } # The infamouse /sammich for Rubin! * Rubin *sammichhuggles* $target sub sammich_cmd { local($cmds) = @_; if($cmds) { IRC::command "/me *%Bsammichuggles%O* $cmds"; } else { IRC::print "$O\tSyntax: \0038SAMMICH\003 "; } return 1; } # These are lame, but classic; Just for fun ;) sub sheep_cmd { local($cmds) = @_; if($cmds =~ /(\S+)\s+(\S+)\s+(\S+)\s*/) { IRC::command "/msg $1 ". ' ___'; IRC::command "/msg $1 ". ' / |'; IRC::command "/msg $1 ". ' / - | <=====' . $2; IRC::command "/msg $1 ". ' | @@'; IRC::command "/msg $1 ". ' @@@@@@@@@'; IRC::command "/msg $1 ". ' @@@@@@@@@@______#'; IRC::command "/msg $1 ". ' @@@@@@@@@@_______# /\___'; IRC::command "/msg $1 ". ' @@@@@@@@@@@@ @@@@@@@@@@ @ |'; IRC::command "/msg $1 ". ' @@@@@@@@@@@@ @@@@@@@@@@@@@@___/ <====='. $3; IRC::command "/msg $1 ". ' @@@@@@@@@@=@@@@@@@@@@@@@@@'; IRC::command "/msg $1 ". ' @@@@@@@|| @@@@@@@@@@@'; IRC::command "/msg $1 ". ' @ || || ||'; IRC::command "/msg $1 ". ' ~~~ ~~ ~~'; } else { IRC::print "$O\tSyntax: \0038SHEEP\003 "; } return 1; } sub snl_cmd { local($cmds) = @_; if($cmds =~ /(\S+)\s+(\S+)\s*/) { IRC::command "/say $1!!!!!!! $2ster!!! $2-o-rama!!! $2miester!!! $2inator!! $2ola!!! makin $2's!!! $2a-$2a-ding-dong!!! The $2!!!"; return 1; } IRC::print "$O\tSyntax: \0038SNL \003"; return 1; } # repeats the same thing over and over sub repeat_cmd { local($cmds) = @_; if($cmds =~ /(\d+)\s+(.+)/) { $count = $1; $cmd = $2; for($i=0;$i<$count;$i++) { IRC::command "/$cmd"; } return 1; } else { IRC::print "$O\t\syntax: \0038REPEAT\003 "; } } #alias for /unban sub ub_cmd { local($cmds) = @_; IRC::command "/unban $cnds"; return 1; } # alias for /ban sub b_cmd { local($cmds) = @_; IRC::command "/ban $cmds"; return 1; } # kick-ban sub kb_cmd { local($cmds) = @_; IRC::command "/kickban $cmds"; return 1; } sub k_cmd { local($cmds) = @_; IRC::command "/kick $cmds"; return 1; } sub uba_cmd { local($cmds) = @_; if($cmds =~ /\#.*/) { $chan = $cmds; } else { $chan = IRC::get_info(2); } # Set a variable the ban parsing sub can detect: $UBA_PENDING = $chan; IRC::send_raw "MODE $chan +b\n"; return 1; } sub gone_cmd { local($cmds) = @_; if($cmds =~ /.+/) { $reason = $cmds; } else { $reason = "Gone"; } IRC::command("/AWAY [%B $reason %O]"); return 1; } sub back_cmd { IRC::command("/AWAY"); return 1; } sub bans_cmd { local($cmds) = @_; if($cmds =~ /\#.*/) { $chan = $cmds; } else { $chan = IRC::get_info(2); } IRC::send_raw("mode $chan +b\n"); return 1; } # The /umode command used instead of /mode nick +-mode # Xchat has this, but it does not support all modes etc. sub umode_cmd { $nick=IRC::get_info(1); #get the current nickname local($cmds) = @_; $cmds =~ m/(.*)/; IRC::send_raw("mode $nick $cmds\r\n"); return 1; } #The Server notice mask command changes the current +s mask on undernet servers sub sno_mask_cmd { $nick=IRC::get_info(1); #get current nickname local($cmds) = @_; @command=split(/ /, $cmds); #split the commands foreach $command (@command){ SWITCH: { if ($command eq "+OLDSNO"){ IRC::send_raw("mode $nick +s +1\r\n"); last SWITCH; } if ($command eq "-OLDSNO"){ IRC::send_raw("mode $nick +s -1\r\n"); last SWITCH; } if ($command eq "+SERVKILL"){ IRC::send_raw("mode $nick +s +2\r\n"); last SWITCH; } if ($command eq "-SERVKILL"){ IRC::send_raw("mode $nick +s -2\r\n"); last SWITCH; } if ($command eq "+OPERKILL"){ IRC::send_raw("mode $nick +s +4\r\n"); last SWITCH; } if ($command eq "-OPERKILL"){ IRC::send_raw("mode $nick +s -4\r\n"); last SWITCH; } if ($command eq "+HACK2"){ IRC::send_raw("mode $nick +s +8\r\n"); last SWITCH; } if ($command eq "-HACK2"){ IRC::send_raw("mode $nick +s -8\r\n"); last SWITCH; } if ($command eq "+HACK3"){ IRC::send_raw("mode $nick +s +16\r\n"); last SWITCH; } if ($command eq "-HACK3"){ IRC::send_raw("mode $nick +s -16\r\n"); last SWITCH; } if ($command eq "+UNAUTH"){ IRC::send_raw("mode $nick +s +32\r\n"); last SWITCH; } if ($command eq "-UNAUTH"){ IRC::send_raw("mode $nick +s -32\r\n"); last SWITCH; } if ($command eq "+TCPCOMMON"){ IRC::send_raw("mode $nick +s +64\r\n"); last SWITCH; } if ($command eq "-TCPCOMMON"){ IRC::send_raw("mode $nick +s -64\r\n"); last SWITCH; } if ($command eq "+TOOMANY"){ IRC::send_raw("mode $nick +s +128\r\n"); last SWITCH; } if ($command eq "-TOOMANY"){ IRC::send_raw("mode $nick +s -128\r\n"); last SWITCH; } if ($command eq "+HACK4"){ IRC::send_raw("mode $nick +s +256\r\n"); last SWITCH; } if ($command eq "-HACK4"){ IRC::send_raw("mode $nick +s -256\r\n"); last SWITCH; } if ($command eq "+GLINE"){ IRC::send_raw("mode $nick +s +512\r\n"); last SWITCH; } if ($command eq "-GLINE"){ IRC::send_raw("mode $nick +s -512\r\n"); last SWITCH; } if ($command eq "+NETWORK"){ IRC::send_raw("mode $nick +s +1024\r\n"); last SWITCH; } if ($command eq "-NETWORK"){ IRC::send_raw("mode $nick +s -1024\r\n"); last SWITCH; } if ($command eq "+IPMISMATCH"){ IRC::send_raw("mode $nick +s +2048\r\n"); last SWITCH; } if ($command eq "-IPMISMATCH"){ IRC::send_raw("mode $nick +s -2048\r\n"); last SWITCH; } if ($command eq "+THROTTLE"){ IRC::send_raw("mode $nick +s +4096\r\n"); last SWITCH; } if ($command eq "-THROTTLE"){ IRC::send_raw("mode $nick +s -4096\r\n"); last SWITCH; } if ($command eq "+OLDREALOP"){ IRC::send_raw("mode $nick +s +8192\r\n"); last SWITCH; } if ($command eq "-OLDREALOP"){ IRC::send_raw("mode $nick +s -8192\r\n"); last SWITCH; } if ($command eq "+CONNEXIT"){ IRC::send_raw("mode $nick +s +16384\r\n"); last SWITCH; } if ($command eq "-CONNEXIT"){ IRC::send_raw("mode $nick +s -16384\r\n"); last SWITCH; } IRC::print "Usage: /snomask +-\n"; } } return 1; } sub ohelp_cmd_handler { $O = "\00311(\00312O\00311)\003"; IRC::print "$O\tOrical Help:\n"; IRC::print "$O\t------------\n"; IRC::print "$O\tw - List who is in current channel\n"; IRC::print "$O\twi - Show whois information on a nick\n"; IRC::print "$O\twii - Show detailed (slower) information on a nick\n"; IRC::print "$O\tluser - Show network connection statistics\n"; IRC::print "$O\tsnomask- Set undernet +s mode masks"; IRC::print "$O\trose - Sends a rose"; IRC::print "$O\tyawn - Yawns"; IRC::print "$O\tsheep - Sends lude sheep"; return 1; } sub luser_cmd_handler { IRC::command "/lusers"; return 1; } sub wallop_cmd_handler { local($cmd) = @_; IRC::command "/WALLOPS $cmd\n"; return 1; } sub w_cmd_handler { if( $target = IRC::get_info(2)) { IRC::command "/who $target"; } return 1; } # allows * to mean "current channel" sub mode_cmd_handler { local($cmds) = @_; $cmds =~ /(\S+)\s(.*)/; $target = $1; $rest = $2; if($target == "*") { $target = IRC::get_info(2); } IRC::send_raw("Mode $target $rest\n"); #IRC::print "Sending: MODE $target $rest\n"; return 1; } sub who_cmd_handler { local($cmds) = @_; # command line may contain extra white spaces. $cmds =~ s/\s+$//; IRC::print "\00311(\00312O\00311)\003\t\00311Who list for $cmds\003\n"; IRC::send_raw("WHO $cmds\r\n"); return 1; } # this handler is used to avoid printing of "End of list" message sub who_end_handler { local($line) = @_; # IRC::print "who_end_handler() ''$line''\n"; return 1; } sub wi_cmd_handler { local($cmds) = @_; if($cmds =~ /\S+/) { IRC::send_raw("WHOIS $cmds\n"); } else { IRC::print "$O\t\0038WI\003 Usage: \00311WI \003\n"; IRC::print "$O\tRetrieves whois info.\n"; } return 1; } sub wii_cmd_handler { local($cmds) = @_; if($cmds =~ /\S+/) { IRC::send_raw("WHOIS $cmds $cmds\n"); } else { IRC::print "$O\t\0038WI\003 Usage: \00311WII \003\n"; IRC::print "$O\t\Retrieves detailed whois info from remote server.\n"; } return 1; } # this is the real handler, it is used to reformat the /who command return values sub who_handler { local($line) = @_; # /who list # >> :server 352 me chan user addr serv2 nick flag1 :flag2 realname if($line =~ m/:(.*)\s+352\s+(.*?)\s+(.*?)\s+(.*?)\s+(.*?)\s+(.*?)\s+(.*?)\s+(.*?):(.*?)\s+(.*)/o) { $server = $1; # irc server adresse $me = $2; # my nick name $chan = $3; # which chan nick is on $user = $4; # username $addr = $5; # user adresse $serv2 = $6; # an other serv adress with meta char ? $nick = $7; # nickname $flag1 = $8; # flags ? $flag2 = $9; # flags ? $real = $10; # realname # XXXX : change display format here ! # Setup to look like (good) ircii script my $result = sprintf("\0036%s\t\00311%-10s\0033 %-4s \00310%s\00315\@\00310%s\003 (%s)", $chan, $nick, $flag1, $user, $addr, $real); IRC::print "$result\n"; return 1; } else { # there may be a probleme with /who result that may have change format. IRC::print "xchat::who handler: may be a problem with return value of /who command\n"; IRC::print "xchat::who handler: this is a pattern matching problem.\n"; IRC::print "xchat::who handler: using default handler\n"; # so make default handler work ;-) return 0; } return 0; } IRC::print "$O\tOrical loading complete. See /ohelp for details \003\n"; 1; _END_