alias md.def return vho
alias md.allowed return vhoqeba

alias md.p.m { 
  var %n = 1,%m
  while ($mid($1,%n,1)) {
    if ($v1 isin $md.allowed) var %m = $addtok(%m,$v1,44)
    inc %n
    if ($calc(%n -1) > $len($1)) break
  }
  return $remove(%m,$chr(44))
}

alias md.start {
  if (!$hget(md)) {
    hmake md
    if ($isfile(modedenial.hsh)) hload md modedenial.hsh
  }
}

alias md.stop { 
  if ($hget(md)) { 
    hsave -o md modedenial.hsh
    hfree md
  }
}

alias md.add {
  if (!$hget(md)) md.start
  if ($1 === -h) return * /md.add [-h] <address> [chan=All|*] [network=All|*] [modes=*]
  var %chan = $iif($wildtok($2-,chan=*,1,32),$gettok($v1,2,61))
  var %net = $iif($wildtok($2-,network=*,1,32),$gettok($v1,2,61))
  var %modes = $iif($wildtok($2-,modes=*,1,32),$md.p.m($gettok($v1,2,61)),$md.def)
  if (!%net) var %net = All
  if (!%chan) var %chan = All
  var %name = $+(%net,;,%chan,;,$1)
  if (!$hget(md,%name)) {
    hadd md %name %modes 
    return * Added $qt($1) to Mode Denial list. ( $+ %modes $+ )
  }
  else return * Error: $qt($1) is already listed.
}

alias md.del {
  if (!$hget(md)) md.start
  var %chan = $iif($wildtok($2-,chan=*,1,32),$gettok($v1,2,61))
  var %net = $iif($wildtok($2-,network=*,1,32),$gettok($v1,2,61))
  var %modes = $iif($wildtok($2-,modes=*,1,32),$md.p.m($gettok($v1,2,61)))
  if (!%net) var %net = All
  if (!%chan) var %chan = All
  var %name = $+(%net,;,%chan,;,$1)
  if ($hget(md,%name)) {
    hdel md %name
    return * Removed $qt($1) from the Mode Denial list. 
  }
  else return * Error: $qt($1) is not listed.
}

alias md.search {
  if (!$hget(md)) md.start
  var %chan = $iif($wildtok($2-,chan=*,1,32),$gettok($v1,2,61))
  var %net = $iif($wildtok($2-,network=*,1,32),$gettok($v1,2,61))
  var %modes = $iif($wildtok($2-,modes=*,1,32),$gettok($v1,2,61))
  var %n = 1
  while ($hget(md,%n).item) {
    var %string = $v1,%addy = $gettok($v1,3,59)
    var %netmatch = $iif($gettok($v1,1,59) == All,*,$v1) 
    var %chanmatch = $iif($gettok(%string,2,59) == All,*,$v1)
    var %full = $+($iif(%netmatch == *,All,$v1),;,$iif(%chanmatch == *,All,$v1),;,%addy)
    if (%addy $iif($chr(42) isin %addy,iswm,isin) $1) && (%netmatch iswm %net) && (%chanmatch iswm %chan) {
      if ((%modes) && (%modes isin $hget(md,%full))) || (!%modes) return %full
    }
    inc %n
  }
}

on *:RAWMODE:#:{
  var %check = $gettok($gettok($1,1,43),1,45)
  var %modes = $hget(md, $md.search($iif($address($2,5),$v1,$2) , $+(network=,$network) $+(chan=,$chan) $+(modes=,%check)) )
  if (%modes) { 
    var %n = 1,%remove
    while ($mid(%check,%n,1)) {
      if ($v1 isin %modes) || ($v1 iswm %modes) var %remove = %remove $+ $v1
      inc %n
    }
    if (%remove) mode $chan $+(-,%remove) $str($2 $+ $chr(32),$len(%remove))
  }
}
