### ChanLink.tcl v2.3e by JunKie <seizure@fdt.net>
### Remember to always get the latest version of ChanLink at:
### FTP Site: yoda.fdt.net /pub/users/s/seizure/

### Latest Gripes + Flotsam Corner:
### For Remote /WHOIS's to work, be sure to edit eggdrop.h and 
### #define USE_CONSOLE_R instead of #undef USE_CONSOLE_R.
### If this applies to you, you must recompile if it was #undef.
### ChanLink Requires Eggdrop v0.9tp or better to run properly.  
### Sorry, all you 0.9r's out there.. Upgrade your ShitBot.

### This is version 2.3e:
### Added in this version: Thanks to Gumbie, this script is almost bug-free.

### *** CONFIGURATION OPTIONS ***
set chancode ORAC
###          ^^^^ = ACTIVATION Code!  Leave at ORAC to link to all the 
###                 bots, or add your own for privacy.

set myircnet UnknownNet
###          ^^^^^^^^ = IRC Net your bot is located on.

#set badbota H2O
#set badbotb LamestBot
#set badbotc BotNick
###  ^^^^^^^ ^^^^^^^^^ = We are having problems with bots.  Add the offending
###                      Bot's nicks and they will be disconnected on !LINKALLs

### Command Summary:  No longer needed.  Use on-line help, ya tard! ;)

### Sets current version information.
set cnver "v2.3e.Gumbie"

### If the link isn't already up, turn it off.
if {![info exists orac]} {set orac 0}

### Automatic, Complete, never-to-be-beat On-Line Help.
bind pub - !linkhelp pub_linkhelp
bind msg - linkhelp pub_linkhelp

