#by wiebe @ QuakeNet

#script to auth with the Q bot on quakenet
#script uses CHALLENGEAUTH command on Q to auth
#script checks servername and Q's user@host
#script checks to make sure the challenge given is valid

#set Q or L +o for each channel your bot's account has access on
#giving +v to Q/L, makes the bot use INVITE to get on the channel, but never requests ops
#chanlev +v on L is enough to use invite, for Q at least +o is needed
#  if the channel lost all ops, bot tries to request op from O (operserv)

#set here the Q account to use
set quakenet(account) Q_account

#set here the password
set quakenet(password) password

#use usermode x?
#0=no , 1=yes
set quakenet(umodex) 0



#connect event
bind evnt - init-server quakenet:connect

proc quakenet:connect { type } {
  global quakenet quakenetdb
  if { [info exists quakenetdb] } { unset quakenetdb }
  if { ![string match *.quakenet.org [lindex [split $::server :] 0]] } { return 0 }
  if { [info exists quakenet(umodex)] && [string equal $quakenet(umodex) 1] } { putserv "MODE $::botnick +x" }
  if { ![info exists quakenet(account)] || ![info exists quakenet(password)] } { return 0 }
  putquick "PRIVMSG Q@CServe.quakenet.org :CHALLENGE" -next
}



#notice from Q
bind notc -|- "AUTH'd successfully." quakenet:qnotice
bind notc -|- "CHALLENGEAUTH'd successfully." quakenet:qnotice
bind notc -|- "CHALLENGE MD5 ????????????????????????????????" quakenet:qnotice
bind notc -|- "Either you haven't requested a challenge yet or your one expired." quakenet:qnotice
bind notc -|- "You are already authed." quakenet:qnotice

proc quakenet:qnotice { nick uhost handle text dest } {
  if { ![isbotnick $dest] } { return 0 }
  if { ![string equal $nick!$uhost Q!TheQBot@CServe.quakenet.org] } { return 0 }
  if { ![string match *.quakenet.org [lindex [split $::server :] 0]] } { return 0 }
  global quakenet quakenetdb

  if { ![info exists quakenet(account)] || ![info exists quakenet(password)] } { return 0 }

#challenge
  if { [regexp {^CHALLENGE MD5 ([0-9a-z]){32}$} $text] } {
    set challenge [lindex [split $text] 2]
    putquick "PRIVMSG Q@CServe.quakenet.org :CHALLENGEAUTH $quakenet(account) [md5 "[string range $quakenet(password) 0 9] $challenge"]" -next
  }

#no challenge
  if { [string equal $text "Either you haven't requested a challenge yet or your one expired."] } {
    putserv "PRIVMSG Q@CServe.quakenet.org :CHALLENGE" -next
  }

#already authed
  if { [string equal $text "You are already authed."] } {
    if { ![info exists quakenetdb(authed)] } { set quakenetdb(authed) 1 }
    if { ![info exists quakenetdb(account)] } { putserv "WHOIS $::botnick" }
  }

#success
  if { [string equal $text "CHALLENGEAUTH'd successfully."] || [string equal $text "AUTH'd successfully."] } {
    set quakenetdb(authed) 1
    putserv "WHOIS $::botnick"
  }
}



#raw 330 to get account
bind raw - 330 quakenet:raw

proc quakenet:raw { source numeric text } {
  if { ![string equal $numeric 330] } { return 0 }
  if { ![isbotnick [lindex [split $text] 1]] } { return 0 }
  global quakenetdb
  set quakenetdb(account) [lindex [split $text] 2]
  set quakenetdb(authed) 1
}



#check each minute if bot needs to auth
bind time - "* * * * *" quakenet:time

proc quakenet:time { mi ho da mo ye } {
  if { [string equal $::botname $::botnick] } { return 0 }
  global quakenetdb quakenet
  if { ![info exists quakenet(account)] || ![info exists quakenet(password)] } { return 0 }
  if { ![string match *.quakenet.org [lindex [split $::server :] 0]] } { return 0 }
  if { ![info exists quakenetdb(authed)] } {
    putserv "PRIVMSG Q@CServe.quakenet.org :CHALLENGE" -next
  } elseif { ![info exists quakenetdb(account)] } {
    putserv "WHOIS $::botnick"
  }
  if { ![validuser Q] } {
    addbot Q ""
    chattr Q +a
    setuser Q hosts Q!TheQBot@CServe.quakenet.org
  }
  if { ![validuser L] } {
    addbot L ""
    chattr L +a
    setuser L hosts L!TheLBot@lightweight.quakenet.org
  }
  if { ![validuser O] } {
    addbot O ""
    setuser O hosts O!operserv@operserv.quakenet.org
  }
}



#need
bind need - * quakenet:need

proc quakenet:need { chan type } {
  global quakenetdb
  if { ![info exists quakenetdb(authed)] } { return 0 }
  set target ""

#op
  if { [string equal -nocase $type op] && [botonchan $chan] } {
    if { [matchattr Q b&o $chan] && [onchan Q $chan] } { lappend target Q@CServe.quakenet.org }
    if { [matchattr L b&o $chan] && [onchan L $chan] } {
      if { [string equal $target ""] } { lappend target L@lightweight.quakenet.org }
    }
    if { ![string equal $target ""] } {
      set target [join $target ,]
      putserv "PRIVMSG $target :OP $chan"
    } elseif { [matchattr Q b&o $chan] || [matchattr L b&o $chan] } {
      #set o 0
      #foreach nick [chanlist $chan] { if { [isop $nick $chan] } { incr o 1 } }
      #if { [string equal $o 0] } { putserv "PRIVMSG O@operserv.quakenet.org :REQUESTOP $chan" }
    }
  }

  if { [matchattr Q b&o $chan] || [matchattr Q b&v $chan] } { lappend target Q@CServe.quakenet.org }
  if { [matchattr L b&o $chan] || [matchattr L b&v $chan] } {
    if { [string equal $target ""] } { lappend target L@lightweight.quakenet.org }
  }

  if { [string equal $target ""] } { return 0 }
  set target [join $target ,]

#unban
  if { [string equal -nocase $type unban] && ![botonchan $chan] } { putserv "PRIVMSG $target :INVITE $chan" }

#invite
  if { [string equal -nocase $type invite] && ![botonchan $chan] } { putserv "PRIVMSG $target :INVITE $chan" }

#limit
  if { [string equal -nocase $type limit] && ![botonchan $chan] } { putserv "PRIVMSG $target :INVITE $chan" }

#key
  if { [string equal -nocase $type key] && ![botonchan $chan] } { putserv "PRIVMSG $target :INVITE $chan" }
}

