
# Bot Protection System 23-Jun-97, 11-Jul-97
# Should work on eggdrop versions 1.1, 1.2 and 1.3
# Last update: 26-Jul-98

# by Ernst <ernst@baschny.de>
# http://www.baschny.de/eggdrop/

# v1.0:
# First release

# v1.1 26-Jul-98:
# Also works on eggdrop >1.3.17 ('bind mode' proc was changed)

# - Protects other bots from being kicked or deopped on the channel
#
#   Bots to be protected need to have the +b and the 'protection flag',
#   which can be global or channel specific. The 'protection flag' is:
#      eggdrop 1.1.x:  +2
#      eggdrop 1.2.x:  +2
#      eggdrop 1.3.x:  +P
#
# - Pseudo-bitch mode: Only bost can give ops to other users
#
#   Bots that are allowed to give ops to other users must have a +b and
#   either channel or global +o.

# -----------------------------------------------------------------------------

# Decides which flag is the 'protection flag', depending on egg-version
global numversion
catch { set numversion }
if {[info exist numversion]} {
  if {$numversion >= 1030000} {
    # 1.3 bots
    set pflag P
    set prot_newbot 1
  } {
    # Some other strange bot
    set pflag 2
    set prot_newbot 0
  }
} {
  # 1.1 and 1.2 bots
  set pflag 2
  set prot_newbot 0
}

# Compatibility: 1.1&1.2 vs. 1.3 bots
proc userhasflag { hand flag chan } {
  global prot_newbot
  set flag [string trimleft $flag "+"]
  if {$prot_newbot} {
    # 1.3 bots
    if {[matchattr $hand $flag|$flag $chan]} { return 1 }
    return 0
  } {
    # 1.1 and 1.2 bots
    if {[matchattr $hand $flag]} { return 1 }
    if {[matchchanattr $hand $flag $chan]} { return 1 }
    return 0
  }
}

# Does not people to op someone, if he isn't a +o Bot (pseudo-bitch)
bind mode - *+o* prot_op

proc prot_op { nick host hand chan args } {
  global botnick
  set oppednick [string tolower [lindex $args 1]]
  if {$oppednick == ""} {
    # eggdrop <1.3.17
    set oppednick [string tolower [lindex [lindex $args 0] 1]]
  }
  set oppedhand [nick2hand $oppednick $chan]
  set oppedhost [getchanhost $oppednick $chan]

  # Checks who got opped (+o bots are allowed)
  if {([matchattr $oppedhand b] &&
       [userhasflag $oppedhand o $chan]) || \
      ($oppednick == [string tolower $botnick])
  } {
    return 1
  }

  # Checks who dared to give ops (+o bots and owners are allowed)
  if {[string tolower $nick] == [string tolower $botnick] || \
      [userhasflag $hand n $chan] || \
      ([matchattr $hand b] && [userhasflag $hand o $chan]) || \
      ($nick == "" && $oppedhand != "*")
  } {
    return 1
  }

  # Someone gave ops when he shoudn't? Deops, sends a NOTICE and note to owner
  if {[botisop $chan]} {
    foreach thismaster [userlist n] {
      sendnote ProtSys $thismaster "$nick!$host ($hand) gave ops to $oppednick!$oppedhost ($oppedhand)"
    }
    putserv "MODE $chan -o $oppednick"
    putserv "NOTICE $nick :Don't give ops, the bots take care of this."
  } {
    foreach thismaster [userlist n] {
      sendnote ProtSys $thismaster "$nick!$host ($hand) gave ops to $oppednick!$oppedhost ($oppedhand) (I wasn't op)"
    }
  }
}

# Don't let someone deop a protected bot from the channel
bind mode - *-o* prot_deop

proc prot_deop { nick host hand chan args } {
  global botnick pflag
  set dnick [string tolower [lindex $args 1]]
  if {$dnick == ""} {
    # eggdrop <1.3.17
    set dnick [string tolower [lindex [lindex $args 0] 1]]
  }
  set deophand [nick2hand $dnick $chan]

  # Checks who was deopped
  if {![matchattr $deophand b] || \
      (![userhasflag $deophand $pflag $chan]) || \
      ($dnick == [string tolower $nick]) || \
      ($dnick == [string tolower $botnick])
  } {
    return 1
  }

  # Checks who is it who dared to deop
  if {[string tolower $nick] == [string tolower $botnick] || \
      [userhasflag $hand n $chan] || \
      [userhasflag $hand m $chan] || \
      [matchattr $hand b]
  } {
    return 1
  }

  if {[botisop $chan]} {
    foreach thismaster [userlist n] {
      sendnote ProtSys $thismaster "$nick!$host ($hand) deoped $dnick"
    }
    putserv "MODE $chan -o+o $nick $dnick"
    putserv "KICK $chan $nick :Don't deop $dnick"
  } {
    foreach thismaster [userlist n] {
      sendnote ProtSys $thismaster "$nick!$host ($hand) deoped $dnick (I wasn't op)"
    }
  }
}

# Don't let someone kick a protected bot from the channel
bind kick - * prot_kick

proc prot_kick {nick host hand chan knick reason} {
  global botnick pflag
  set chan [string tolower $chan]

  set knick [string tolower $knick]
  set kickhand [nick2hand $knick $chan]

  # Checks who was kicked
  if {![matchattr $kickhand b] || \
      (![userhasflag $kickhand $pflag $chan]) || \
      ($knick == [string tolower $nick]) || \
      ($knick == [string tolower $botnick])
  } {
    return 1
  }
  # Checks who is it who dared to deop
  if {[string tolower $nick] == [string tolower $botnick] || \
      [userhasflag $hand n $chan] || \
      [userhasflag $hand m $chan] || \
      [matchattr $hand b]
  } {
    return 1
  }

  if {[botisop $chan]} {
    foreach thismaster [userlist n] {
      sendnote ProtSys $thismaster "$nick!$host ($hand) kicked $knick"
    }
    putserv "MODE $chan -o $nick"
    putserv "KICK $chan $nick :Don't kick $knick"
  } {
    foreach thismaster [userlist n] {
      sendnote ProtSys $thismaster "$nick!$host ($hand) kicked $knick (I wasn't op)"
    }
  }
}

