#// relay.tcl v2.1.7 - Send Channel Text/Acts/Join/Part/Quit/Topc/Nick/Kick/Ban #// Data to one or more networks #// #// v2.1.7 By: `Kumba #// v1.0.0 By: cl00bie #// #// TCL regsub code for mirc code stripping borrowed from mc.moretools by MC_8 #// Version Var set relay-version "2.1.7" #//-------------------------------------------------------------------------------------------------------------- #// --- Known Bugs/Glitches --- #// #// #// 1. Sometimes Unbans will echo twice from a particular network #// #// 2. Netsplits/Merges don't always trigger -- Sometimes treated as Quits/Joins #// #// 3. Due to using "putquick ", in a large relay with lots of #// conversation, it is remotely possible for the order of chat/actions, etc.., to #// get mixed up, sometimes with an action appearing before a line of chat #// or vice-versa. #// #// 4. This script is not advisable for use on IRC Channels which have a large amount #// activity as therein exists the possibility of the relay bots being flooded off #// the chat network by trying to output everything said. #//-------------------------------------------------------------------------------------------------------------- #// --- Observed IRC Network Oddities --- #// #// #// 1. Networks based on the Bahamut IRCd Codebase fail to check to see if a #// Mode (+/- o/h/v) is already applied to a nickname before applying the #// mode. The result is the mode can get applied twice, or more, despite it has #// already been applied. #//-------------------------------------------------------------------------------------------------------------- #// --- Global Variables --- #// -- Network/Botnet Variables -- #// List of channels to relay between (lower case only!) set therelay(channels) "#channel1 #channel2 #channel3" #// Total Number of Networks we will be relaying (Minimum 2) set therelay(maxnets) 3 #// --- The Following Variables must contain the same Number of Elements, --- #// --- In the same order as the other Elements. --- #// --- Example: --- #// --- --- #// --- set therelay(botirc) "botircnick1 botircnick2 botircncik3" --- #// --- set therelay(botnet) "botnetnick1 botnetnick2 botnetnick3" --- #// --- set therelay(netwrk) "netwrkname1 netwrkname2 netwrkname3" --- #// --- #// --- IRC Nicks are the nicknames the bots use on IRC #// --- BOTNET nicks are the nicknames used by the bots on a botnet #// --- if IRC and BOTNET nicks are the same, specify them both anyways #// IRC Nicknames of bots we will be talking to (Names _MUST_ be different) set therelay(botirc) "botircnick1 botircnick2 botircnick3" #// BOTNET Nicknames of bots we will be talking to (Names _MUST_ be different) set therelay(botnet) "botnetnick1 botnetnick2 botnetnick3" #// Names of the Networks as will be seen by others (i.e., @) set therelay(netwrk) "netwrkname1 netwrkname2 netwrkname3" #// -- Option Variables (1 == enable; 0 == disable) -- #// Turn On/Off The Relay? (Shuts off *EVERYTHING* except !rehash/!restart/!shutdown) set theopts(master) 1 #// Show Public Chatter? set theopts(show_pubm) 1 #// Show Actions? set theopts(show_act) 1 #// Show Nickname Changes? set theopts(show_nick) 1 #// Show Status Changes? (This includes multiple bans/excepts/invites at once) set theopts(show_statchg) 1 #// Show Joins? set theopts(show_join) 1 #// Show Quits? set theopts(show_sign) 1 #// Allow Quit messages to be shown? set theopts(show_quitmsg) 1 #// Show Parts? set theopts(show_part) 1 #// Show Topic Changes? (On a large relay, this can get annoying) set theopts(show_topc) 1 #// Show Kicks? set theopts(show_kick) 1 #// Show Bans? (Disabling this will disable the showing of Excepts && Invites!) set theopts(show_ban) 1 #// Show Netsplits? (Sometimes will show up as a Quit) set theopts(show_splt) 1 #// Show Netmerges? (Sometimes shows up as a Join) set theopts(show_rejn) 1 #// Nickname Overflow Limit when reporting Netsplits? #// This value is HIGHLY dependent on the Maximum Nick Length of all the networks, #// and on whether color support is enabled. Please choose a value that will ensure #// All nicknames appear in the list regardless of the network. "25" is the default. set theopts(max_spltrejn) 25 #// Show Bot Links? set theopts(show_link) 1 #// Show Bot Disconnects? set theopts(show_disc) 1 #// Allow use of the !names directive? set theopts(allow_names) 1 #// Maximum number of users to display in a single line of a !names return? #// This value is HIGHLY dependent on the Maximum Nick Length of all the networks, #// and on whether color support is enabled. Please choose a value no greater than #// "35". #// #// This is due to Eggdrop having an upper limit on the amount of data it #// can pass over the botnet. For relaying networks which allow long nicknames, #// choose a smaller value. For relaying networks that permit short nicknames only, #// use a larger value. For relaying networks that contain a mix of long and short #// nickname lengths, pick a value that makes sense, otherwise, the nicklist data #// may not make it to the requesting bot completely, and may confuse users. #// #// Also, if color support is turned on, take extra special care in selecting an #// appropriate value as color data will pad the text that is sent across the botnet. #// #// An example relay network may consist of one "primary" network, in which a #// majority of users will stay on. The other networks may only have a few users, #// never as many users as the primary network. The primary network will only allow #// 9-character nicknames, while other networks allow 12 to 30 character nicknames. #// In this case, select a value that will best suit displaying all the users on the #// primary network. For this example, using color support, a maximum of "25" nicknames #// per line is reccommended. Without color support, "35" is the maximum. Since most #// users will be on the primary network, this configuration works best since #// there will be much fewer users with longer nicknames on the other networks, and #// displaying their nicknames will not be much of a problem. #// #// Remember, the above is only an example that has been tested. Requirements for other #// relay configurations will vary, so set the value below accordingly. Do not exceed #// "35" in either scenario as this exceeds a limit in eggdrop itself, and the script #// checks for this. set theopts(max_names) 25 #// Allow Inter-Relay PRIVMSGes? set theopts(allow_privmsg) 1 #// Allow !gettopic? (Fetches the topic from another network) set theopts(allow_gettopic) 1 #// Enable !kick? set theopts(enable_cmdkick) 1 #// Enable !kickban? set theopts(enable_cmdkickban) 1 #// Length of time a !kickban should last? (60 min is the reccommended default) set theopts(cmdkickban_len) 60 #// Enable !op/!deop? set theopts(enable_cmdops) 1 #// Enable !voice/!devoice? set theopts(enable_cmdvoices) 1 #// Enable !halfop/!dehalfop? set theopts(enable_cmdhalfops) 1 #// Enable !mode? set theopts(enable_cmdmode) 1 #// Enable !topic? set theopts(enable_cmdtopc) 1 #// Enable !help? set theopts(enable_cmdhelp) 1 #// Enable !hurt && !heal? (Attempts silence a user) set theopts(enable_cmdhurt) 1 #// Echo Relay Commands? (!op/!deop/!voice/!devoice, etc...) set theopts(enable_echocmd) 1 #// Strip Control Codes from Relay Text? (Color, Bold, Underline, Reverse) set theopts(strip_codes) 1 #// -- Color/Codes Options (1 == enable; 0 == disable) -- #// If you wish to edit the actual colors, then see further down #// Enable Colors/Codes? (If disabled, all color options below have no effect) set thecolors(master) 1 #// Enable Public Chatter Colors/Codes? set thecolors(pubm) 1 #// Enable Public Action Colors/Codes? set thecolors(act) 1 #// Enable Nickname Colors/Codes? set thecolors(nick) 1 #// Enable Modes Colors/Codes? set thecolors(mode) 1 #// Enable Join Colors/Codes? set thecolors(join) 1 #// Enable Quit Colors/Codes? set thecolors(sign) 1 #// Enable Part Colors/Codes? set thecolors(part) 1 #// Enable Topic Colors/Codes? set thecolors(topc) 1 #// Enable Kick Colors/Codes? set thecolors(kick) 1 #// Enable Bans/Exempts/Invites Colors/Codes? set thecolors(ban) 1 #// Enable Netsplit Colors/Codes? set thecolors(splt) 1 #// Enable Netmerge Colors/Codes? set thecolors(rejn) 1 #// Enable Botnet Link Colors/Codes? set thecolors(link) 1 #// Enable Botnet Discconnect Colors/Codes? set thecolors(disc) 1 #// Enable Colors/Codes for !names Output? set thecolors(names) 1 #// Enable Colors/Codes for Privmsg Output? set thecolors(privmsg) 1 #// Enable Colors/Codes for !help Output? set thecolors(help) 1 #// -- Miscellaneous Options (1 == enable; 0 == disable) -- #// Prefix before certain messages, like Modes/Bans/Unbans/Joins/Parts/Quits (include a trailing space!) #// Default Value: "\00312-\003\00314!\003\00312-\003 " set therelay(prefix) "\00312-\003\00314!\003\00312-\003 " #// Name of the relay (Default is "Eggdrop IRC Relay") set therelay(name) "Eggdrop IRC Relay" #// Enable !rehash? (Owner Only!) set theopts(enable_cmdrehash) 1 #// Enable !restart? (Owner Only!) set theopts(enable_cmdrestart) 1 #// Enable !shutdown? (Owner Only!) set theopts(enable_cmdshutdown) 1 #//-------------------------------------------------------------------------------------------------------------- #//-------------------------------------------------------------------------------------------------------------- #// There are no more normal options to configure below this line. If this is the first time this script is used, #// then comment out the _die_ line further below in the "Checks" section. If you are interested in modifying #// the default colors used, then refer to the "Configure Colors" section below, read the comments, and change #// what is appropriate, otherwise, do not edit anything beyond this point unless you are aware of what you #// are doing. #//-------------------------------------------------------------------------------------------------------------- #//-------------------------------------------------------------------------------------------------------------- #//-------------------------------------------------------------------------------------------------------------- #// --- Checks --- #// ### Make sure people actually edit this script before using it "out of the box" ### die "FATAL ERROR (Relay): You must edit the Relay Script before using it, and remove this \"die\" line." #// Since this script is tried and tested on Eggdrop 1.6.12, let's enforce that if {[lindex [split [lindex [split $version] 0] .] 0] >= 1 && \ [lindex [split [lindex [split $version] 0] .] 1] >= 6 && \ [lindex [split [lindex [split $version] 0] .] 2] >= 12} { } else { die "FATAL ERROR (Relay): This script must be used on Eggdrop 1.6.12 or higher." } #// Enforce a minimum of 2 Networks if {$therelay(maxnets) < 2} { die "FATAL ERROR (Relay): Minimum of two defined Networks required. Check \$therelay(maxnets)." } #// Make sure that all the lists contain same number of elements as $therelay(maxnets) if {[llength $therelay(botirc)] != $therelay(maxnets) && \ [llength $therelay(botnet)] != $therelay(maxnets) && \ [llength $therelay(netwrk)] != $therelay(maxnets)} { die "FATAL ERROR (Relay): Incorrect Size of \$therelay(botirc)\, \$therelay(botnet)\, and/or \ \$therelay(netwrk)\; Must equal \$therelay(maxnets)." } #// Figure out our network set therelay(botpos) [lsearch -exact $therelay(botnet) ${botnet-nick}] if {$therelay(botpos) != -1} { set therelay(ournet) [lindex [split $therelay(netwrk)] $therelay(botpos)] } else {die "FATAL ERROR (Relay): Unable to determine my home network, please check settings."} #// Prevent theopts(max_names) from exceeding "35" if {$theopts(allow_names) == 1 && $theopts(max_names) > 35} { die "FATAL ERROR (Relay): \$theopts(max_names) may NOT exceed \"35\". Please choose a lower value." } #//-------------------------------------------------------------------------------------------------------------- #// --- Color/Code Stripper --- #// Strips Mirc Colors/Bold/Underline/Reverse from text proc strip_codes {text} { global theopts if {$theopts(strip_codes) == 1} { regsub -all -- "\003(\[0-9\]\[0-9\]?(,\[0-9\]\[0-9\]?)?)?" $text "" text; #// Color regsub -all -- "\002" $text "" text; #// Bold regsub -all -- "\026" $text "" text; #// Reverse regsub -all -- "\037" $text "" text; #// Underline } return $text } #//-------------------------------------------------------------------------------------------------------------- #// --- Configure Colors --- #// Color Variable Names: #// $c() #// #// Where is equivalent to: #// 1 == pubm; 2 == act; 3 == nick; 4 == mode; 5 == join; 6 == quit; 7 == part #// 8 == topc; 9 == kick; 10 == ban; 11 == splt; 12 == rejn; 13 == link; #// 14 == disc; 15 == names; 16 == privmsg; 17 == gettopic; 18 == help #// #// Where is equivalent to: #// brac == Angle/Square Brackets/Paranthesis; nick == Nicknames; netw == Networks; #// star == Asterisk; oldn == Old Nickname; newn == New nickname; mode == Modes; #// chan == Channels; host == Userhosts; topc == Topics; kick == Kicks; #// vict == Victims; mask == Hostmasks; splt == Netsplits; rejn == Netmerges; #// link == Botlinks; disc == Bot Disconnects; abot == Bots; #// ___o == Op; ___h == Halfop; ___v == Voice; numA == Number Range A; #// numB == Number Range B; totl == User Totals; help == Help; #// cmds == Help Commands; args == Help Arguments; atch == '@' (At) Character; #// slsh == Forward Slash; #// #// The purpose for this variable naming scheme is to keep the variable names themselves #// as small as possible while still being understandable to anyone reading this code. #// #// The Color Code itself is made up of two parts. First, "\003" is a character code for #// the color identifier, and the last two digits are the code identifying what color is #// to be used. For example, "\00314" specifies a Dark Grey while "\00310 specifies Cyan #// as a color. "\003" by itself terminates an open color code, i.e. "\00314 \003" #// #// Please do realize that using colors pads all IRC text with extra characters not normally #// seen by a standard IRC Client, but these characters must still be dealt with by the IRC Server, #// and all IRC Servers have a different limit on how much text they will deal with on a per #// message basis. Enabling colors may cause some text to not get fully sent across the relay. #// The most common example of this is when using the !names directive or a netsplit involving #// a large number of people occurs, and colors are turned on. If you notice this, then either #// disable the color for that specific command/action, or for !names/netsplit reporting, lower #// the amount of data being sent in the normal Options section near the beginning of this script #// If this is occuring in normal channel text, advise people to limit how much text they type in #// a single line. #// #// The colors chosen below work best in conjunction with black backgrounds, however, they #// should look fine on white backgrounds as well. The color scheme resembles that of #// Irssi, a console IRC Client for Unix/Linux. #// #// Please see the comments below for each color variable below to further understand #// this format. proc configure_colors {} { global therelay theopts thecolors c if {$theopts(master) == 1} { #// Prefix Stripper if {$thecolors(master) != 1} { set therelay(prefix) [strip_codes $therelay(prefix)] } #// Public Chatter if {$thecolors(pubm) == 1 && $thecolors(master) == 1} { set c(1brac) "\00314"; #// Dark Grey - Angle Brackets set c(1nick) ""; #// No Color - Nickname set c(1netw) ""; #// No Color - Network set c(1x) "\003"; #// Color Terminator } else { set c(1brac) ""; set c(1nick) ""; set c(1netw) ""; set c(1x) ""; } #// Public Actions if {$thecolors(act) == 1 && $thecolors(master) == 1} { set c(2star) "\00314"; #// Dark Grey - Asterisk set c(2nick) ""; #// No Color - Nickname set c(2netw) ""; #// No Color - Network set c(2x) "\003"; #// Color Terminator } else { set c(2star) ""; set c(2nick) ""; set c(2netw) ""; set c(2x) ""; } #// Nickname Changes if {$thecolors(nick) == 1 && $thecolors(master) == 1} { set c(3nick) "\00310"; #// Dark Cyan - "Nick" set c(3oldn) "\00310"; #// Dark Cyan - Old Nickname set c(3netw) "\00310"; #// Dark Cyan - Network set c(3newn) "\00303"; #// Dark Green - New Nickname set c(3slsh) "\00314"; #// Dark Grey - Forward Slash set c(3x) "\003"; #// Color Terminator } else { set c(3nick) ""; set c(3oldn) ""; set c(3netw) ""; set c(3newn) ""; set c(3slsh) ""; set c(3x) ""; } #// Mode Changes if {$thecolors(mode) == 1 && $thecolors(master) == 1} { set c(4mode) "\00310"; #// Dark Cyan - "Mode" set c(4netw) "\00310"; #// Dark Cyan - Network set c(4nick) "\00303"; #// Dark Green - Nick that made Mode Change set c(4brac) "\00314"; #// Dark Grey - Square Brackets set c(4slsh) "\00314"; #// Dark Grey - Forward Slash set c(4x) "\003"; #// Color Terminator } else { set c(4mode) ""; set c(4netw) ""; set c(4nick) ""; set c(4brac) ""; set c(4slsh) ""; set c(4x) ""; } #// Joins if {$thecolors(join) == 1 && $thecolors(master) == 1} { set c(5join) "\00310"; #// Dark Cyan - "Join" set c(5chan) "\00303"; #// Dark Green - Channel set c(5host) "\00306"; #// Dark Purple - Hostmask set c(5nick) "\00310"; #// Dark Cyan - Nickname set c(5netw) "\00310"; #// Dark Cyan - Network set c(5brac) "\00314"; #// Dark Grey - Square Brackets set c(5slsh) "\00314"; #// Dark Grey - Forward Slash set c(5x) "\003"; #// Color Terminator } else { set c(5join) ""; set c(5chan) ""; set c(5host) ""; set c(5nick) ""; set c(5netw) ""; set c(5brac) ""; set c(5slsh) ""; set c(5x) ""; } #// Quits/Signoffs if {$thecolors(sign) == 1 && $thecolors(master) == 1} { set c(6sign) "\00310"; #// Dark Cyan - "Quit" set c(6chan) "\00303"; #// Dark Green - Channel set c(6nick) "\00310"; #// Dark Cyan - Nickname set c(6netw) "\00310"; #// Dark Cyan - Network set c(6brac) "\00314"; #// Dark Grey - Parenthesis set c(6slsh) "\00314"; #// Dark Grey - Forward Slash set c(6x) "\003"; #// Color Terminator } else { set c(6sign) ""; set c(6chan) ""; set c(6nick) ""; set c(6netw) ""; set c(6brac) ""; set c(6slsh) ""; set c(6x) ""; } #// Parts if {$thecolors(part) == 1 && $thecolors(master) == 1} { set c(7part) "\00310"; #// Dark Cyan - "Quit" set c(7chan) "\00303"; #// Dark Green - Channel set c(7nick) "\00310"; #// Dark Cyan - Nickname set c(7netw) "\00310"; #// Dark Cyan - Network set c(7slsh) "\00314"; #// Dark Grey - Forward Slash set c(7x) "\003"; #// Color Terminator } else { set c(7part) ""; set c(7chan) ""; set c(7nick) ""; set c(7netw) ""; set c(7slsh) ""; set c(7x) ""; } #// Topic Changes if {$thecolors(topc) == 1 && $thecolors(master) == 1} { set c(8topc) "\00310"; #// Dark Cyan - "Topic" set c(8netw) "\00310"; #// Dark Cyan - Network set c(8nick) "\00303"; #// Dark Green - Nickname set c(8slsh) "\00314"; #// Dark Grey - Forward Slash set c(8x) "\003"; #// Color Terminator } else { set c(8topc) ""; set c(8netw) ""; set c(8nick) ""; set c(8slsh) ""; set c(8x) ""; } #// Kicks if {$thecolors(kick) == 1 && $thecolors(master) == 1} { set c(9kick) "\00310"; #// Dark Cyan - "Kick" set c(9netw) "\00310"; #// Dark Cyan - Network set c(9nick) "\00303"; #// Dark Green - Nickname that Kicked set c(9vict) "\00306"; #// Dark Purple - Victim that was Kicked set c(9brac) "\00314"; #// Dark Grey - Square Brackets set c(9slsh) "\00314"; #// Dark Grey - Forward Slash set c(9x) "\003"; #// Color Terminator } else { set c(9kick) ""; set c(9netw) ""; set c(9nick) ""; set c(9vict) ""; set c(9brac) ""; set c(9slsh) ""; set c(9x) ""; } #// Bans/Exempts/Invites if {$thecolors(ban) == 1 && $thecolors(master) == 1} { set c(10type) "\00310"; #// Dark Cyan - "Ban/Except/Invite" set c(10netw) "\00310"; #// Dark Cyan - Network set c(10mask) "\00303"; #// Dark Green - Hostmask set c(10slsh) "\00314"; #// Dark Grey - Forward Slash set c(10x) "\003"; #// Color Terminator } else { set c(10type) ""; set c(10netw) ""; set c(10mask) ""; set c(10slsh) ""; set c(10x) ""; } #// Netsplits if {$thecolors(splt) == 1 && $thecolors(master) == 1} { set c(11splt) "\00310"; #// Dark Cyan - "Netsplit" set c(11netw) "\00310"; #// Dark Cyan - Network set c(11nick) "\00303"; #// Dark Green - Nickname set c(11slsh) "\00314"; #// Dark Grey - Forward Slash set c(11x) "\003"; #// Color Terminator } else { set c(11splt) ""; set c(11netw) ""; set c(11nick) ""; set c(11slsh) ""; set c(11x) ""; } #// Netmerges if {$thecolors(rejn) == 1 && $thecolors(master) == 1} { set c(12rejn) "\00310"; #// Dark Cyan - "Netmerge" set c(12netw) "\00310"; #// Dark Cyan - Network set c(12nick) "\00303"; #// Dark Green - Nickname set c(12slsh) "\00314"; #// Dark Grey - Forward Slash set c(12x) "\003"; #// Color Terminator } else { set c(12rejn) ""; set c(12netw) ""; set c(12nick) ""; set c(12slsh) ""; set c(12x) ""; } #// Botnet Links if {$thecolors(link) == 1 && $thecolors(master) == 1} { set c(13link) "\00310"; #// Dark Cyan - "Linked Bot" set c(13netw) "\00303"; #// Dark Cyan - Network set c(13abot) "\00303"; #// Dark Green - Bot set c(13atch) "\00314"; #// Dark Grey - '@' Character set c(13x) "\003"; #// Color Terminator } else { set c(13link) ""; set c(13netw) ""; set c(13abot) ""; set c(13atch) ""; set c(13x) ""; } #// Botnet Disconnects if {$thecolors(disc) == 1 && $thecolors(master) == 1} { set c(14disc) "\00310"; #// Dark Cyan - "Lost bot" set c(14netw) "\00303"; #// Dark Cyan - Network set c(14abot) "\00303"; #// Dark Green - Bot set c(14atch) "\00314"; #// Dark Grey - '@' Character set c(14x) "\003"; #// Color Terminator } else { set c(14disc) ""; set c(14netw) ""; set c(14abot) ""; set c(14atch) ""; set c(14x) ""; } #// !names Output if {$thecolors(names) == 1 && $thecolors(master) == 1} { set c(15chan) "\00310"; #// Dark Cyan - Channel set c(15netw) "\00310"; #// Dark Cyan - Network set c(15___o) "\00307"; #// Orange - "@" Symbol (Op) set c(15___h) "\00303"; #// Dark Green - "%" Symbol (Halfop) set c(15___v) "\00306"; #// Dark Purple - "+" Symbol (Voice) set c(15numA) "\00303"; #// Dark Green - User Number Range A set c(15numB) "\00303"; #// Dark Green - User Number Range B set c(15totl) "\00310"; #// Dark Cyan - User Total set c(15atch) "\00314"; #// Dark Grey - '@' Character set c(15x) "\003"; #// Color Terminator } else { set c(15chan) ""; set c(15netw) ""; set c(15___o) ""; set c(15___h) ""; set c(15___v) ""; set c(15numA) ""; set c(15numB) ""; set c(15totl) ""; set c(15atch) ""; set c(15x) ""; } #// Privmsg Output if {$thecolors(privmsg) == 1 && $thecolors(master) == 1} { set c(16brac) "\00314"; #// Dark Grey - Angle Brackets set c(16nick) ""; #// No Color - Nickname set c(16netw) ""; #// No Color - Network set c(16atch) "\00314"; #// Dark Grey - '@' Character set c(16x) "\003"; #// Color Terminator } else { set c(16brac) ""; set c(16nick) ""; set c(16netw) ""; set c(16atch) ""; set c(16x) ""; } #// !gettopic Output if {$thecolors(help) == 1 && $thecolors(master) == 1} { set c(17chan) "\00310"; #// Dark Cyan - Channel set c(17netw) "\00310"; #// Dark Cyan - Network set c(17topc) "\00303"; #// Dark Green - Topic set c(17atch) "\00314"; #// Dark Grey - '@' Character set c(17x) "\003"; #// Color Terminator } else { set c(17chan) ""; set c(17netw) ""; set c(17topc) ""; set c(17atch) ""; set c(17x) ""; } #// !help Output if {$thecolors(help) == 1 && $thecolors(master) == 1} { set c(18help) "\00303"; #// Dark Green - !help Options set c(18cmds) "\00310"; #// Dark Cyan - Commands set c(18args) "\00303"; #// Dark Green - Command Parameters set c(18home) "\00307"; #// Orange - "Home" Network in !help network set c(18x) "\003"; #// Color Terminator } else { set c(18help) ""; set c(18cmds) ""; set c(18args) ""; set c(18home) ""; set c(18x) ""; } } } #//-------------------------------------------------------------------------------------------------------------- #// --- Reset Binds --- #// Based upon the configured options, bind or unbind certain events proc set_binds {} { global theopts #// Misc Binds if {$theopts(master) == 1} { bind bot - rlycmd recv_cmd bind raw - MODE send_mode } else { set tmpbit [bind bot - rlycmd] if {$tmpbit != ""} { if {[string first "recv_cmd" $tmpbit] > -1} { unbind bot - rlycmd recv_cmd unbind raw - MODE send_mode } } } #// Public Chatter if {$theopts(show_pubm) == 1 && $theopts(master) == 1} { bind pubm - * send_pubm bind bot - pubm recv_pubm } else { set tmpbit [bind pubm - *] if {$tmpbit != ""} { if {[string first "send_pubm" $tmpbit] > -1} { unbind pubm - * send_pubm unbind bot - pubm recv_pubm } } } #// Actions if {$theopts(show_act) == 1 && $theopts(master) == 1} { bind ctcp - "ACTION" send_actn bind bot - act recv_actn } else { set tmpbit [bind ctcp - "ACTION"] if {$tmpbit != ""} { if {[string first "send_actn" $tmpbit] > -1} { unbind ctcp - "ACTION" send_actn unbind bot - act recv_actn } } } #// Nick Changes if {$theopts(show_nick) == 1 && $theopts(master) == 1} { bind nick - * send_nick bind bot - nick recv_nick } else { set tmpbit [bind nick - *] if {$tmpbit != ""} { if {[string first "send_nick" $tmpbit] > -1} { unbind nick - * send_nick unbind bot - nick recv_nick } } } #// Status Changes if {$theopts(show_statchg) == 1 && $theopts(master) == 1} { bind bot - statchg recv_statchg } else { set tmpbit [bind bot - statchg] if {$tmpbit != ""} { if {[string first "recv_statchg" $tmpbit] > -1} { unbind bot - statchg recv_statchg } } } #// Joins if {$theopts(show_join) == 1 && $theopts(master) == 1} { bind join - * send_join bind bot - join recv_join } else { set tmpbit [bind join - *] if {$tmpbit != ""} { if {[string first "send_join" $tmpbit] > -1} { unbind join - * send_join unbind bot - join recv_join } } } #// Signoffs/Quits if {$theopts(show_sign) == 1 && $theopts(master) == 1} { bind sign - * send_sign bind bot - sign recv_sign } else { set tmpbit [bind sign - *] if {$tmpbit != ""} { if {[string first "send_sign" $tmpbit] > -1} { unbind sign - * send_sign unbind bot - sign recv_sign } } } #// Parts if {$theopts(show_part) == 1 && $theopts(master) == 1} { bind part - * send_part bind bot - part recv_part } else { set tmpbit [bind part - *] if {$tmpbit != ""} { if {[string first "send_part" $tmpbit] > -1} { unbind part - * send_part unbind bot - part recv_part } } } #// Topic Changes if {$theopts(show_topc) == 1 && $theopts(master) == 1} { bind topc - * send_topc bind bot - topc recv_topc } else { set tmpbit [bind topc - *] if {$tmpbit != ""} { if {[string first "send_topc" $tmpbit] > -1} { unbind topc - * send_topc unbind bot - topc recv_topc } } } #// Kicks if {$theopts(show_kick) == 1 && $theopts(master) == 1} { bind kick - * send_kick bind bot - kick recv_kick } else { set tmpbit [bind kick - *] if {$tmpbit != ""} { if {[string first "send_kick" $tmpbit] > -1} { unbind kick - * send_kick unbind bot - kick recv_kick } } } #// Bans if {$theopts(show_ban) == 1 && $theopts(master) == 1} { bind bot - ban recv_ban } else { set tmpbit [bind bot - ban] if {$tmpbit != ""} { if {[string first "recv_ban" $tmpbit] > -1} { unbind bot - ban recv_ban } } } #// Netsplits if {$theopts(show_splt) == 1 && $theopts(master) == 1} { bind splt - * send_splt bind bot - splt recv_splt } else { set tmpbit [bind splt - *] if {$tmpbit != ""} { if {[string first "send_splt" $tmpbit] > -1} { unbind splt - * send_splt unbind bot - splt recv_splt } } } #// Netmerges if {$theopts(show_rejn) == 1 && $theopts(master) == 1} { bind rejn - * send_rejn bind bot - rejn recv_rejn } else { set tmpbit [bind rejn - *] if {$tmpbit != ""} { if {[string first "send_rejn" $tmpbit] > -1} { unbind rejn - * send_rejn unbind bot - rejn recv_rejn } } } #// Botnet Links if {$theopts(show_link) == 1 && $theopts(master) == 1} { bind link - * recv_link } else { set tmpbit [bind link - *] if {$tmpbit != ""} { if {[string first "recv_link" $tmpbit] > -1} { unbind link - * recv_link } } } #// Botnet Disconnects if {$theopts(show_disc) == 1 && $theopts(master) == 1} { bind disc - * recv_disc } else { set tmpbit [bind disc - *] if {$tmpbit != ""} { if {[string first "recv_disc" $tmpbit] > -1} { unbind disc - * recv_disc } } } #// !names if {$theopts(allow_names) == 1 && $theopts(master) == 1} { bind pub - !names pub_getnames bind msg - !names msg_getnames bind bot - names send_names bind bot - snames recv_names } else { set tmpbit [bind pub - !names] if {$tmpbit != ""} { if {[string first "pub_getnames" $tmpbit] > -1} { unbind pub - !names pub_getnames unbind msg - !names msg_getnames unbind bot - names send_names unbind bot - snames recv_names } } } #// Inter-relay PRIVMSGes if {$theopts(allow_privmsg) == 1 && $theopts(master) == 1} { bind msgm - "*@*" send_msg bind bot - "sprivmsg" recv_msg bind msg - !reply send_replymsg } else { set tmpbit [bind msgm - "*@*"] if {$tmpbit != ""} { if {[string first "send_msg" $tmpbit] > -1} { unbind msgm - "*@*" send_msg unbind bot - "sprivmsg" recv_msg unbind msg - !reply send_replymsg } } } #// !gettopic if {$theopts(allow_gettopic) == 1 && $theopts(master) == 1} { bind pub - !gettopic pub_gettopic bind msg - !gettopic msg_gettopic bind bot - "gettopic" send_gettopic bind bot - "sgettopic" recv_gettopic } else { set tmpbit [bind pub - !gettopic] if {$tmpbit != ""} { if {[string first "pub_gettopic" $tmpbit] > -1} { unbind pub - !gettopic pub_gettopic unbind msg - !gettopic msg_gettopic unbind bot - "gettopic" send_gettopic unbind bot - "sgettopic" recv_gettopic } } } #// !kick if {$theopts(enable_cmdkick) == 1 && $theopts(master) == 1} { bind msg - !kick send_msgkick bind pub - !kick send_pubkick } else { set tmpbit [bind msg - !kick] if {$tmpbit != ""} { if {[string first "send_msgkick" $tmpbit] > -1} { unbind msg - !kick send_msgkick unbind pub - !kick send_pubkick } } } #// !kickban if {$theopts(enable_cmdkickban) == 1 && $theopts(master) == 1} { bind msg - !kickban send_msgkickban bind pub - !kickban send_pubkickban } else { set tmpbit [bind msg - !kickban] if {$tmpbit != ""} { if {[string first "send_msgkickban" $tmpbit] > -1} { unbind msg - !kickban send_msgkickban unbind pub - !kickban send_pubkickban } } } #// !op/!deop if {$theopts(enable_cmdops) == 1 && $theopts(master) == 1} { bind msg - !op send_msgop bind msg - !deop send_msgdeop bind pub - !op send_pubop bind pub - !deop send_pubdeop } else { set tmpbit [bind msg - !op] if {$tmpbit != ""} { if {[string first "send_msgop" $tmpbit] > -1} { unbind msg - !op send_msgop unbind msg - !deop send_msgdeop unbind pub - !op send_pubop unbind pub - !deop send_pubdeop } } } #// !voice/!devoice if {$theopts(enable_cmdvoices) == 1 && $theopts(master) == 1} { bind msg - !voice send_msgvoice bind msg - !devoice send_msgdevoice bind pub - !voice send_pubvoice bind pub - !devoice send_pubdevoice } else { set tmpbit [bind msg - !voice] if {$tmpbit != ""} { if {[string first "send_msgvoice" $tmpbit] > -1} { unbind msg - !voice send_msgvoice unbind msg - !devoice send_msgdevoice unbind pub - !voice send_pubvoice unbind pub - !devoice send_pubdevoice } } } #// !halfop/!dehalfop if {$theopts(enable_cmdhalfops) == 1 && $theopts(master) == 1} { bind msg - !halfop send_msghalfop bind msg - !dehalfop send_msgdehalfop bind pub - !halfop send_pubhalfop bind pub - !dehalfop send_pubdehalfop } else { set tmpbit [bind msg - !halfop] if {$tmpbit != ""} { if {[string first "send_msghalfop" $tmpbit] > -1} { unbind msg - !halfop send_msghalfop unbind msg - !dehalfop send_msgdehalfop unbind pub - !halfop send_pubhalfop unbind pub - !dehalfop send_pubdehalfop } } } #// !mode if {$theopts(enable_cmdmode) == 1 && $theopts(master) == 1} { bind msg - !mode send_msgmode bind pub - !mode send_pubmode } else { set tmpbit [bind msg - !mode] if {$tmpbit != ""} { if {[string first "send_msgmode" $tmpbit] > -1} { unbind msg - !mode send_msgmode unbind pub - !mode send_pubmode } } } #// !topic if {$theopts(enable_cmdmode) == 1 && $theopts(master) == 1} { bind msg - !topic send_msgtopc bind pub - !topic send_pubtopc } else { set tmpbit [bind msg - !topic] if {$tmpbit != ""} { if {[string first "send_msgtopc" $tmpbit] > -1} { unbind msg - !topic send_msgtopc unbind pub - !topic send_pubtopc } } } #// !help if {$theopts(enable_cmdhelp) == 1 && $theopts(master) == 1} { bind msg - !help send_msghelp bind pub - !help send_pubhelp } else { set tmpbit [bind msg - !help] if {$tmpbit != ""} { if {[string first "send_msghelp" $tmpbit] > -1} { unbind msg - !help send_msghelp unbind pub - !help send_pubhelp } } } #// !hurt && !heal if {$theopts(enable_cmdhurt) == 1 && $theopts(master) == 1} { bind pub - !hurt send_pubhurt bind pub - !heal send_pubheal bind msg - !hurt send_msghurt bind msg - !heal send_msgheal bind bot - hurt recv_hurt bind bot - heal recv_heal } else { set tmpbit [bind pub - !hurt] if {$tmpbit != ""} { if {[string first "send_pubhurt" $tmpbit] > -1} { unbind pub - !hurt send_pubhurt unbind pub - !heal send_pubheal unbind msg - !hurt send_msghurt unbind msg - !heal send_msgheal unbind bot - hurt recv_hurt unbind bot - heal recv_heal } } } #// !rehash if {$theopts(enable_cmdrestart) == 1} { bind pub n !rehash pub_rehash bind msg n !rehash msg_rehash bind bot - botrehash recv_rehash } else { set tmpbit [bind pub n !rehash] if {$tmpbit != ""} { if {[string first "pub_rehash" $tmpbit] > -1} { unbind pub n !rehash pub_rehash unbind msg n !rehash msg_rehash unbind bot - botrehash recv_rehash } } } #// !restart if {$theopts(enable_cmdrehash) == 1} { bind pub n !restart pub_restart bind msg n !restart msg_restart bind bot - botrestart recv_restart } else { set tmpbit [bind pub n !restart] if {$tmpbit != ""} { if {[string first "pub_restart" $tmpbit] > -1} { unbind pub n !restart pub_restart unbind msg n !restart msg_restart unbind bot - botrestart recv_restart } } } #// !shutdown if {$theopts(enable_cmdshutdown) == 1} { bind pub n !shutdown pub_shutdown bind msg n !shutdown msg_shutdown bind bot - botshutdown recv_shutdown } else { set tmpbit [bind pub n !shutdown] if {$tmpbit != ""} { if {[string first "pub_shutdown" $tmpbit] > -1} { unbind pub n !shutdown pub_shutdown unbind msg n !shutdown msg_shutdown unbind bot - botshutdown recv_shutdown } } } return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Startup Code --- #// Clear the Global Variables (If They Exist) if {[info exists spltbuf] == 1} {array unset spltbuf} if {[info exists rejnbuf] == 1} {array unset rejnbuf} if {[info exists linkbuf] == 1} {array unset linkbuf} if {[info exists discbuf] == 1} {array unset discbuf} if {[info exists hurtbuf] == 1} {array unset hurtbuf} if {[info exists replybuf] == 1} {array unset replybuf} if {[info exists c] == 1} {array unset c} #// Initialize our Global Variables set spltbuf(init) "donotremoveme" set rejnbuf(init) "donotremoveme" set linkbuf(init) "donotremoveme" set discbuf(init) "donotremoveme" set hurtbuf(init) "donotremoveme" set replybuf(init) "donotremoveme" #// Fix our binds set_binds #// Configure Colors configure_colors #// Some people cannot follow directions at times. This prevents such people from screwing the script up set therelay(channels) [string tolower $therelay(channels)] #//-------------------------------------------------------------------------------------------------------------- #// --- Message Handler --- #// Receives Events from Bots on the Botnet, and sends out Responses proc send_across {cmd chan nick text} { global therelay #// Make Sure the Channel we're relaying is specified if {[lsearch $therelay(channels) [string tolower $chan]] != -1} { #// Prepare and send a message to All Bots containing the data to display set botMsg [concat $cmd $chan $therelay(ournet) $nick $text] putallbots $botMsg } } #//-------------------------------------------------------------------------------------------------------------- #// --- Hurt Checker --- #// Checks to see if a user's uhost is in $hurtbuf proc is_hurt {uhost} { global hurtbuf #// Are they in $hurtbuf? if {[info exists hurtbuf] == 1} { set tmpnames [array names hurtbuf] foreach tmpbit $tmpnames { #// If we have _one_ match, break out and flag that this user is silenced if {[string match -nocase $tmpbit $uhost] == 1} { return 1 } } } return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Public Chatter --- #// Send all normal chatroom talk ("pubm" event) proc send_pubm {nick uhost hand chan text} { global theopts #// See if a user is "Hurt" if {[is_hurt $uhost] == 1} { putquick "NOTICE $nick :You have been silenced on the relay. Please talk to an Operator for further information." return 0 } #// If the first character is a !, and theopts(enable_echocmd) is no, then block our command binds if {([string index $text 0] == "!") && ($theopts(enable_echocmd) == 0)} { switch -exact -- [lindex [split $text] 0] { !names - !gettopic - !kick - !kickban - !op - !deop - !voice - !devoice - !halfop - !dehalfop - !mode - !topic - !help - !hurt - !heal - !rehash - !restart - !shutdown { return 0 } } } #// Send the Chatter send_across "pubm" $chan $nick $text return 0 } #// Receive and display all normal chatroom talk ("pubm" event) proc recv_pubm {frm_bot command arg} { global theopts c set arg [split $arg] set thechan [lindex $arg 0] set thenetw "$c(1netw)[lindex $arg 1]$c(1x)" set thenick "$c(1nick)[lindex $arg 2]$c(1x)" set thetext [strip_codes [join [lrange $arg 3 end]]] putquick "PRIVMSG $thechan :$thenetw: $c(1brac)\<$c(1x)$thenick$c(1brac)\>$c(1x) $thetext" return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Actions --- #// Send all Actions ("act" event) proc send_actn {nick uhost hand chan keyw text} { #// See if a user is "Hurt" if {[is_hurt $uhost] == 1} { putquick "NOTICE $nick :You have been silenced on the relay. Please talk to an Operator for further information." return 0 } #// Send the Action send_across "act" $chan $nick $text return 0 } #// Process and display all Actions ("act" event) proc recv_actn {frm_bot command arg} { global theopts c set arg [split $arg] set thechan [lindex $arg 0] set thenetw "$c(2netw)[lindex $arg 1]$c(2x)" set thenick "$c(2nick)[lindex $arg 2]$c(2x)" set theactn [strip_codes [join [lrange $arg 3 end]]] putquick "PRIVMSG $thechan :$thenetw: $c(2star)\*$c(2x) $thenick $theactn" return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Nickname Changes --- #// Send a "nick" event to the Botnet proc send_nick {nick uhost hand chan newnick} { global replybuf #// See if a User is "Hurt" (Blocks showing of nickname incase users tries to "nicktalk" if {[is_hurt $uhost] != 1} { send_across "nick" $chan $nick $newnick } #// Update the reply buffer (if one exists) to reflect the new nick!ident@host (PrivMsg Feature) if {[info exists replybuf($nick\!$uhost)] != 0} { set replybuf($newnick\!$uhost) $replybuf($nick\!$uhost) unset replybuf($nick\!$uhost) } return 0 } #// Print the nickchange from the sending network proc recv_nick {frm_bot command arg} { global therelay replybuf c set arg [split $arg] set thechan [lindex $arg 0] set thenetw [lindex $arg 1] set thenick [lindex $arg 2] set newnick [join [lrange $arg 3 end]] putquick "PRIVMSG $thechan :$therelay(prefix)$c(3nick)Nick$c(3x)$c(3slsh)\/$c(3x)$c(3netw)$thenetw$c(3x): $c(3oldn)$thenick$c(3x) is now known as $c(3newn)$newnick$c(3x)" #// Update the reply buffer (if one exists) to reflect the new user's nickname (PrivMsg Feature) set tmplist [split [array get replybuf]] set tmplen [llength $tmplist] if {$tmplen != 0} { for {set xCtr 2} {$xCtr < $tmplen} {incr xCtr 2} { set tmpuhost [lindex [split $tmplist] $xCtr] set tmpval $replybuf($tmpuhost) if {$tmpval == "$thenick\@$thenetw"} { set replybuf($tmpuhost) "$newnick\@$thenetw" } } } return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Mode Changes --- #// Send either a "ban" event for +beI/-beI, or a "statchg" event for othermodes/multiple modes proc send_mode {from keyword text} { set text [split $text] set thenick [lindex [split [split $from !]] 0] set thechan [lindex $text 0] set themode [lindex $text 1] set victims [join [lrange $text 2 end]] #// If the length of $themode is '2' (+/- and b/e/I), then see if this is a Ban/Unban/Except/Invite if {[string length $themode] == 2} { switch -exact -- [string range $themode 1 1] { b - e - I { send_across "ban" $thechan $thenick "$themode $victims" return 0 } } } #// If it's more than one ban, or anything else, just show it send_across "statchg" $thechan $thenick [concat $themode $victims] return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Status Changes --- #// Process a "statchg" event proc recv_statchg {frm_bot command arg} { global therelay c set arg [split $arg] set thechan [lindex $arg 0] set thenetw "$c(4netw)[lindex $arg 1]$c(4x)" set bywhom "$c(4nick)[lindex $arg 2]$c(4x)" set themode "$c(4brac)\[$c(4x)[lindex $arg 3]" set victims "[join [lrange $arg 4 end]]$c(4brac)\]$c(4x)" putquick "PRIVMSG $thechan :$therelay(prefix)$c(4mode)Mode$c(4x)$c(4slsh)\/$c(4x)$thenetw: $themode $victims by $bywhom" return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Joins --- #// Send a "join" event proc send_join {nick uhost hand chan} { send_across "join" $chan $nick $uhost return 0 } #// Process a "join" event proc recv_join {frm_bot command arg} { global therelay c set arg [split $arg] set thechan "[lindex $arg 0]" set thenetw "$c(5netw)[lindex $arg 1]$c(5x)" set thenick "$c(5nick)[lindex $arg 2]$c(5x)" set thehost "$c(5brac)\[$c(5x)$c(5host)[lindex $arg 3]$c(5x)$c(5brac)\]$c(5x)" putquick "PRIVMSG $thechan :$therelay(prefix)$c(5join)Join$c(5x)$c(5slsh)\/$c(5x)$c(5netw)$thenetw$c(5x): $c(5nick)$thenick$c(5x) $thehost has joined the channel" return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Quit/Signoffs --- #// Send a "sign" event (a quit) proc send_sign {nick uhost hand chan reason} { global theopts replybuf #// See if a user is "Hurt" (Masks Quit Message with canned message) if {[is_hurt $uhost] == 1} { set reason "This user has been silenced. Quit message not shown." } #// Do we want to show a user's quit message or not? if {$theopts(show_quitmsg) != 1} { set reason "" } #// Send the Quit notice send_across "sign" $chan $nick $reason #// If the user had an entry in the reply buffer for privmsgs, remove it if {[info exists replybuf($nick\!$uhost)] != 0} { unset replybuf($nick\!$uhost) } return 0 } #// Process a "sign" event (a quit) proc recv_sign {frm_bot command arg} { global therelay theopts replybuf c set arg [split $arg] set thechan [lindex $arg 0] set thenetw [lindex $arg 1] set thenick [lindex $arg 2] set thereason "$c(6brac)\($c(6x)[strip_codes [join [lrange $arg 3 end]]]$c(6brac)\)$c(6x)" #// Check quit message length - don't print anything if 0 if {[string length $thereason] == 0} { set thereason "" } #// Send to IRC putquick "PRIVMSG $thechan :$therelay(prefix)$c(6sign)Quit$c(6x)$c(6slsh)\/$c(6x)$c(6netw)$thenetw$c(6x): $c(6nick)$thenick$c(6x) $thereason" #// If any values in the reply buffer match the nickname that quit, remove them set tmpnames [array names replybuf] foreach tmpbit $tmpnames { if {$replybuf($tmpbit) == "$thenick\@$thenetw"} { unset $replybuf($tmpbit) } } return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Parts --- #// Send a "part" event proc send_part {nick uhost hand chan arg} { global therelay send_across "part" $chan $nick "dummy" #// See if the user is still in any channels relayed, if not, assume a quit, and delete the entry if {[info exists replybuf($nick\!$uhost)] != 0} { foreach tmpchan $therelay(channels) { if {[onchan $nick $tmpchan] == 1} {return 0} } unset replybuf($nick\!$uhost) } return 0 } #// Process a "part" event proc recv_part {frm_bot command arg} { global therelay c set arg [split $arg] set thechan [lindex $arg 0] set thenetw [lindex $arg 1] set thenick [lindex $arg 2] putquick "PRIVMSG $thechan :$therelay(prefix)$c(7part)Part$c(7x)$c(7slsh)\/$c(7x)$c(7netw)$thenetw$c(7x): $c(7nick)$thenick$c(7x) has left the channel" return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Topics --- #// Send a "topc" event proc send_topc {nick uhost hand chan topic} { send_across "topc" $chan $nick $topic return 0 } #// Process a "topc" event proc recv_topc {frm_bot command arg} { global therelay c set arg [split $arg] set thechan [lindex $arg 0] set thenetw "$c(8netw)[lindex $arg 1]$c(8x)" set thenick [lindex $arg 2] set thetopc [join [lrange $arg 3 end]] #// If the bot is just Joining the channel, Don't send the Topic out ($thenick will == "*") if {$thenick != "*"} { putquick "PRIVMSG $thechan :$therelay(prefix)$c(8topc)Topic$c(8x)$c(8slsh)\/$c(8x)$thenetw: $thetopc \(Set by $c(8nick)$thenick$c(8x)\)" } return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Kicking --- #// Send a "kick" event proc send_kick {nick uhost hand chan target reason} { global botnick append target " $reason" send_across "kick" $chan $nick $target return 0 } #// Process a "kick" event proc recv_kick {frm_bot command arg} { global therelay c set arg [split $arg] set thechan [lindex $arg 0] set thenetw "$c(9netw)[lindex $arg 1]$c(9x)" set thenick "$c(9nick)[lindex $arg 2]$c(9x)" set thevictim "$c(9vict)[lindex $arg 3]$c(9x)" set thereason "$c(9brac)\[$c(9x)[strip_codes [join [lrange $arg 4 end]]]$c(9brac)\]$c(9x)" #// Show the Kick putquick "PRIVMSG $thechan :$therelay(prefix)$c(9kick)Kick$c(9x)$c(9slsh)\/$c(9x)$thenetw: $thevictim by $thenick $thereason" return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Single Bans/Excepts/Invites --- #// Process a "ban" event proc recv_ban {frm_bot command arg} { global therelay theopts c set arg [split $arg] set thechan [lindex $arg 0] set thenetw "$c(10netw)[lindex $arg 1]$c(10x)" set themode [lindex $arg 3] set themask "$c(10mask)[lindex $arg 4]$c(10x)" set bit [string range $themode 0 0] set type [string range $themode 1 1] set newheader "$therelay(prefix)$c(10type)New " set remheader "$therelay(prefix)$c(10type)Removed " set theslash "$c(10x)$c(10slsh)\/$c(10x)" #// Ban, Exception, or Invite? switch -exact -- $type { b { #// Is the Ban New, or being Removed? switch -exact -- $bit { + {putquick "PRIVMSG $thechan :$newheader\Ban$theslash$thenetw: $themask"} - {putquick "PRIVMSG $thechan :$remheader\Ban$theslash$thenetw: $themask"} } return 0 } e { #// Is the Exception New or being Removed? switch -exact -- $bit { + {putquick "PRIVMSG $thechan :$newheader\Exception$theslash$thenetw: $themask"} - {putquick "PRIVMSG $thechan :$remheader\Exception$theslash$thenetw: $themask"} } return 0 } I { #// Is the Invite New, or being Removed? switch -exact -- $bit { + {putquick "PRIVMSG $thechan :$newheader\Invite$theslash$thenetw: $themask"} - {putquick "PRIVMSG $thechan :$remheader\Invite$theslash$thenetw: $themask"} } return 0 } } return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Netsplits/Netmerges --- #// Report Netsplit/Netmerges proc splt-rejn_report {type cnum} { global c therelay theopts ${type}buf #// Prep Colors set clr(1) $c(${cnum}${type}) set clr(2) $c(${cnum}slsh) set clr(3) $c(${cnum}netw) set clr(4) $c(${cnum}nick) set clr(x) $c(${cnum}x) #// What Array are we using? switch -exact -- $type { splt {set chantxt "$therelay(prefix)$clr(1)Netsplit$clr(x)$clr(2)\/$clr(x)"} rejn {set chantxt "$therelay(prefix)$clr(1)Netmerge$clr(x)$clr(2)\/$clr(x)"} } set tmpnames [array names ${type}buf] set tmplen [llength $tmpnames] #// Provided we actually have data to work with... if {$tmplen > 1} { set thelist "" #// Loop through the Array... foreach tmpbit $tmpnames { if {$tmpbit != "init"} { set thenetw [lindex [split $tmpbit @] 0] set thechan [lindex [split $tmpbit @] 1] #// Get data in $spltbuf, or $rejnbuf set thedata [set ${type}buf($tmpbit)] set datalen [llength $thedata] #// Determine if there are too many nicknames to display in a single line if {$datalen > $theopts(max_spltrejn)} { for {set xStart 0} {$xStart < $datalen} {incr xStart $theopts(max_spltrejn)} { set xEnd [expr $xStart + $theopts(max_spltrejn)] set tmplist [join [lrange $thedata $xStart [expr $xEnd - 1]]] if {$xEnd > $datalen} {set xEnd $datalen} putquick "PRIVMSG $thechan :$chantxt$clr(3)$thenetw$clr(x): $clr(4)$tmplist$clr(x)" } } else { putquick "PRIVMSG $thechan :$chantxt$clr(3)$thenetw$clr(x): $clr(4)$thedata$clr(x)" } } } #// Clear out whatever array we used foreach tmpbit $tmpnames { if {$tmpbit != "init"} {unset ${type}buf($tmpbit)} } } return 0 } #// Take the given where/who && type, and record it to the appropriate global array proc splt-rejn_record {where who type cnum} { global ${type}buf #// If the size of the array is < 1, do nothing (Shouldn't happen, but....) #// If the size of the array == 1, then record the event, and start a timer (15 Seconds) #// if the size of the array is > 1, then just record the event, as the timer is already started if {[array size ${type}buf] < 1} { return 0 } elseif {[array size ${type}buf] == 1} { set thechan [lindex [split $where @] 1] set ${type}buf($where) $who utimer 10 [split "splt-rejn_report $type $cnum"] } elseif {[array size ${type}buf] > 1} { set ${type}buf($where) [concat [set ${type}buf($where)] $who] } return 0 } #// Send a "splt" event (Netsplit) proc send_splt {nick uhost hand chan} { send_across "splt" $chan $nick "dummy" return 0 } #// Process a "splt" event (Netsplit) proc recv_splt {frm_bot command arg} { global c set arg [split $arg] set thechan [lindex $arg 0] set thenetw [lindex $arg 1] set thenick [lindex $arg 2] splt-rejn_record "$thenetw\@$thechan" $thenick "splt" "11" return 0 } #// Send a "rejn" event (Netmerge) proc send_rejn {nick uhost hand chan} { send_across "rejn" $chan $nick "dummy" return 0 } #// Process a "rejn" event (Netmerge) proc recv_rejn {frm_bot command arg} { global c set arg [split $arg] set thechan [lindex $arg 0] set thenetw [lindex $arg 1] set thenick [lindex $arg 2] splt-rejn_record "$thenetw\@$thechan" $thenick "rejn" "12" return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Botnet Links/Disconnects --- #// Process a "link" event proc recv_link {botname via} { global c link-disc_record $botname "link" $c(13abot) $c(13netw) $c(13atch) $c(13x) return 0 } #// Process a "disc" event proc recv_disc {botname} { global c link-disc_record $botname "disc" $c(14abot) $c(14netw) $c(14atch) $c(14x) return 0 } #// Take the given botnick, type, & any colors and record it to the appropriate global array proc link-disc_record {botname type c1 c2 c3 cx} { global therelay ${type}buf #// Used a chopped up rand() as our element name set bit [string range [string trimleft [expr rand()] "0."] 0 4] #// Figure out IRC Nick/Network of the other bot(s) set botpos [lsearch -exact $therelay(botnet) $botname] if {$botpos != -1} { set othbotn [lindex [split $therelay(botirc)] $botpos] set thenetw [lindex [split $therelay(netwrk)] $botpos] #// If the size of the array is < 1, do nothing (Shouldn't happen, but....) #// If the size of the array == 1, then record the bot, and start a timer #// if the size of the array is > 1, then just record the bot, as the timer is already started if {[array size ${type}buf] < 1} { return 0 } elseif {[array size ${type}buf] == 1} { set ${type}buf($bit) "$c1$othbotn$cx$c3\@$cx$c2$thenetw$cx" utimer 5 "link-disc_report $type" } elseif {[array size ${type}buf] > 1} { set ${type}buf($bit) "$c1$othbotn$cx$c3\@$cx$c2$thenetw$cx" } } return 0 } proc link-disc_report {type} { global therelay ${type}buf c #// What Array are we using? switch -exact -- $type { link {set chantxt "$therelay(prefix)$c(13link)Linked Bot\(s\)$c(13x):"} disc {set chantxt "$therelay(prefix)$c(14disc)Lost Bot\(s\)$c(14x):"} } set tmplist [split [array get ${type}buf]] set tmplen [llength $tmplist] #// Provided we actually have data to work with... if {$tmplen > 2} { set thelist "" #// Fetch only the values of the array (Not the names) for {set xCtr 1} {$xCtr < $tmplen} {incr xCtr 2} { set tmpbit [lindex [split $tmplist] $xCtr] if {$tmpbit != "donotremoveme"} { set thelist [concat $thelist $tmpbit] } } #// Print the results to all chanels foreach thechan $therelay(channels) { putquick "PRIVMSG $thechan :$chantxt $thelist" } #// Clear out whatever array we used set tmplist [array names ${type}buf] foreach tmpbit $tmplist { if {$tmpbit != "init"} {unset ${type}buf($tmpbit)} } } return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- !names Procedures --- #// Sends a "names" request to the Botnet (Public) proc pub_getnames {nick uhost hand chan arg} { global theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!names"} send_across "names" $chan $nick "dummy" return 0 } #// Sends a "names" request to the Botnet (Privmsg) proc msg_getnames {nick uhost hand arg} { global therelay set thechan [lindex [split $arg] 0] #// Valid Channel Type? switch -exact -- [string range $thechan 0 0] { # - & - + - ! {} default { putserv "PRIVMSG $nick :Invalid Channel. Use one of the following: $therelay(channels)" return 0 } } #// Valid Channel listed in $therelay(channels)? if {[lsearch -exact $therelay(channels) [string tolower $thechan]] == -1} { putserv "PRIVMSG $nick :Invalid Channel. Use one of the following: $therelay(channels)" return 0 } send_across "names" $thechan $nick "dummy" return 0 } #// Each bot scans its appropriate Channel, and returns a list to the Calling Bot proc send_names {frm_bot command arg} { global therelay theopts botnick botnet-nick c set arg [split $arg] set thechan [lindex $arg 0] set thenick [lindex $arg 2] set thelist [chanlist $thechan] set olist " " set hlist " " set vlist " " set ulist " " #// Go through the main Channel List, and determine Ops/Halfops/Voices/Normal Users foreach user $thelist { if {[isop $user $thechan] != 0} { #// Ops lappend olist "$c(15___o)\@$c(15x)$user"; } elseif {[ishalfop $user $thechan] != 0} { #// Halfops lappend hlist "$c(15___h)\%$c(15x)$user"; } elseif {[isvoice $user $thechan] != 0} { #// Voice lappend vlist "$c(15___v)\+$c(15x)$user"; } else { #// Normal Users lappend ulist "$user"; } } #// Sort && append the lists together into a final list if {$olist != ""} {append chlist [lsort $olist]} if {$hlist != ""} {append chlist " [lsort $hlist]"} if {$vlist != ""} {append chlist " [lsort $vlist]"} if {$ulist != ""} {append chlist " [lsort $ulist]"} #// Reply ONLY to the calling Bot with our responses, and split up the response if necessary set usernum [llength $chlist] if {$usernum > $theopts(max_names)} { for {set xStart 0} {$xStart < $usernum} {incr xStart $theopts(max_names)} { set xEnd [expr $xStart + $theopts(max_names)] set tmplist [join [lrange $chlist $xStart [expr $xEnd - 1]]] if {$xEnd > $usernum} {set xEnd $usernum} putbot $frm_bot [concat "snames" $thechan $therelay(ournet) $thenick "yes" $xStart $xEnd $usernum $tmplist] } return 0 } putbot $frm_bot [concat "snames" $thechan $therelay(ournet) $thenick "no" 0 0 $usernum $chlist] return 0 } #// Prints the names in PRIVMSG to the $nick that requested the list proc recv_names {frm_bot command arg} { global theopts c set arg [split $arg] set thechan "$c(15chan)[lindex $arg 0]$c(15x)" set thenetw "$c(15netw)[lindex $arg 1]$c(15x)" set thenick [lindex $arg 2] set isSplit [lindex $arg 3] set xStart [lindex $arg 4] set xEnd [lindex $arg 5] set usernum [lindex $arg 6] set thelist [join [join [lrange $arg 7 end]]] #// Determine if the message is split up into pieces or not if {$isSplit == "yes"} { putquick "PRIVMSG $thenick :$thechan$c(15atch)\@$c(15x)$thenetw: $thelist \ \(\[Displaying $c(15numA)[expr $xStart + 1]$c(15x) to \ $c(15numB)$xEnd$c(15x)\] of $c(15totl)$usernum$c(15x) Users\)" } else { putquick "PRIVMSG $thenick :$thechan$c(15atch)\@$c(15x)$thenetw: $thelist \ \($c(15totl)$usernum$c(15x) Users\)" } return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Private Messageing --- #// Send a PRIVMSG proc send_msg {nick uhost hand text} { global therelay botnet-nick replybuf set text [split $text] set theuser [lindex [split [split [lindex $text 0] @]] 0] set thenetw [lindex [split [split [lindex $text 0] @]] 1] set themsgm [join [lrange [split $text] 1 end]] #// Incase we intercept another msg command switch -exact -- [lindex $text 0] { !gettopic - !op - !deop - !halfop - !dehalfop - !voice - !devoice - !topic - !kick - !kickban - !mode - !hurt - !heal { return 0 } } #// Strip our network from the list set netpos [lsearch -exact $therelay(botnet) ${botnet-nick}] set temp(irclist) [lreplace $therelay(botirc) $netpos $netpos] set temp(botlist) [lreplace $therelay(botnet) $netpos $netpos] set temp(netlist) [lreplace $therelay(netwrk) $netpos $netpos] #// Figure out the bot on the target network set netpos [lsearch -exact $temp(netlist) $thenetw] if {$netpos != -1} { set thebot(irc) [lindex [split $temp(irclist)] $netpos] set thebot(net) [lindex [split $temp(botlist)] $netpos] if {[islinked $thebot(net)] == 0} { putserv "PRIVMSG $nick :Network $thenetw is not online/linked." return 0 } } else { putserv "PRIVMSG $nick :Invalid Network. Use one of the following: $temp(netlist)" return 0 } #// Let's avoid sending privmsgs to the target bot if {$thebot(irc) == $theuser} { putserv "PRIVMSG $nick :Please do not send messages to the other relay bots." return 0 } #// Send the message putbot $thebot(net) [concat "sprivmsg" $nick $therelay(ournet) $theuser $themsgm] #// Store the User@Network that the message was sent to in our Reply Buffer set replybuf($nick\!$uhost) "$theuser\@$thenetw" return 0 } #// Send a Reply to a Privmsg proc send_replymsg {nick uhost hand text} { global replybuf #// See if a reply buffer exists for the user if {[info exists replybuf($nick\!$uhost)] != 0} { send_msg $nick $uhost $hand [concat $replybuf($nick\!$uhost) $text] } else { putserv "PRIVMSG $nick :Your reply buffer is empty." } return 0 } #// Receive a PRIVMSG proc recv_msg {frm_bot command arg} { global theopts replybuf c set arg [split $arg] set sender [lindex $arg 0] set sendnet [lindex $arg 1] set thenick [lindex $arg 2] set themsgm [strip_codes [join [lrange $arg 3 end]]] #// Output the message putquick "PRIVMSG $thenick :$c(16brac)\<$c(16x)$c(16nick)$sender$c(16x)$c(16atch)\@$c(16x)$c(16netw)$sendnet$c(16x)$c(16brac)\>$c(16x) $themsgm" #// Store the User@Network that the message was received from in our Reply Buffer set tmphost [getchanhost $thenick] if {$tmphost != ""} { set replybuf($thenick\!$tmphost) "$sender\@$sendnet" } return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- !gettopic Procedures --- #// Sends a "gettopic" request to the Botnet (Public) #// !gettopic proc pub_gettopic {nick uhost hand chan text} { global theopts set thenetw [lindex [split $text] 0] if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!gettopic $text"} cmd_gettopic "gettopic" $chan $nick $thenetw return 0 } #// Sends a "gettopic" request to the Botnet (Privmsg) #// /msg !gettopic @ proc msg_gettopic {nick uhost hand text} { global therelay set text [split $text] set thechan [lindex [split [split [lindex $text 0] @]] 0] set thenetw [lindex [split [split [lindex $text 0] @]] 1] #// Valid Channel Type? switch -exact -- [string range $thechan 0 0] { # - & - ! {} + { putserv "PRIVMSG $nick :Sorry, channels prefixed with a \'\+\' character do not support topics." return 0 } default { putserv "PRIVMSG $nick :Invalid Channel. Use one of the following: $therelay(channels)" return 0 } } #// Valid Channel listed in $therelay(channels)? if {[lsearch -exact $therelay(channels) [string tolower $thechan]] == -1} { putserv "PRIVMSG $nick :Invalid Channel. Use one of the following: $therelay(channels)" return 0 } cmd_gettopic "gettopic" $thechan $nick $thenetw return 0 } #// Determine where to send the "gettopic" request proc cmd_gettopic {msg chan nick netw} { global therelay botnick botnet-nick #// Strip our network from the list set netpos [lsearch -exact $therelay(botnet) ${botnet-nick}] set temp(irclist) [lreplace $therelay(botirc) $netpos $netpos] set temp(botlist) [lreplace $therelay(botnet) $netpos $netpos] set temp(netlist) [lreplace $therelay(netwrk) $netpos $netpos] #// Figure out the bot on the target network set netpos [lsearch -exact $temp(netlist) $netw] if {$netpos != -1} { set thebot(net) [lindex [split $temp(botlist)] $netpos] if {[islinked $thebot(net)] == 0} { putserv "NOTICE $nick :Network $netw is not online." return 0 } } else { putserv "NOTICE $nick :Invalid Network. Use one of the following: $temp(netlist)" return 0 } #// Send a message to the target bot requesting a channel topic set botMsg [concat $msg $chan $nick] putbot $thebot(net) $botMsg return 0 } #// Fetches the topic for the specified channel, and sends it back to the calling bot proc send_gettopic {frm_bot command arg} { global therelay botnick botnet-nick c set arg [split $arg] set thechan [lindex $arg 0] set thenick [lindex $arg 1] set thetopc [topic $thechan] #// Reply ONLY to the calling Bot with our response putbot $frm_bot [concat "sgettopic" $thechan $therelay(ournet) $thenick $thetopc] return 0 } #// Prints the topic of the specified channel to the requesting user in PRIVMSG proc recv_gettopic {frm_bot command arg} { global c set arg [split $arg] set thechan "$c(17chan)[lindex $arg 0]$c(17x)" set thenetw "$c(17netw)[lindex $arg 1]$c(17x)" set thenick [lindex $arg 2] set thetopc [join [lrange $arg 3 end]] #// Was there a topic? if {$thetopc == ""} { set thetopc "No Topic Available" } else { set thetopc "\'$thetopc\'" } #// Give the Topic... putquick "PRIVMSG $thenick :$thechan$c(17atch)\@$c(17x)$thenetw Topic: $c(17topc)$thetopc$c(17x)" return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Command Handler --- proc send_cmd {nick chan text} { global therelay botnet-nick set text [split $text] set thecmd [lindex $text 0] set thevictim [lindex [split [split [lindex $text 1] @]] 0] set thenetwrk [lindex [split [split [lindex $text 1] @]] 1] #// Valid Channel Type? switch -exact -- [string range $chan 0 0] { # - & - ! {} + { putserv "NOTICE $nick :Sorry, channels prefixed with a \'\+\' character do not support channel modes." return 0 } default { putserv "NOTICE $nick :Invalid Channel. Use one of the following: $therelay(channels)" return 0 } } #// Valid Channel listed in $therelay(channels)? if {[lsearch -exact $therelay(channels) [string tolower $chan]] == -1} { putserv "NOTICE $nick :Invalid Channel. Use one of the following: $therelay(channels)" return 0 } #// Make sure the user is an Operator (Halfops shouldn't need this level of access) if {[isop $nick $chan] == 0} { putserv "NOTICE $nick :Sorry, that command is reserved for operators only." return 0 } #// Figure out the bot on the target network (if network == "all", then skip) if {$thenetwrk != "all"} { set netpos [lsearch -exact $therelay(netwrk) $thenetwrk] if {$netpos != -1} { set thebot(net) [lindex [split $therelay(botnet)] $netpos] if {$thebot(net) != ${botnet-nick}} { if {[islinked $thebot(net)] == 0} { putserv "NOTICE $nick :Network $thenetw is not online/linked." return 0 } set isLocal 0 } else { set isLocal 1 } } else { putserv "NOTICE $nick :Invalid Network. Use one of the following: $therelay(netwrk) all" return 0 } } else { set isLocal 1 } #// Make sure we are not attempting to execute commands on the relay bots set tmppos1 [lsearch -exact $therelay(botirc) $thevictim] set tmppos2 [lsearch -exact $therelay(netwrk) $thenetwrk] if {($tmppos1 > -1 && $tmppos2 > -1) && ($tmppos1 == $tmppos2)} { putserv "NOTICE $nick :Invalid Nickname." return 0 } #// What are we doing? switch -exact -- $thecmd { !kick - !kickban { set thereason [join [lrange [split $text] 1 end]] set botMsg [concat "rlycmd" $nick $chan $therelay(ournet) $thecmd $thevictim $thereason] } !mode - !topic { set themode [join [lrange [split $text] 2 end]] set botMsg [concat "rlycmd" $nick $chan $therelay(ournet) $thecmd $themode] } default {set botMsg [concat "rlycmd" $nick $chan $therelay(ournet) $thecmd $thevictim]} } #// if $thenetwrk == "all, send it to all bots/networks, otherwise... if {$thenetwrk != "all"} { if {$isLocal == 0} { putbot $thebot(net) $botMsg } } elseif {$thenetwrk == "all"} { putallbots $botMsg } #// If $isLocal == 1, execute a local version of the command as well if {$isLocal == 1} { recv_cmd "null" "rlycmd" [lrange $botMsg 1 end] } return 0 } proc recv_cmd {frm_bot command arg} { global theopts set arg [split $arg] set thenick [lindex $arg 0] set thechan [lindex $arg 1] set thenetw [lindex $arg 2] set thecmnd [lindex $arg 3] #// Perform the requested Action if {[botisop $thechan] == 1} { #// Channel Modes/Multiple Modes _OR_ Topics switch -exact -- $thecmnd { !mode { set themodes [join [lrange $arg 4 end]] putserv "MODE $thechan $themodes" return 0 } !topic { set thetopc [join [lrange $arg 4 end]] putserv "TOPIC $thechan :$thetopc" return 0 } } set victim [join [lindex $arg 4]] if {[onchan $victim $thechan] == 1} { switch -exact -- $thecmnd { !kick { #// Kick set reason [join [lrange $arg 6 end]] putserv "KICK $thechan $victim :$reason \($thenick\@$thenetw\)" return 0 } !kickban { #// Kickban set reason [join [lrange $arg 6 end]] set theban "*![getchanhost $victim $thechan]" putquick "MODE $thechan +b $theban" putserv "KICK $thechan $victim :$reason \($thenick\@$thenetw\)" timer $theopts(cmdkickban_len) "putquick \"MODE $thechan -b $theban\"" return 0 } default { #// What mode are we doing? switch -exact -- $thecmnd { !op {set themode "+o"} !deop {set themode "-o"} !voice {set themode "+v"} !devoice {set themode "-v"} !halfop {set themode "+h"} !dehalfop {set themode "-h"} } putserv "MODE $thechan $themode $victim" return 0 } } } } return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- !op/!deop --- #// /msg !op @ proc send_msgop {nick uhost hand text} { set text [split $text] set victim [lindex $text 0] set thechan [lindex $text 1] send_cmd $nick $thechan [concat "!op" $victim] return 0 } #// /msg !deop @ proc send_msgdeop {nick uhost hand text} { set text [split $text] set victim [lindex $text 0] set thechan [lindex $text 1] send_cmd $nick $thechan [concat "!deop" $victim] return 0 } #// !op @ proc send_pubop {nick uhost hand chan text} { global theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!op $text"} send_cmd $nick $chan [concat "!op" $text] return 0 } #// !deop @ proc send_pubdeop {nick uhost hand chan text} { global theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!deop $text"} send_cmd $nick $chan [concat "!deop" $text] return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- !voice/!devoice --- #// /msg !voice @ proc send_msgvoice {nick uhost hand text} { set text [split $text] set victim [lindex $text 0] set thechan [lindex $text 1] send_cmd $nick $thechan [concat "!voice" $victim] return 0 } #// /msg !devoice @ proc send_msgdevoice {nick uhost hand text} { set text [split $text] set victim [lindex $text 0] set thechan [lindex $text 1] send_cmd $nick $thechan [concat "!devoice" $victim] return 0 } #// !voice @ proc send_pubvoice {nick uhost hand chan text} { global theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!voice $text"} send_cmd $nick $chan [concat "!voice" $text] return 0 } #// !devoice @ proc send_pubdevoice {nick uhost hand chan text} { global theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!devoice $text"} send_cmd $nick $chan [concat "!devoice" $text] return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- !halfop/!dehalfop --- #// /msg !halfop @ proc send_msghalfop {nick uhost hand text} { set text [split $text] set victim [lindex $text 0] set thechan [lindex $text 1] send_cmd $nick $thechan [concat "!halfop" $victim] return 0 } #// /msg !dehalfop @ proc send_msgdehalfop {nick uhost hand text} { set text [split $text] set victim [lindex $text 0] set thechan [lindex $text 1] send_cmd $nick $thechan [concat "!dehalfop" $victim] return 0 } #// !halfop @ proc send_pubhalfop {nick uhost hand chan text} { global theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!halfop $text"} send_cmd $nick $chan [concat "!halfop" $text] return 0 } #// !dehalfop @ proc send_pubdehalfop {nick uhost hand chan text} { global theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!dehalfop $text"} send_cmd $nick $chan [concat "!dehalfop" $text] return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- !topic --- #// /msg !topic @ proc send_msgtopc {nick uhost hand text} { set text [split $text] set thechan [lindex [split [split [lindex $text 0] @]] 0] set thenetw [lindex [split [split [lindex $text 0] @]] 1] set thetopc [join [lrange $text 1 end]] send_cmd $nick $thechan [concat "!topic" "null\@$thenetw" $thetopc] return 0 } #// !topic proc send_pubtopc {nick uhost hand chan text} { global theopts set text [split $text] set thenetw [lindex $text 0] set thetopc [join [lrange $text 1 end]] if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!topic $text"} send_cmd $nick $chan [concat "!topic" "null\@$thenetw" $thetopc] return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- !kick/!kickban --- #// /msg !kick @ proc send_msgkick {nick uhost hand text} { set text [split $text] set victim [lindex $text 0] set thechan [lindex $text 1] set reason [join [lrange $text 2 end]] send_cmd $nick $thechan [concat "!kick" $victim $reason] return 0 } #// !kick @ proc send_pubkick {nick uhost hand chan text} { global theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!kick $text"} send_cmd $nick $chan [concat "!kick" $text] return 0 } #// /msg !kickban @ (60 Minute ban) proc send_msgkickban {nick uhost hand text} { set text [split $text] set victim [lindex $text 0] set thechan [lindex $text 1] set reason [join [lrange $text 2 end]] send_cmd $nick $thechan [concat "!kickban" $victim $reason] return 0 } #// !kickban @ (60 Minute Ban) proc send_pubkickban {nick uhost hand chan text} { global theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!kickban $text"} send_cmd $nick $chan [concat "!kickban" $text] return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- !mode --- #// /msg !mode @ proc send_msgmode {nick uhost hand text} { set text [split $text] set thechan [lindex [split [split [lindex $text 0] @]] 0] set thenetw [lindex [split [split [lindex $text 0] @]] 1] set themode [join [lrange $text 1 end]] send_cmd $nick $thechan [concat "!mode" "null\@$thenetw" $themode] return 0 } #// !mode proc send_pubmode {nick uhost hand chan text} { global theopts set text [split $text] set thenetw [lindex $text 0] set themode [join [lrange $text 1 end]] if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!mode $text"} send_cmd $nick $chan [concat "!mode" "null\@$thenetw" $themode] return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- !help --- #// /msg !help proc send_msghelp {nick uhost hand text} { cmd_help $nick $text return 0 } #// !help proc send_pubhelp {nick uhost hand chan text} { global theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!help $text"} cmd_help $nick $text return 0 } #// Process Help proc cmd_help {nick text} { global therelay theopts botnick botnet-nick c set text [split $text] set helpcmd [lindex $text 0] set chopcmd [lindex $text 1] set ischanop 0 #// Figure out our home network set netpos [lsearch -exact $therelay(botnet) ${botnet-nick}] set netwrks [lreplace $therelay(netwrk) $netpos $netpos "$c(18home)$therelay(ournet)$c(18x)$c(18cmds)"] #// Is the user an op on atleast one of the channels on the relay? foreach chan $therelay(channels) { if {[isop $nick $chan] == 1} { set ischanop 1 set netwrks "$netwrks all" } } #// If $helpcmd is empty, print basic help info if {[string length $helpcmd] == 0} { putserv "PRIVMSG $nick :-- $therelay(name) Help --" putserv "PRIVMSG $nick :  " puthelp "PRIVMSG $nick :Available Topics:" puthelp "PRIVMSG $nick :$c(18help)privmsg$c(18x) - Private Messaging" puthelp "PRIVMSG $nick :$c(18help)network$c(18x) - List of networks on the relay" puthelp "PRIVMSG $nick :$c(18help)usercmd$c(18x) - User Commands" if {$ischanop == 1} {puthelp "PRIVMSG $nick :$c(18help)chopcmd$c(18x) - Chanop Commands"} puthelp "PRIVMSG $nick :  " return 0 } else { #// Figure out what kind of help to give, and give it if {$helpcmd == "privmsg"} { #// Private Messaging putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :Private Messaging:" puthelp "PRIVMSG $nick :Allows a User on one network to send a private message to a user on another network." puthelp "PRIVMSG $nick :Use the following format:" puthelp "PRIVMSG $nick :$c(18cmds)\/msg $botnick$c(18x) $c(18args)\$c(18x)\@$c(18args)\ \$c(18x)" puthelp "PRIVMSG $nick :Where $c(18args)\$c(18x) is the nickname of the User to receive the message," puthelp "PRIVMSG $nick :And $c(18args)\$c(18x) is the remote network the user is on." puthelp "PRIVMSG $nick :For a list of available networks, type \"$c(18cmds)!help network$c(18x)\"." puthelp "PRIVMSG $nick :To quickly respond to the last private message received without typing out the" puthelp "PRIVMSG $nick :sender's nickname and network, use \"$c(18cmds)!reply \$c(18x)\"." return 0 } elseif {$helpcmd == "network"} { #// List the networks putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :Available networks:" puthelp "PRIVMSG $nick :$c(18cmds)$netwrks$c(18x)" return 0 } elseif {$helpcmd == "usercmd"} { #// Basic User Commands putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :User Commands:" puthelp "PRIVMSG $nick :$c(18help)!help$c(18x) - Relay Help System." puthelp "PRIVMSG $nick :$c(18help)!names$c(18x) - Lists names/status of users on all networks." puthelp "PRIVMSG $nick : " puthelp "PRIVMSG $nick :$c(18help)!gettopic$c(18x) - Get the topic of a channel on another network." puthelp "PRIVMSG $nick :Public Usage: $c(18cmds)!gettopic$c(18x) $c(18args)\$c(18x)." puthelp "PRIVMSG $nick :Msg Usage: $c(18cmds)/msg $botnick !gettopic$c(18x) $c(18args)\$c(18x)\@$c(18args)\$c(18x)." return 0 } elseif {$helpcmd == "chopcmd"} { #// Channel Op Commands if {$ischanop == 1} { #// If $chopcmd is empty, list available commands if {[string length $chopcmd] == 0} { putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :Channel Operator Commands:" puthelp "PRIVMSG $nick :$c(18cmds)!op !deop !halfop !dehalfop !voice !devoice !topic !kick !kickban !mode !hurt !heal$c(18x)" puthelp "PRIVMSG $nick : " puthelp "PRIVMSG $nick :For help on individual commands, use:" puthelp "PRIVMSG $nick :$c(18cmds)!help chopcmd$c(18x) $c(18args)\$c(18x)." return 0 } else { #// Give help on Channel Op Commands if {$chopcmd == "!op"} { #// !op putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :$c(18cmds)!op$c(18x) - Gives channel ops to a user on a remote network." puthelp "PRIVMSG $nick :Public Usage: $c(18cmds)!op$c(18x) $c(18args)\$c(18x)\@$c(18args)\$c(18x)." puthelp "PRIVMSG $nick :Msg Usage: $c(18cmds)/msg $botnick !op$c(18x) $c(18args)\$c(18x)\@$c(18args)\ \$c(18x)." return 0 } elseif {$chopcmd == "!deop"} { #// !deop putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :$c(18cmds)!deop$c(18x) - Removes channel ops from a user on a remote network." puthelp "PRIVMSG $nick :Public Usage: $c(18cmds)!deop$c(18x) $c(18args)\$c(18x)\@$c(18args)\$c(18x)." puthelp "PRIVMSG $nick :Msg Usage: $c(18cmds)/msg $botnick !deop$c(18x) $c(18args)\$c(18x)\@$c(18args)\ \$c(18x)." return 0 } elseif {$chopcmd == "!halfop"} { #// !halfop putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :$c(18cmds)!halfop$c(18x) - Gives halfops to a user on a remote network." puthelp "PRIVMSG $nick :Public Usage: $c(18cmds)!halfop$c(18x) $c(18args)\$c(18x)\@$c(18args)\$c(18x)." puthelp "PRIVMSG $nick :Msg Usage: $c(18cmds)/msg $botnick !halfop$c(18x) $c(18args)\$c(18x)\@$c(18args)\ \$c(18x)." return 0 } elseif {$chopcmd == "!dehalfop"} { #// !dehalfop putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :$c(18cmds)!dehalfop$c(18x) - Removes halfops from a user on a remote network." puthelp "PRIVMSG $nick :Public Usage: $c(18cmds)!dehalfop$c(18x) $c(18args)\$c(18x)\@$c(18args)\$c(18x)." puthelp "PRIVMSG $nick :Msg Usage: $c(18cmds)/msg $botnick !dehalfop$c(18x) $c(18args)\$c(18x)\@$c(18args)\ \$c(18x)." return 0 } elseif {$chopcmd == "!voice"} { #// !voice putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :$c(18cmds)!voice$c(18x) - Gives voice to a user on a remote network." puthelp "PRIVMSG $nick :Public Usage: $c(18cmds)!voice$c(18x) $c(18args)\$c(18x)\@$c(18args)\$c(18x)." puthelp "PRIVMSG $nick :Msg Usage: $c(18cmds)/msg $botnick !voice$c(18x) $c(18args)\$c(18x)\@$c(18args)\ \$c(18x)." return 0 } elseif {$chopcmd == "!devoice"} { #// !devoice putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :$c(18cmds)!devoice$c(18x) - Removes voice from a user on a remote network." puthelp "PRIVMSG $nick :Public Usage: $c(18cmds)!devoice$c(18x) $c(18args)\$c(18x)\@$c(18args)\$c(18x)." puthelp "PRIVMSG $nick :Msg Usage: $c(18cmds)/msg $botnick !devoice$c(18x) $c(18args)\$c(18x)\@$c(18args)\ \$c(18x)." return 0 } elseif {$chopcmd == "!topic"} { #// !topic putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :$c(18cmds)!topic$c(18x) - Changes the topic on a remote channel." puthelp "PRIVMSG $nick :Public Usage: $c(18cmds)!topic$c(18x) $c(18args)\ \$c(18x)." puthelp "PRIVMSG $nick :Msg Usage: $c(18cmds)/msg $botnick !topic$c(18x) $c(18args)\$c(18x)\@$c(18args)\ \$c(18x)." return 0 } elseif {$chopcmd == "!kick"} { #// !kick putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :$c(18cmds)!kick$c(18x) - Kicks a user from a channel on a remote network." puthelp "PRIVMSG $nick :Public Usage: $c(18cmds)!kick$c(18x) $c(18args)\$c(18x)\@$c(18args)\ \$c(18x)." puthelp "PRIVMSG $nick :Msg Usage: $c(18cmds)/msg $botnick !kick$c(18x) $c(18args)\$c(18x)\@$c(18args)\ \ \$c(18x)." return 0 } elseif {$chopcmd == "!kickban"} { #// !kickban putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :$c(18cmds)!kickban$c(18x) - Kicks a user from a channel on a remote network, and\ applies a simple, $c(18args)$theopts(cmdkickban_len) min\(s\)$c(18x) ban." puthelp "PRIVMSG $nick :Public Usage: $c(18cmds)!kickban$c(18x) $c(18args)\$c(18x)\@$c(18args)\ \$c(18x)." puthelp "PRIVMSG $nick :Msg Usage: $c(18cmds)/msg $botnick !kickban$c(18x) $c(18args)\$c(18x)\@$c(18args)\ \ \$c(18x)." return 0 } elseif {$chopcmd == "!mode"} { #// !mode putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :$c(18cmds)!mode$c(18x) - Applies Modes to a remote channel (Allows multiple modes)." puthelp "PRIVMSG $nick :Public Usage: $c(18cmds)!mode$c(18x) $c(18args)\ \$c(18x)." puthelp "PRIVMSG $nick :Msg Usage: $c(18cmds)/msg $botnick !mode$c(18x) $c(18args)\$c(18x)\@$c(18args)\ \$c(18x)." return 0 } elseif {$chopcmd == "!hurt"} { #// !hurt putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :$c(18cmds)!hurt$c(18x) - Silences a User on the relay (Chat, Actions, Nickchanges, Quit Msgs)." puthelp "PRIVMSG $nick :Public Usage: $c(18cmds)!hurt$c(18x) $c(18args)\[ --list \| \ \]$c(18x)." puthelp "PRIVMSG $nick :Msg Usage: $c(18cmds)/msg $botnick !hurt$c(18x) $c(18args)\[ --list \| \ \]$c(18x)." puthelp "PRIVMSG $nick :Using $c(18args)--list$c(18x) will list the hurtmasks stored in the bot." return 0 } elseif {$chopcmd == "!heal"} { #// !heal putserv "PRIVMSG $nick : " puthelp "PRIVMSG $nick :$c(18cmds)!heal$c(18x) - Removes a Hurtmask on a User (See !hurt)." puthelp "PRIVMSG $nick :Public Usage: $c(18cmds)!heal$c(18x) $c(18args)\[ --list \| \ \| \ \]$c(18x)." puthelp "PRIVMSG $nick :Msg Usage: $c(18cmds)/msg $botnick !heal$c(18x) $c(18args)\[ --list \| \ \| \ \]$c(18x)." puthelp "PRIVMSG $nick :Using $c(18args)--list$c(18x) will list the hurtmasks stored in the bot." return 0 } else { #// Command Does not exist putserv "PRIVMSG $nick :No help available on that topic." return 0 } } } } else { #// Command Does not exist putserv "PRIVMSG $nick :No help available on that topic." return 0 } } return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- !hurt/heal --- #// /msg !hurt [--list] proc send_msghurt {nick uhost hand text} { send_hurt $text $nick return 0 } #// /msg !heal [--list] | proc send_msgheal {nick uhost hand text} { send_heal $text $nick return 0 } #// !hurt [--list] proc send_pubhurt {nick uhost hand chan text} { global theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!hurt $text"} send_hurt $text $nick return 0 } #// !heal [--list] | nick proc send_pubheal {nick uhost hand chan text} { global theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!heal $text"} send_heal $text $nick return 0 } #// Determines 's userhost, adds it to $hurtbuf, and tells the other bots proc send_hurt {victim nick} { global hurtbuf #// Is the caller a Chanop? if {[isop $nick] != 1} { puthelp "NOTICE $nick :Sorry, that command is reserved for operators only." return 0 } #// If "--list" was specified, list the contents of $hurtbuf if {$victim == "--list"} { set tmpnames [array names hurtbuf] set tmppos [lsearch -exact $tmpnames "init"] set tmpnames [lreplace $tmpnames $tmppos $tmppos] if {[llength $tmpnames] > 0} { puthelp "PRIVMSG $nick :Hurt List: $tmpnames" } else { puthelp "PRIVMSG $nick :No users in the Hurt List." } return 0 } #// Prepare and add the new Hurt if {[onchan $victim] == 1} { set thehost [getchanhost $victim] set theisp [lindex [split $thehost @] 1] set thehurt "\*\@$theisp" set hurtbuf($thehurt) "null" putquick "NOTICE $nick :Added $victim \($thehurt\) to the Hurt List, sending to other bots." } else { putquick "NOTICE $nick :User $victim not found on channel, sending to other bots." } #// Tell all bots about the new Hurt set botMsg [concat "hurt" $victim] putallbots $botMsg return 0 } #// We've received a message to hurt someone, so do it proc recv_hurt {frm_bot command text} { global hurtbuf #// Prepare and add the new Hurt if {[onchan $text] == 1} { set thehost [getchanhost $text] set theisp [lindex [split $thehost @] 1] set thehurt "\*\@$theisp" set hurtbuf($thehurt) "null" } return 0 } #// Removes a host from $hurtbuf, and tells the other bots about it proc send_heal {victim nick} { global hurtbuf #// Is the caller a Chanop? if {[isop $nick] != 1} { puthelp "NOTICE $nick :Sorry, that command is reserved for operators only." return 0 } #// If "--list" was specified, list the contents of $hurtbuf if {$victim == "--list"} { set tmpnames [array names hurtbuf] set tmppos [lsearch -exact $tmpnames "init"] set tmpnames [lreplace $tmpnames $tmppos $tmppos] if {[llength $tmpnames] > 0} { puthelp "PRIVMSG $nick :Hurt List: $tmpnames" } else { puthelp "PRIVMSG $nick :No users in the Hurt List." } return 0 } #// Are we using a nickname or a hostmask? if {[string first "@" $victim] == -1} { set thehost [getchanhost $victim] set theisp [lindex [split $thehost @] 1] set theheal "\*\@$theisp" } #// Heal the Hurt if {[info exists hurtbuf($theheal)] == 1} { unset hurtbuf($theheal) putquick "NOTICE $nick :Removed \"$victim\" from the Hurt List." } else { putquick "NOTICE $nick :User nick/mask not found in Hurt List, sending to other bots." } #// Tell all bots about the removal of the Hurt set botMsg [concat "heal" $victim] putallbots $botMsg return 0 } #// We've received a message to heal someone, so do it proc recv_heal {frm_bot command text} { global hurtbuf #// Are we using a nickname or a hostmask? if {[string first "@" $text] == -1} { set thehost [getchanhost $text] set theisp [lindex [split $thehost @] 1] set theheal "\*\@$theisp" } #// Prepare and add the new Hurt if {[info exists hurtbuf($theheal)] == 1} { unset hurtbuf($theheal) } return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- !restart/!rehash/!shutdown --- #// Public !rehash proc pub_rehash {nick uhost hand chan text} { global theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!rehash"} set botMsg [concat "botrehash" "null"] putallbots $botMsg rehash return 0 } #// Public !restart proc pub_restart {nick uhost hand chan text} { global therelay theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!restart"} set botMsg [concat "botrestart" "null"] putallbots $botMsg #// Inform our channels of the restart foreach tmpchan $therelay(channels) { putquick "PRIVMSG $tmpchan :Relay Restarting..." } restart return 0 } #// Public !shutdown proc pub_shutdown {nick uhost hand chan text} { global theopts if {$theopts(enable_echocmd) == 1} {send_across "pubm" $chan $nick "!die $text"} set botMsg [concat "botshutdown" $text] putallbots $botMsg die $text return 0 } #// Privmsg !rehash proc msg_rehash {nick uhost hand text} { set botMsg [concat "botrehash" "null"] #// Send a message to the botnet and rehash putallbots $botMsg rehash return 0 } #// Privmsg !restart proc msg_restart {nick uhost hand text} { global therelay #// Send a message to the botnet set botMsg [concat "botrestart" "null"] putallbots $botMsg #// Inform our channels of the restart foreach tmpchan $therelay(channels) { putquick "PRIVMSG $tmpchan :Relay Restarting..." } #// Restart restart return 0 } #// Privmsg !shutdown proc msg_shutdown {nick uhost hand text} { #// Check for shutdown message if {$text == ""} { set text "Relay Shutdown" } #// Send a message to the botnet set botMsg [concat "botshutdown" $text] putallbots $botMsg #// Die die $text return 0 } #// Receive Rehash proc recv_rehash {frm_bot command arg} { #// Rehash rehash return 0 } #// Receive Restart proc recv_restart {frm_bot command arg} { global therelay #// Inform our channels of the restart foreach tmpchan $therelay(channels) { putquick "PRIVMSG $tmpchan :Relay Restarting..." } #// Restart restart return 0 } #// Receive Shutdown proc recv_shutdown {frm_bot command arg} { #// Die die $arg return 0 } #//-------------------------------------------------------------------------------------------------------------- #// --- Our Tagline --- putlog "$therelay(name) \[relay v${relay-version} by: `Kumba \]"