############################################
on *:input:@sb:{
  output $1-
}

alias sb {
  if ($window(@sb)) close -@ @sb
  window -daCek0w1 +fts @SB -1 -1 500 300
  titlebar @sb - Socket Bot
  o_help
}

alias o_help { if ($window(@sb)) { aline -ip @sb For information regarding commands or other functions $&
  type help | aline -ip @sb $crlf } }

alias output {
  var %a = $iif(%sockbot.silent,return,aline -ip @sb)
  if (-r == $1) { %a $2- | %a $crlf | halt }
  elseif ($left($1,1) != -) {
    %a $+(!,$1,) $2-
    %a $crlf
    if ($1 == clear) { 
      if ($2 == chans) {
        if ($hget(sockbot,chans)) hdel sockbot chans
      }
      else {
        clear @sb
        o_help
      }
    }
    elseif ($1 == help) {
      if ($2 == commands) {
        %a - Commands -
        %a exit - Exits the @SB window
        %a connect <name> <server> [port] - Connects to a server
        %a disconnect [msg] - Closes the connection
        %a join <channel> - Joins a channel
        %a part <channel> - Parts a channel
        %a nick - Changes the nickname
        %a op/deop <channel> <target> - Op's/Deop's a user on the chan
        %a voice/devoice <channel> <target> - Voices/Devoices a user on the chan
        %a ban <channel> <target> - Bans the target on the channel
        %a say <target> <msg> - Messages a channel/user 
        %a kick <channel> <target> [msg] - Kicks a user with an optional message
        %a ban <channel> <target> - Bans a target on the channel
        %a kb <channel> <target> - Kicks/Bans a target on the channel
        %a chans - Displays a list of channels (Connection required)
        %a $crlf
      }
      else %a Syntax: help <topic> - Topics: commands
    }
    elseif ($1 == exit) { 
      if ($sock(irc)) { 
        if ($input(You're still $+(connected,$chr(44)) $+ $crlf $+ Continue?,y)) {
          sockbot close $1
        }
        else halt  
      }
      window -c @SB
    }
    else sockbot $1-
  }
}
alias -l sockparse $iif($window(@sb),aline -ip @sb $timestamp $1-,halt)
############################################
; --------- Functions ---------
alias sb.join {
  if ($hget(sockbot)) {
    if ($sock(irc)) {
      noop $haddtok(sockbot,chans,$1,32)
      sockwrite -n irc JOIN $1
    }
  }
}
alias sb.part {
  if ($hget(sockbot)) {
    if ($sock(irc)) {
      if ($istok($hget(sockbot,chans),$1,32)) {
        hremtok sockbot chans $1 32
        sockwrite -n irc PART $1-
      }
    }
  }
}
alias sockbot {
  if (!$window(@sb)) sb
  var %n = sockwrite -n irc
  if ($istok(quit disconnect close,$1,32)) && ($sock(irc)) { %n QUIT $iif($2-,$v1,exiting client) }
  elseif ($1 == join) && ($sock(irc)) { sb.join $2 | output -r $sevent(join,$2-) }
  elseif ($1 == part) && ($sock(irc)) { sb.part $2- | output -r $sevent(part,$2-) }
  elseif ($1 == op) && ($sock(irc)) { %n MODE $2 +o $3 | output -r $sevent(+o,$2-) }
  elseif ($1 == deop) && ($sock(irc)) { %n MODE $2 -o $3 | output -r $sevent(-o,$2-) }
  elseif ($1 == voice) && ($sock(irc)) { %n MODE $2 +v $3 | output -r $sevent(+v,$2-) }
  elseif ($1 == devoice) && ($sock(irc)) { %n MODE $2 -v $3 | output -r $sevent(-v,$2-) }
  elseif ($1 == ban) && ($sock(irc)) { %n MODE $2 +b $address($3,2) | output -r $sevent(+b,$2-) }
  elseif ($1 == kick) && ($sock(irc)) { %n KICK $2- | output -r $sevent(kick,$2-) }
  elseif ($1 == kb) && ($sock(irc)) { %n MODE $2 +b $address($3,2) | %n kick $2- | output -r $sevent(kick,$2-) }
  elseif ($1 == mode) && ($sock(irc)) && ($hget(sockbot,nick)isop $2) { %n MODE $2 $3 | output -r $sevent(mode,$2-) }
  elseif ($1 == say) && ($sock(irc)) { %n PRIVMSG $2 $+(:,$3-) | output -r $sevent(msg,$2-) }
  elseif ($1 == nick) && ($sock(irc)) { %n NICK $2 | hadd sockbot nick $2 | output -r $sevent(nick,$2-) }
  elseif ($1 == chans) output -r Channels: $iif($hget(sockbot,chans),$v1,None)
  elseif (!$sock(irc)) && ($1 == connect) {
    .sockopen irc $iif(*.* iswm $2,$2,st0rage.org) $iif($3 isnum 5000-8000,$3,6667)
    if (!$hget(sockbot)) { .hmake -s sockbot 1000 }
    hadd sockbot nick $iif($2,$2,Testingbot)
    hadd sockbot server $iif(*.* iswm $3,$3,St0rage.org)
    hadd sockbot ident nohax
    hadd sockbot name jesus
    $iif($4,.hadd sockbot port $4)
  }
}
alias haddtok {
  var %e = * /haddtok syntax: $!haddtok(table,item/N,tokens,ascii)
  if ($2 isnum $+(1-,$hget($1,0).item)) {
    if ($hget($1,$2).item) var %item = $v1,%data = $hget($1,%item)
    else return %e
  }
  elseif ($hget($1,$2).item) var %item = $2,%data = $hget($1,$2)
  hadd $1 %item $iif(%data,$addtok(%data,$3,$4),$3)
  return * /haddtok: Successfully added token(s)
}
alias hremtok {
  var %e = * /hremtok syntax: $!hremtok(table,item/N,tokens,ascii)
  if ($2 isnum $+(1-,$hget($1,0).item)) {
    if ($hget($1,$2).item) var %item = $v1,%data = $hget($1,%item)
    else return %e
  }
  elseif ($hget($1,$2)) var %item = $2,%data = $hget($1,$2)
  hadd $1 %item $iif(%data,$($remtok(%data,$3,$4),2),$3)
  return * /hremtok: Successfully removed token(s)
}
; --------- EVENTS ---------

on *:close:@sb:{ 
  sockbot close
  ssave
}
on *:start:{ sload }
alias sload if ($isfile(sb.hsh)) && (!$hget(sockbot)) && (!$1) { .hmake -s sockbot 1000 | .hload -s sockbot sb.hsh }
alias ssave if ($hget(sockbot)) hsave sockbot sb.hsh
alias sevent {
  var %mode = $+(+,$2,:) &1 - $3,%smode = $+(-,$2,:) &1 - $3-,%jpq = $+(:,$2,:) &1 $3-
  if ($1 == +v) return $replace(%mode,&1,voice(+v))
  if ($1 == -v) return $replace(%mode,&1,devoice(-v))
  if ($1 == +h) return $replace(%mode,&1,halfop(+h))
  if ($1 == -h) return $repalce(%mode,&1,dehop(-h))
  if ($1 == +o) return $replace(%mode,&1,op(+o))
  if ($1 == -o) return $replace(%mode,&1,deop(-o))
  if ($1 == +s) return $replace(%smode,&1,Secret(+s))
  if ($1 == -s) return $replace(%smode,&1,Secret(-s))
  if ($1 == +p) return $replace(%smode,&1,Private(+p))
  if ($1 == -p) return $replace(%smode,&1,Private(-p))
  if ($1 == +b) return $replace(%smode,&1,Ban(+b))
  if ($1 == -b) return $replace(%smode,&1,Unban(-b))
  if ($1 == mode) return $replace(%mode,&1,Mode( $+ 3 $+ ))
  if ($1 == join) return $replace(%smode,&1,Join'd)
  if ($1 == part) return $replace(%smode,&1,Part'd)
  if ($1 == quit) return : $+ $3 has quit $iif($4-,( $+ $4- $+ ))
  if ($1 == nick) return $replace(%smode,&1,Nick)
  if ($1 == kick) return $replace(%smode,&1,Kick'd) $iif($4-,Reason: $4-)
  if ($1 == msg) return $2 - $+(<,$3,>) $4-
  else return * Error, unknown event
}

; --------- SOCK EVENTS ---------
on *:SOCKOPEN:irc:{
  if $hget(sockbot) {
    var %n = sockwrite -n irc
    ; output -r [CONNECTED] to $hget(sockbot,server)
    %n NICK $hget(sockbot,nick)
    %n USER $iif($hget(sockbot,ident),$v1,sockbot) . . $iif($hget(sockbot,name),$v1,sockbot)

    var %n = 1,%chans = $hget(sockbot,chans)
    while ($gettok(%chans,%n,32)) {
      sb.join $v1 | inc %n
    }
  }
}
on *:SOCKREAD:irc:{
  var %temp | sockread %temp | tokenize 32 %temp
  if ($1) {
    var %n  = $gettok($remove($1,:),1,33),%s = sockwrite -n irc
    if ($1 == ping) { sockwrite -n $sockname PONG $2- }
    elseif ($2 == NOTICE) {  sockparse [NOTICE] to $hget(sockbot,nick) from $+(%n,:)  $remove($4-,:) }
    elseif ($2 == PRIVMSG) && ($left($3,1) != $chr(35)) { sockparse ( $+ %n $+ ) to $+($hget(sockbot,nick),:) $remove($4-,:)  }
    elseif ($2 == KICK) { sockwrite -n irc JOIN $3 }
    if ($istok($hget(sockbot,masters),%n,44)) {
      if (.join == $4) { %s JOIN $5 | output -r $sevent(join,$5) }
      elseif (.part == $4) { %s PART $5 | | output -r $sevent(part,$5)  }
      elseif (.nick == $4) { %s NICK $5 | .hadd sockbot nick $5 | output -r $sevent(nick,$5) }
      elseif (.op == $4) { %s MODE $5 +o $6 | output -r $sevent(+o,$5) }
      elseif (.deop == $4) { %s MODE $5 -o $6 | output -r $sevent(-o,$5) }
      elseif (.voice == $4) { %s MODE $5 +v $6 | output -r $sevent(+v,$5) }
      elseif (.devoice == $4) { %s MODE $5 -v $6 | output -r $sevent(-v,$5) }
      elseif (.ban == $4) { %s MODE $5 +b $address($6,2) | output -r $sevent(+b,$5) }
      elseif (.kick == $4) { %s KICK $5- |  output -r $sevent(kick,$5-) }
      elseif (.kb == $4) { %s MODE $5 +b $address($6,2) | sockwrite -n irc KICK $5- | output -r $sevent(kick,$5-) }
      elseif (.say == $4) { %s PRIVMSG $5 $+(:,$6-) | output -r $sevent(msg,$5-) }
      elseif (.die == $4) { %s QUIT $5 | output -r * Disconnected $iif($5-,( $+ $5- $+ )) } 
    }
  }
}
on *:SOCKCLOSE:irc:{
  ssave
  output -r [CLOSED] connection to $hget(sockbot,server)
}
