#################################################################################################
# ChanScan TCL eggdrop script, made by Merlin			                		#
# realy... alot of stuff were stolen from the original vip.tcl but I've changed it so much you 	#
# will never notice.										#
# This script was made by me so my botnet would operate like it should.				#
#                                                                                               #
# The get-key command will be out very soon... I'm just not up to it :/                         #
# 												#
# Any comments will be accepted at merlin-@mindless.com						#
#################################################################################################

###############=- You don't need to change anything below this :o) =-############################

# Binding commands:
bind bot o "needops" bot_needs_ops
bind bot o "opresp" bot_ops_response
bind bot o "needinvite" bot_needs_invite
bind bot o "inviteresp" bot_invite_response
bind bot o "unbanresp" bot_unban_response
bind bot o "needunban" bot_needs_unban
bind bot o "limitresp" bot_limit_response
bind bot o "needlimit" bot_needs_limit
bind bot o "botnotonchan" bot_not_on_chan
bind mode - "*+o*" merlin:bot_got_op
bind mode - "*-o*" merlin:bot_lost_op

# Some Junk that you don't need to change:
set myversion "1.3.0"
set globalflags "B c d f j k m n o p u x i"
set chanflags   "d f k m n o i"
set botflags    "a b h l r s"
set newglobalflags "1 2 3 4 5"
set newchanflags   "w"
set chanflag1 "w"

# If a bot on the botnet gets a request of ops or something from another this bot about a channel he's not monitering
#  the bot asks your bot to set a +w flag so your bot won't ask him about ops there anymore. 
# This keeps the botnet from lagging :/

proc bot_not_on_chan { bot cmd arg } {
  set invitebot [lindex $arg 0]
  set channel [lindex $arg 1]
  putlog "Chanscan: $bot is not monitering $channel... placing +w flag on him"
  chattr $bot +w $channel
}
  
# Returns the channel modes for the channel... This is for others bot to know 

proc getchanmode {channel} {
  global savedchans
  for {set i 0} {$i < [llength $savedchans]} {incr i} {
    set this [lindex $savedchans $i]
    if {[string compare [string tolower [lindex $this 0]] [string tolower $channel]] == 0} {
      return [lindex $this 1]
    }
  }
  return ""
}

# Does almost the same thing as above

proc getchanmodes {channel} {
  global savedchans
  for {set i 0} {$i < [llength $savedchans]} {incr i} {
    set this [lindex $savedchans $i]
    if {[string compare [string tolower [lindex $this 0]] [string tolower $channel]] == 0} {
      return [lindex $this 2]
    }
  }
  return ""
}

# Returns the channel topic from the channel to another bot

proc getchantopic {channel} {
  global savedchans
  for {set i 0} {$i < [llength $savedchans]} {incr i} {
    set this [lindex $savedchans $i]
    if {[string compare [string tolower [lindex $this 0]] [string tolower $channel]] == 0} {
      return [lindex $this 3]
    }
  }
  return ""
}
 
# Sets channel modes

proc setchanmode {channel data} {     
  global savedchans
  for {set i 0} {$i < [llength $savedchans]} {incr i} {
    set this [lindex $savedchans $i]
    if {[string compare [string tolower [lindex $this 0]] [string tolower $channel]] == 0} {
      set topic [lindex $this 2]
      set this [list $channel $data $topic]
      set savedchans [lreplace $savedchans $i $i $this]
      savechans
      return 0
    }
  }
}

# Sets channel topic

proc setchantopic {channel data} {     
  global savedchans
  for {set i 0} {$i < [llength $savedchans]} {incr i} {
    set this [lindex $savedchans $i]
    if {[string compare [string tolower [lindex $this 0]] [string tolower $channel]] == 0} {
      set modes [lindex $this 1]
      set this [list $channel $modes $data]
      set savedchans [lreplace $savedchans $i $i $this]
      savechans
      return 0
    }
  }
}


# Responses from other bots... This no longer works... I deleted the reply :o|