proc pub_linkhelp {nick uhost hand text} {
	global cnver channel botnick
	set linkhelp "ChanLink Help v1.0a By JunKie"
	if {$text == "" || $text == " "} {
	putserv "PRIVMSG $nick :$linkhelp"
	putserv "PRIVMSG $nick :USAGE: LINKHELP <topic> where topic is:"
	putserv "PRIVMSG $nick :LINKUP     LINKDOWN  LINKIN     UNLINK"
	putserv "PRIVMSG $nick :LINKUSERS  LINKBOTS  LINKWHOM   LINKMSG"
	putserv "PRIVMSG $nick :LINKPING   LINKBOOT  LINKWHOIS  HELP"
	return 0
	}
if {$text != ""} {
	putserv "NOTICE $nick :$linkhelp"
	if {$text == "HELP" || $text == "help"} {
	putserv "NOTICE $nick :General Help for ChanLink $cnver:"
	putserv "NOTICE $nick :Channel Link is a channel linker.  It links channels together via the bots."
	putserv "NOTICE $nick :Everything said and done in the channel is relayed thru a network."
	putserv "NOTICE $nick :It is simply for entertainment, and to enhance the bandwidth of one channel!"
	putserv "NOTICE $nick :If you don't like it, stick it in your ear!  \(\002Shove it, $nick!\002\) Hah."
	return 0
	}
	if {$text == "LINKUP" || $text == "linkup"} {
	putserv "PRIVMSG $nick :LINKUP is a command which locally turns on ONLY your"
	putserv "PRIVMSG $nick :bot's link to the ChanLink."
	putserv "PRIVMSG $nick :USAGE: !LINKUP or /MSG $botnick LINKUP"
	return 0
	}
	if {$text == "LINKDOWN" || $text == "linkdown"} {
	putserv "PRIVMSG $nick :LINKDOWN is the command to turn off, locally, ONLY your"
	putserv "PRIVMSG $nick :bot's link to the ChanLink."
	putserv "PRIVMSG $nick :USAGE: !LINKDOWN or /MSG $botnick LINKDOWN"
	return 0
	}
	if {$text == "LINKWHOIS" || $text == "linkwhois"} {
	putserv "PRIVMSG $nick :LINKWHOIS tells you the userhost and realname of a remote user."
	putserv "PRIVMSG $nick :Usage: /MSG $botnick LINKWHOIS <remotebotnick> <remotenick>"
	return 0
	}
	if {$text == "LINKBOTS" || $text == "linkbots"} {
	putserv "PRIVMSG $nick :LINKBOTS is a command which instructs the bot to list all"
	putserv "PRIVMSG $nick :the bots that it knows of that are connected, and include what"
	putserv "PRIVMSG $nick :version of ChanLink they are currently running on their systems."
	putserv "PRIVMSG $nick :USAGE: !LINKBOTS or /MSG $botnick LINKBOTS"
	return 0
	}
	if {$text == "LINKUSERS" || $text == "linkusers"} {
	putserv "PRIVMSG $nick :LINKUSERS is a sophisticated command which asks the remote bot specified"
	putserv "PRIVMSG $nick :to relay a list of people currently on the channel.  This requires you know"
	putserv "PRIVMSG $nick :the nick of the bot in question.  This is a cool command."
	putserv "PRIVMSG $nick :USAGE: !LINKUSERS <remotebotnick> or /MSG $botnick LINKUSERS <remotebotnick>"
	putserv "PRIVMSG $nick :See Also: LINKWHOM"
	return 0
	}
	if {$text == "LINKWHOM" || $text == "linkwhom"} {
	putserv "PRIVMSG $nick :LINKWHOM is an easier rendition of LINKUSERS.  LINKWHOM asks ALL bots to list"
	putserv "PRIVMSG $nick :the current channel users and it is nicer than LINKUSERS."
	putserv "PRIVMSG $nick :USAGE: !LINKWHOM or /MSG $botnick LINKWHOM"
	return 0
	}
	if {$text == "LINKPING" || $text == "linkping"} {
	putserv "PRIVMSG $nick :LINKPING is a command for the open-minded.  It simply reports the # of seconds"
	putserv "PRIVMSG $nick :in lag time that is detected using UNIX kernel second time.  It is for non-"
	putserv "PRIVMSG $nick :entertainment purposes only.  \002NOTE:\002 LINKPING is compatible with putbot."
	putserv "PRIVMSG $nick :USAGE: !LINKPING <remotebotnick> or /MSG $botnick LINKPING <remotebotnick>"
	putserv "PRIVMSG $nick :To ping \002ALL\002 bots, try LINKPING *."
	return 0
	}
	if {$text == "LINKIN" || $text == "linkin"} {
	putserv "PRIVMSG $nick :LINKIN is another bot connection command.  It forces a remote bot to link to ChanLink."
	putserv "PRIVMSG $nick :This should only be used when you really want to get a bot on the link."
	putserv "PRIVMSG $nick :USAGE: !LINKIN <remotebotnick> or /MSG $botnick LINKIN <remotebotnick>"
	putserv "PRIVMSG $nick :See Also: UNLINK"
	return 0
	}
	if {$text == "UNLINK" || $text == "unlink"} {
	putserv "PRIVMSG $nick :UNLINK is a bot disconnection command.  It forces a remote bot to unlink from ChanLink."
	putserv "PRIVMSG $nick :This should be used when you are recieving flooding or annoyance from a certain bot."
	putserv "PRIVMSG $nick :USAGE: !UNLINK <remotebotnick> or /MSG $botnick <remotebotnick>"
	putserv "PRIVMSG $nick :See Also: LINKIN"
	return 0
	}
	if {$text == "LINKALL" || $text == "LINKSHUTDOWN"} {
	putserv "PRIVMSG $nick :LINKALL and LINKSHUTDOWN are MASTER ONLY commands.  These control the entire botnet."
	putserv "PRIVMSG $nick :Please avoid these commands.  Thanks."
	return 0
	}
	if {$text == "LINKBOOT" || $text == "linkboot"} {
	putserv "PRIVMSG $nick :LINKBOOT is a volatile command.  It actually tells a remote bot to /kick someone."
	putserv "PRIVMSG $nick :Access to this command is limited to channel ops in the bot and should be avoided."
	putserv "PRIVMSG $nick :Usage: !LINKBOOT or /MSG $botnick LINKBOOT <remotebotnick> <remotelamernick> <reason>"
	return 0
	}
	if {$text == "LINKMSG" || $text == "linkmsg"} {
	putserv "PRIVMSG $nick :LINKMSG is a very nice addition to ChanLink.  It sends /MSG \(/NOTICE\) to a remote user."
	putserv "PRIVMSG $nick :Usage: /MSG $botnick LINKMSG <remotebotnick> <remotenick> <message>"
	return 0
	}
   }
   putserv "NOTICE $nick :No help available for \"$text\"." 
}

