####################################################
# by wiebe @ QuakeNet
#
####################################################

#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(x) 0

####################################################
# quakenet:evnt
####################################################
bind evnt - init-server quakenet:evt; bind evnt - userfile-loaded quakenet:evt
proc quakenet:evt { t } {
  if {$t == "init-server"} {
    catch {unbind need -|- * quakenet:need}
    bind notc -|- * quakenet:notc
    bind time - "* * * * *" quakenet:time
    global quakenet quakenetdb
    if {[info exists quakenetdb]} { unset quakenetdb }
    if {![info exists quakenet(x)]} { set quakenet(x) 0 }
    if {![string match "*.quakenet.org:*" $::server]} {
      putlog "QUAKENET: not connected to QuakeNet."
      catch {unbind notc -|- * quakenet:notc}
      catch {unbind time - "* * * * *" quakenet:time}
      catch {unbind need -|- * quakenet:need}
    } elseif {![info exists quakenet(account)] || ![info exists quakenet(password)]} {
      putlog "QUAKENET: account or password not set."
      catch {unbind notc -|- * quakenet:notc}
      catch {unbind time - "* * * * *" quakenet:time}
      catch {unbind need -|- * quakenet:need}
    } else {
      if {$quakenet(x) == 1} { putquick "MODE $::botnick +x" }
      putquick "PRIVMSG Q@CServe.quakenet.org :CHALLENGE" -next
    }
  } elseif {$t == "userfile-loaded"} {
    if {![validuser Q]} {
      addbot Q ""; chattr Q +af; setuser Q hosts "Q!TheQBot@CServe.quakenet.org"
    }
    if {![validuser O]} {
      addbot O ""; chattr O +af; setuser O hosts "O!operserv@operserv.quakenet.org"
      setuser O hosts "NO!control@services4.uk.quakenet.org"
    }
    if {![validuser G]} {
      addbot G ""; chattr G +af; setuser G hosts "G!help@quakenet.org"
    }
  }
}


####################################################
# quakenet:notc
####################################################
bind notc -|- * quakenet:notc
proc quakenet:notc { n u h t d } {
  if {![isbotnick $d]} { return 0 }
  if {"$n!$u" != "Q!TheQBot@CServe.quakenet.org"} { return 0 }
  if {![string match "*.quakenet.org:*" $::server]} { return 0 }
  global quakenet quakenetdb
  if {![info exists quakenet(account)] || ![info exists quakenet(password)]} { return 0 }
  set q "Q@CServe.quakenet.org"
  set a "$quakenet(account)"
  set p "[string range $quakenet(password) 0 9]"
  if {[regexp {^CHALLENGE ([0-9a-f]){32} .*} $t]} {
    set c [lindex [split $t] 1]; set r [md5 "$p $c"]
    putquick "PRIVMSG $q :CHALLENGEAUTH $a $r LEGACY-MD5" -next
  } elseif {$t == "Challenge has either not been requested or has expired."} {
    putserv "PRIVMSG $q :CHALLENGE" -next
  } elseif {$t == "challenge is not available once you have authed." || [string match -nocase "You are now logged in as *." $t] } {
    set quakenetdb(authed) 1
    bind need -|- * quakenet:need
    catch {unbind notc -|- * quakenet:notc}
    catch {unbind time - "* * * * *" quakenet:time}
  } elseif {$t == "Username or password incorrect."} {
    if {![info exists quakenetdb(f)]} { set quakenetdb(f) 0 }
    incr quakenetdb(f)
    if {$quakenetdb(f) > 5} {
      catch {unbind need -|- * quakenet:need}
      catch {unbind notc -|- * quakenet:notc}
      catch {unbind time - "* * * * *" quakenet:time}
      unset quakenetdb
      putlog "QUAKENET: failed to auth with Q, username or password must be incorrect!"
    }
  }
}