proc bot_ops_response {bot cmd response } { 
  return 0
}

proc bot_invite_response {bot cmd response } {
  return 0
}

proc bot_unban_response {bot cmd response } { 
  return 0
}

proc bot_limit_response {bot cmd response } {
  return 0
}

# When the bot needs something... these progs are called.

proc bot_needs_limit {bot cmd arg} {
  global botnick
  if {![validchan [lindex $arg 1]]} {
    putbot $bot "botnotonchan $botnick [lindex $arg 1]"
    putlog "Sent -BOTNOTONCHAN- request to $bot"
    return 0
  }
  set invitebot [lindex $arg 0]
  set channel [lindex $arg 1]
  if {$bot == $botnick} {
    return 0
  }
  if {![botisop $channel]} {
    putbot $bot "limitresp I am not an op on $channel (Multi Chan Bots)."
    return 0
  }
  if {[onchan $invitebot $channel]} {
    putbot $bot "limitresp $invitebot is already on $channel (Multi Chan Bots)."
    return 0
  }
  if {[onchansplit $invitebot $channel]} {
    putbot $bot "limitresp $invitebot is split away from $channel (Multi Chan Bots)."
    return 0
  }
  if {[matchattr $invitebot o]} {
    pushmode $channel +l [expr [llength [chanlist $channel]] + 1]
    return 0
  }
  if {![matchchanattr $invitebot o $channel]} {
    putbot $bot "limitresp $invitebot is no chop on $channel (Multi Chan Bots)."
    return 0
  }
  putcmdlog "$bot: LIMIT $invitebot $channel"
  pushmode $channel +l [expr [llength [chanlist $channel]] + 2]
  return 0
}

proc bot_needs_unban {bot cmd arg} {
  global botnick
  if {![validchan [lindex $arg 1]]} {
    putbot $bot "botnotonchan $botnick [lindex $arg 1]"
    putlog "Sent -BOTNOTONCHAN- request to $bot"
    return 0
  }
  set unbanbot [lindex $arg 0]
  set chan [lindex $arg 1]
  set channel [lindex $arg 1]
  set nick $bot
  if {$bot == $botnick} {
    return 0
  }
  if {![botisop $channel]} {
    putbot $bot "unbanresp I am not an op on $channel (Multi Chan Bots)."
    return 0
  }
  if {[onchan $unbanbot $channel]} {
    putbot $bot "unbanresp $unbanbot is already on $channel (Multi Chan Bots)."
    return 0
  }
  if {[matchattr $unbanbot o]} {
    foreach ban [chanbans $chan] {
      if {[string compare $nick $ban]} {
        pushmode $chan -b $ban
        return 0
      }
    }
  }
  if {![matchchanattr $unbanbot o $channel]} {
    putbot $bot "unbanresp $unbanbot is no chop on $channel (Multi Chan Bots)."
    return 0
  }
  foreach ban [chanbans $chan] {
    if {[string compare $nick $ban]} {
      pushmode $chan -b $ban
      return 0
    }
  }
  return 0
}
 
proc bot_needs_invite {bot cmd arg} {
  global botnick
  if {![validchan [lindex $arg 1]]} {
    putbot $bot "botnotonchan $botnick [lindex $arg 1]"
    putlog "Sent -BOTNOTONCHAN- request to $bot"
    return 0
  }
  set invitebot [lindex $arg 0]
  set channel [lindex $arg 1]
  if {$bot == $botnick} {
    return 0
  }
  if {![botisop $channel]} {
    putbot $bot "inviteresp I am not an op on $channel (Multi Chan Bots)."
    return 0
  }
  if {[onchan $invitebot $channel]} {
    putbot $bot "inviteresp $invitebot is already on $channel (Multi Chan Bots)."
    return 0
  }
  if {[onchansplit $invitebot $channel]} {
    putbot $bot "inviteresp $invitebot is split away from $channel (Multi Chan Bots)."
    return 0
  }
  if {[matchattr $invitebot o]} {
    putcmdlog "$bot: INVITE $invitebot $channel"
    putserv "INVITE $invitebot $channel"
    return 0
  }
  if {![matchchanattr $invitebot o $channel]} {
    putbot $bot "inviteresp $invitebot is no chop on $channel (Multi Chan Bots)."
    return 0
  }
  putcmdlog "$bot: INVITE $invitebot $channel"
  putserv "INVITE $invitebot $channel"
  return 0
}