### Ask who on the botnet is running ChanLink
bind pub - !LINKBOTS pub_whohaschanlink
bind pub - !LINKSTAT pub_whohaschanlink
bind msg - linkbots pub_whohaschanlink
proc pub_whohaschanlink {nick uhost hand text} {
	global botnick
	putallbots "CHANLINK $botnick $nick"
}
bind bot - CHANLINK bot_whosgotit
proc bot_whosgotit {bot cmd txt} {
	set whom [lindex $txt 1]
	global botnick channel cnver server myircnet chancode
	putbot $bot "LMSG $botnick $whom $myircnet's $channel, with ChanLink $cnver." 
	putbot $bot "LMSG $botnick $whom I am on server $server"
}

### Sends all public messages, save those sent by the bot, out to the net.
bind pubm - * pub_orac
proc pub_orac {nick uhost hand text} {
  global orac botnick channel chancode
  if {!($orac)} {return 0}
  if {$botnick == $nick} {return 0}
  putallbots "$chancode \<$nick@$channel\> $text"
}

### Sends all Channel Mode Changes out to the net.  *NEW IN v2.2!*
bind mode - * mode_orac
proc mode_orac {nick uhost hand mode} {
  global orac botnick channel chancode
  if {!($orac)} {return 0}
  putallbots "$chancode \($botnick\) Mode Change \"$mode\" on channel $channel by $nick." }

### Send all ACTIONS out on the net.
bind ctcp - ACTION ctcp_orac
proc ctcp_orac {nick uhost hand dest cmd arg} {
	global botnick channel orac chancode
	if {!($orac)} {return 0}
	if {$botnick == $nick} {return 0}
	putallbots "$chancode \($botnick\) \* $nick@$channel $arg"
}

### Sends information about people who Joined out to the net.
bind join - % join_orac
proc join_orac {nick uhost hand} {
  global channel orac botnick chancode
  if {!($orac)} {return 0}
  putallbots "$chancode \($botnick\) *** $nick \($uhost\) just joined $channel." }

### Sends information about people who have LEFT, out to the net.
bind part - % part_orac
proc part_orac {nick uhost hand} {
  global botnick channel orac chancode
  if {!($orac)} {return 0}
  putallbots "$chancode \($botnick\) *** $nick left $channel."
}

### Lets the net know someone changed the topic!
bind topc - * topc_orac
proc topc_orac {nick uhost hand topic} {
  global channel orac botnick chancode myircnet
  if {!($orac)} {return 0}
  putallbots "$chancode *** \($botnick\) $nick changed topic on $myircnet $channel to:"
  putallbots "$chancode *** \"$topic\""
}

### Announces when a Channel Kick occurs.
bind kick - % kick_orac
proc kick_orac {nick uhost hand kicked reason} {
  global channel orac botnick chancode myircnet
  if {!($orac)} {return 0}
  putallbots "$chancode *** $kicked has been kicked off $myircnet $channel by $nick \($reason\)" }