####################################################
# quakenet:time
####################################################
bind time - "* * * * *" quakenet:time
proc quakenet:time { n h d m y } {
  if {[expr [clock seconds] - ${::server-online}] < 61} { return 0 }
  if {$::botname == $::botnick} { return 0 }
  global quakenetdb quakenet
  if {![info exists quakenet(account)] || ![info exists quakenet(password)] || ![string match "*.quakenet.org:*" $::server]} {
    catch {unbind notc -|- * quakenet:notc}
    catch {unbind time - "* * * * *" quakenet:time}
    catch {unbind need -|- * quakenet:need}
  } elseif {![info exists quakenetdb(authed)]} {
    putserv "PRIVMSG Q@CServe.quakenet.org :CHALLENGE" -next
    bind notc -|- * quakenet:notc
    catch {unbind need -|- * quakenet:need}
  } elseif {$quakenetdb(authed) == "1"} {
    catch {unbind notc -|- * quakenet:notc}
    catch {unbind time - "* * * * *" quakenet:time}
  }
}


####################################################
# quakenet:need
####################################################
bind need -|- * quakenet:need
proc quakenet:need { c t } {
  global quakenetdb
  if {![info exists quakenetdb(authed)]} { catch {unbind need -|- * quakenet:need}; return 0 }
  set b ""; set t [string tolower $t]; set u ""
  set q "Q@CServe.quakenet.org"
  set g "G"

  if {$t == "op" && [botonchan $c]} {
    if {[matchattr Q b&o $c] && [onchan Q $c]} { lappend b $q }
    if {[matchattr G b&o $c] && [onchan G $c]} { lappend b $g }
    if {$b == ""} { return 0 }
    set b [join $b ,]
    putserv "PRIVMSG $b :OP $c"
  }

  if {[matchattr Q b&o $c] || [matchattr Q b&v $c]} { lappend b $q }
  if {[matchattr G b&o $c] || [matchattr G b&v $c]} { lappend b $g }

  set b [join $b ,]
  if {$b == ""} { return 0 }

  if {[botonchan $c]} { return 0 }
  if {$t == "unban"} {
    if {[matchattr Q b&o $c] || [matchattr Q b&v $c]} { lappend u $q  }
    set u [join $u ,]
    if {$u != ""} { putserv "PRIVMSG $u :UNBANME $c" }
    putserv "PRIVMSG $b :INVITE $c"
  }
  if {$t == "invite"} { putserv "PRIVMSG $b :INVITE $c" }
  if {$t == "limit"} { putserv "PRIVMSG $b :INVITE $c" }
  if {$t == "key"} { putserv "PRIVMSG $b :INVITE $c" }
}


####################################################
# quakenet:dcc
####################################################
bind dcc n auth quakenet:dcc
proc quakenet:dcc { h i t } {
  global quakenetdb quakenet
  if {$::botname == $::botnick} {
    lappend o "QUAKENET: not connected."
  } elseif {![info exists quakenet(account)] || ![info exists quakenet(password)]} {
    lappend o "QUAKENET: account or password not set."
  } elseif {![string match "*.quakenet.org:*" $::server]} {
    lappend o "QUAKENET: not connected to QuakeNet."
  } elseif {![info exists quakenetdb(authed)]} {
    lappend o "QUAKENET: trying to auth with Q - requesting a challenge."
    putserv "PRIVMSG Q@CServe.quakenet.org :CHALLENGE" -next
    bind notc -|- * quakenet:notc
    catch {unbind need -|- * quakenet:need}
  } elseif {$quakenetdb(authed) == 1} {
    lappend o "QUAKENET: already authed to Q."
    catch {unbind notc -|- * quakenet:notc}
    catch {unbind time - "* * * * *" quakenet:time}
  }
  foreach l $o { putidx $i $l }
}


####################################################
# set info for script.tcl
####################################################
set ::scriptdb(quakenet) {
  "provides interaction with QuakeNet services Q, and G. uses challenge auth to auth with Q, requesting invite, op from Q"
}