proc bot_needs_ops {bot cmd arg} {
  global botnick
  if {![validchan [lindex $arg 1]]} {
    putbot $bot "botnotonchan $botnick [lindex $arg 1]"
    putlog "Sent -BOTNOTONCHAN- request to $bot"
    return 0
  }
  set opbot [lindex $arg 0]
  set channel [lindex $arg 1]
  if {$bot == $botnick} {
    return 0
  }
  if {![onchan $botnick $channel]} {
    return 0
  }
  if {![botisop $channel]} {
    putbot $bot "opresp I am not an op on $channel (Multi Chan Bots)."
    return 0
  }
  if {[onchansplit $opbot $channel]} {
    putbot $bot "opresp $opbot is split away from $channel (Multi Chan Bots)."
    return 0
  }
  if {[matchattr $opbot o]} {
    putcmdlog "$bot: OP $opbot $channel"
    pushmode $channel +o "$opbot"
    return 0
  }
  if {![matchchanattr $opbot o $channel]} {
    putbot $bot "opresp $opbot is no chop on $channel (Multi Chan Bots)."
    return 0
  }
  putcmdlog "$bot: OP $opbot $channel"
  pushmode "$channel +o $opbot"

  return 0
}

# Activated by the bot when it needs something on the channel
#  Kind of explains itself :/

proc gain-invite {channel} {
  global botnick myfamily
	foreach bot [lbots] {
		if {[matchchanattr $bot w $channel]} { return 1 }
		putbot $bot "needinvite $botnick $channel"

	}
}

proc gain-unban {channel} {
  global botnick myfamily
	foreach bot [lbots] {
		if {[matchchanattr $bot w $channel]} { return 1 }
		putbot $bot "needunban $botnick $channel"
	}
}

proc gain-limit {channel} {
  global botnick myfamily
	foreach bot [lbots] {
		if {[matchchanattr $bot w $channel]} { return 1 }
			putbot $bot "needlimit $botnick $channel"

	}
}

proc gain-ops {channel} {
  global botnick myfamily
	foreach bot [lbots] {
		if {[matchchanattr $bot w $channel]} { return 1 }
			putbot $bot "needops $botnick $channel"
		}

}

# This is entirely stolen... Yes I'm a thief, shoot me !

proc wincontrol {newidx} {
  control $newidx get_address
}

proc get_address {idx args} {
  set usrs [dcclist]
  set teller 0
  foreach addr $usrs {
    if {[lindex $addr 0] == $idx} {
      putlog "Connect on port 139 (Windows NetBios) detected from: [lindex [split [lindex $addr 2] :] 1]  (Out Of Bounds Bug)"
    }
  }
  return 1
}

# Something I picked up.. sounds useful

proc lbots {} {
 set unf ""
 foreach users [userlist b] {
  foreach bs [bots] {
   if {$users == $bs} {
    lappend unf $users
   }
  }
 }
 return $unf
}

# This is activated by the +o mode on channel. 
#  The bot scans all nicks on the channel and deops the nonops if the channel is set as +bitch
# Also the bot ops all friendly bots in the channel automaticly