### Announces when a user /QUIT's.
bind sign - % sign_orac
proc sign_orac {nick uhost hand reason} {
  global orac channel botnick chancode
  if {!($orac)} {return 0}
  putallbots "$chancode \($botnick\) *** Signoff: $nick \[$uhost\] \($reason\)" }

### Announces any changes of nicks.
bind nick - % nick_orac
proc nick_orac {nick uhost hand newnick} {
  global orac botnick channel chancode
  if {!($orac)} {return 0}
  putallbots "$chancode \($botnick\) *** $nick \($uhost\) is now known as $newnick on $channel." }

bind msg - linkmsg msg_linkmsg
proc msg_linkmsg {nick uhost hand txt} {
	if {$txt == ""} { 
	putserv "PRIVMSG $nick :USAGE: linkmsg <botnick> <user> <message>"
	return 0
	}
	set whatbot [lindex $txt 0]
	set whoto [lindex $txt 1]
	set msg [lrange $txt 2 end]
	putbot $whatbot "LMSG $nick $whoto $msg"
}
bind bot - LMSG msg_sendlinkmsg
proc msg_sendlinkmsg {bot cmd arg} {
	set whofrom [lindex $arg 0]
	set whoto [lindex $arg 1]
	set msg [lrange $arg 2 end]
	putserv "NOTICE $whoto :\($bot\) Message from $whofrom:"
	putserv "NOTICE $whoto :\"$msg\""
}

bind raw - * raw_whois
proc raw_whois {whois} {
	global wnick wuser whost rlnm
	set prelim [lindex $whois 1]
	if {$prelim == "311"} {
	set wnick [lindex $whois 3]
	set wuser [lindex $whois 4]
	set whost [lindex $whois 5]
	set rlnm [lrange $whois 7 end]
	}
	if {$prelim == "401"} {
	set wnick [lindex $whois 3]
	set wuser "nonexistant"
	set whost "noHOST"
	set rlnm "This user does not exist."
	}
}

bind msg - linkwhois pub_linkwhois
proc pub_linkwhois {nick uhost hand whol} {
	global botnick
	set whatbot [lindex $whol 0]
	set whom [lindex $whol 1]
        if { $whatbot == "" || $whom == "" } {
          pub_linkhelp $nick $uhost $hand "linkwhois"
	  return 1 }
        set botss [bots]
        set lowbot [string tolower $whatbot]
        foreach b $botss {
   	  if {[lsearch -exact $lowbot [string tolower $b]] > -1 } {
	putserv "NOTICE $nick :Please wait 1 minute for WHOIS reply."
	putbot $whatbot "CWHOIS $nick $whom"
	return 1
	} }
	putserv "PRIVMSG $nick :Bad Bot: $whatbot not connected."
}
bind bot - CWHOIS bot_whois
proc bot_whois {bot cmd arg} {
	global botnick wibot from
	set wibot [lindex $bot 0]
	set who [lindex $arg 1]
	set from [lindex $arg 0]
	putserv "WHOIS $who"
	timer 1 raw_sendwhois
}
proc raw_sendwhois {} {
	global wibot wnick wuser whost rlnm from
	putbot $wibot "LMSG WHOIS_DAEMON $from $wnick is \($wuser@$whost\) \[$rlnm\]" 
}

bind pub o !UNLINK pub_unlinkabot
bind msg o unlink pub_unlinkabot

proc pub_unlinkabot {nick uhost hand bot} {
	global channel botnick
        set botss [bots]
        set lowbot [string tolower $bot]
        foreach b $botss {
   	  if {[lsearch -exact $lowbot [string tolower $b]] > -1 } {
	putserv "PRIVMSG $channel :$bot disconnected."
	putbot $bot "LINKDOWN $nick"
	return 1
	} }
	putserv "PRIVMSG $channel :Bad Bot: $bot was not connected."
	return 0
}