proc merlin:bot_got_op { nick uhost handle channel modes } {
	global botnick
	if {$modes=="+o $botnick"} {
		putlog "Chanscan: Got op on $channel, scanning..."
		foreach cuser [chanlist $channel] {
			if {[isop $cuser $channel]} {
				set nice "0"
				if {$cuser == $botnick} { set nice "1" }
				if {[matchchanattr [nick2hand $cuser $channel] o $channel]} { set nice "1" }
				if {[matchchanattr [nick2hand $cuser $channel] m $channel]} { set nice "1" }
				if {[matchattr [nick2hand $cuser $channel] o]} { set nice "1" }
				if {[matchattr [nick2hand $cuser $channel] m]} { set nice "1" }
				if {[string first +bitch [channel info $channel]] < 0} { set nice "1" }
				if {$nice == "0"} { 
					putlog "Chanscan: taking ops from $cuser on $channel"
					pushmode $channel -o $cuser 
				}
			}
			if [matchchanattr $cuser w $channel] { 
				putlog "Chanscan: $cuser has the +w flag on $channel"
				return 0
			}
			if {![isop $cuser $channel]} {
				if [matchattr [nick2hand $cuser $channel] b] {
					if {[matchattr [nick2hand $cuser $channel] o]} { 
						pushmode $channel +o $cuser
						putlog "ChanScan: giving op to $cuser on $channel"
					}
					if {[matchchanattr [nick2hand $cuser $channel] o $channel]} {
						pushmode $channel +o $cuser
						putlog "ChanScan: giving op to $cuser on $channel"
					}
				}
			}
		}
	}
	flushmode $channel
	return 0
}
# This is activated by the -o mode on the channel.
# The bot detects if his bot, friend was deoped and ops him back
#  Also, if the deoper isn't a friend, master or owner the bots deops him also

proc merlin:bot_lost_op { nick uhost handle channel modes } {
	global botnick
	set opnick [lindex $modes 1]	
	if {$opnick == $botnick} { return 1 }
	if {[matchattr $opnick b]} {
		if {$modes=="-o $opnick"} {
			set nice "0"
			set botnice "0"
			if {[matchattr [nick2hand $nick $channel] f]} { set nice "1" } 
			if {[matchchanattr [nick2hand $nick $channel] f $channel]} { set nice "1" }
			if {[matchattr [nick2hand $nick $channel] m]} { set nice "1" }
			if {[matchchanattr [nick2hand $nick $channel] m $channel]} { set nice "1" }
			if {[matchattr $opnick o]} { set botnice "1" }
			if {[matchchanattr $opnick o $channel]} { set botnice "1" }
			# If the bots are "nice" I'm going to give it back to them and destroy our enemies
			if {$botnice == "0"} { set nice "1" }
			if {$nice == "0"} { pushmode $channel -o $nick }
			if {$botnice == "1"} { pushmode $channel +o $opnick }
			putlog "Chanscan: $opnick got deoped by $nick on $channel"
		}
	flushmode $channel
	}
}

# # # # LINK ALL COMMAND # # # # - Makes sure that all channels have the +shared flag -
proc link_all {} {
  foreach channel [channels] {
    channel set $channel need-invite "gain-invite $channel"
    channel set $channel need-op "gain-ops $channel"
    channel set $channel need-unban "gain-unban $channel"
    channel set $channel need-limit "gain-limit $channel"
    channel set $channel +shared -greet -statuslog
  }
}

# Additional commands here below . . . . .

# Mass Change - Command (A DCC command that bot owners are only allowed to touch)
bind dcc n masschange dcc:masschange

proc dcc:masschange { hand idx parm } {
	set command "[lindex $parm 0]"
	if {$command == ""} { putdcc $idx "MassChange\[CS\]: Type '.masschange help' for help" ; return 0 }
	if {$command == "help"} { 
		putdcc $idx "MassChange\[CS\]: Help" 
		putdcc $idx "MassChange\[CS\]: - masschange flag2flag <flags2change> <flags2change2>" 
		putdcc $idx "MassChange\[CS\]: - masschange flag2cflag <flag2change> <chanflag2change2>"
	}
	
}


# Startup, loaded at the end :þ
set savedchans { }
link_all
timer 60 link_all
putlog "\[ChanScan\] \[V1.31\] \< A botnet tcl script. Made by Merlin. All Rights Reserved \>"