bind pub o !LINKIN pub_linkupabot
bind msg o LINKIN pub_linkupabot
proc pub_linkupabot {nick uhost hand bot} {
	global channel botnick
        set lowbot [string tolower $bot]
        set botss [bots]
        foreach b $botss {
          if {[lsearch -exact $lowbot [string tolower $b]] > -1} {
	    putbot $bot "LINKUP $channel $nick"
            return 0
          }
        }
        putserv "PRIVMSG $nick :No bot named $bot found on bot-net"
}
bind pub m !LINKALL pub_linkup
bind pub m LINKALL pub_linkup
proc pub_linkup {nick uhost hand text} {
	global channel orac botnick badbota badbotb badbotc
	set orac 1
	putallbots "LINKUP $channel $nick"
	putserv "PRIVMSG $channel :Linking Channels..."
	if {[info exists badbota]} {
	pub_unlinkabot $botnick grin badbot $badbota }
	if {[info exists badbotb]} {
	pub_unlinkabot $botnick grin badbot $badbotb }
	if {[info exists badbotc]} {
	pub_unlinkabot $botnick grin badbot $badbotc }
	return 0
}

bind pub m !linkshutdown pub_linkdown
bind msg m LINKSHUTDOWN pub_linkdown
bind pub o !linkup pub_linkulocal
bind msg o LINKUP pub_linkulocal
proc pub_linkulocal {nick uhost hand text} {
	global orac channel
	putserv "PRIVMSG $channel :Channel Link turned on locally."
	set orac 1
}
bind pub o !LINKDOWN pub_linkdlocal
bind msg o LINKDOWN pub_linkdlocal
proc pub_linkdlocal {nick uhost hand text} {
	global orac channel
	putserv "PRIVMSG $channel :Channel Link disconnected locally."
	set orac 0
}

proc pub_linkdown {nick uhost hand text} {
	global channel orac
	putallbots "LINKDOWN $nick"
	set orac 0
	putserv "PRIVMSG $channel :Link Disconnected."
}
bind msg n spychanlink pub_spychanlink
proc pub_spychanlink {nick uhost hand arg} {
	putallbots "SPYCHAN $nick"
}
### Shit, not another White Rabbit!  This is to tell ya who's usin what chancode.
bind bot - SPYCHAN bot_spychan
proc bot_spychan {bot cmd nick} {
	global botnick channel chancode
	putbot $bot "LMSG $botnick $nick My code is $chancode!"
}
bind bot - LINKUP do_link
proc do_link {from command arg} {
	global channel botnick orac cnver chancode
	set orac 1
	set whodid [lindex $arg 1]
	set whatbot $from
	set whatchan [lindex $arg 0]
	putserv "privmsg $channel :Channel Link Established!"
	putserv "privmsg $channel :We are now linked to $whatchan via $whatbot."
	putserv "privmsg $channel :This link was authorized by $whodid!"
	putbot $whatbot "$chancode Channel Link-Up Established to $channel via $botnick \($cnver\)." }

bind bot - LINKDOWN do_unlink
proc do_unlink {from command arg} {
	global channel botnick orac chancode
	putallbots "$chancode \($botnick\) Disconnected from Link."
	set orac 0
	putserv "privmsg $channel :Channel Link Disconnected by $arg."
}

# ping <bot> or <*> for all bots

bind pub - !LINKPING dcc_ping
bind msg - LINKPING dcc_ping
proc dcc_ping {nick uhost hand arg} {
global botnick
  if {$arg == ""} {
	putserv "PRIVMSG $nick :USAGE: !LINKPING <bot> or !LINKPING * (pings all bots)"
	return 0
  }
if {[string compare [string tolower $arg] [string tolower $botnick]] == 0} {
  putserv "PRIVMSG $nick :$nick, you must specify a bot that is linked to $botnick!"
  return 0
  }
  if {$arg == "\*"} {
    putallbots "ping $hand [unixtime]"
    return 0
  }
  putbot $arg "ping $hand [unixtime]"
  return 1
}

bind bot - ping bot_ping
proc bot_ping {bot cmd arg} {
  set from [lindex $arg 0]
  set rtime [lindex $arg 1] 
  putbot $bot "pong $from $rtime"
}

bind bot - pong bot_pong
proc bot_pong {bot cmd arg} {
  global channel
  set to [lindex $arg 0]
  set pingtime [expr [unixtime] - [lindex $arg 1] + 1]
  set outstr "*** \($bot\) PONG!  \[$pingtime seconds\]"
  putserv "PRIVMSG $channel :$outstr"
  return 1
}

# chlist <bot>
bind pub o !LINKBOOT pub_linkboot 
bind msg o LINKBOOT pub_linkboot
proc pub_linkboot {nick uhost hand arg} {
	if {$arg == ""} {
	putserv "PRIVMSG $nick :USAGE: !LINKBOOT <bot> <nick> <reason>"
	return 0
	}
	set whatbot [lindex $arg 0]
	set who [lindex $arg 1]
	set why [lrange $arg 2 end]
	putbot $whatbot "KICK $who $nick $why"
	putserv "PRIVMSG $nick :Trying to boot $who via $whatbot."
}
bind bot - KICK bot_kick
proc bot_kick {bot cmd arg} {
	global channel botnick chancode
	set who [lindex $arg 0]
	set whodunit [lindex $arg 1]
	set why [lrange $arg 2 end]
	if {$who == $botnick} {
	putallbots "$chancode \($botnick\) $whodunit \*TRIED\* to boot me!"
	return 0
	}
  if {![onchan $who]} {
    return 0
  }
  if {[onchanSplit $who]} {
    return 0
  }
  append userhost $who "!" [getchanhost $who]
  set target [finduser $userhost]
  if {$target != "*"} {
    if {([matchattr $target o] || [matchattr $target m] || [matchattr $target f])} {
      putallbots "$chancode \($botnick\) $whodunit \*TRIED\* to boot $who."
	return 0
	}        
  }
	putlog "Link Booting $who: $why by $whodunit"
	if {$who == "W"} {return 0}
	putserv "KICK $channel $who :$why"
	putallbots "$chancode \($botnick\) $whodunit Booted $who: $why" 
}

bind pub - !LINKUSERS pub_linkusers
bind msg - LINKUSERS pub_linkusers
proc pub_linkusers {nick uhost hand arg} {
global botnick 
  if {$arg == ""} {
  putserv "PRIVMSG $nick :USAGE: !LINKUSERS <bot>"
  return 0
  }
  if {[string compare [string tolower $arg] [string tolower $botnick]] == 0} {
  putserv "PRIVMSG $nick :$nick, you must specify a bot that is linked to $botnick!"
  return 0
  }
     putbot $arg "LINKUSERS $nick"
  return 1
}
proc pub_linkwhom {nick uhost hand arg} {
	putallbots "LINKUSERS $nick"
}
bind pub - !LINKWHOM pub_linkwhom
bind msg - LINKWHOM pub_linkwhom
bind bot - LINKUSERS bot_linkusers
proc bot_linkusers {bot cmd arg} {
global channel botnick pbotlog
  set from [lindex $arg 0] 
    if {$channel == {}} {
    putbot $bot "result $from $from, I'm currently not on a channel!" 
  return 0
  }
  set users [chanlist]
  foreach user $users {
    if {[isop $user]} { 
    append userlist "@" $user " " 
    } else {
    append userlist $user " "
    }
  }
  putbot $bot "LMSG $botnick $from Users on $channel: \[$userlist\]" 
  return 0
}

### Takes any information sent to ORAC users on the net, and displays it.
bind bot - $chancode do_orac
proc do_orac {from command arg} {
  global orac channel
  if {!($orac)} {return 0}
  putserv "PRIVMSG $channel :$arg"
}
