Hash tables and .INI files share the same structure, so it's pretty much exactly the same as it would be with .INI files. You just need to remember that hash tables are temporary.

Too lazy to read and/or guess missing details, so here's how I'd do it:
Code:
;Free, create and load the channel's hash table on join.
on me:*:join:#:var %h = cmds. $+ # | hfree -w %h | hmake %h | hload -i %h Commands.db #

;Free up the channel's hash table on part.
on me:*:part:#:hfree -w cmds. $+ #

;Free up the channel's hash table on kick.
on *:kick:#:if ($knick == $me) hfree -w cmds. $+ #

;Free up all the hash tables on disconnect.
on *:disconnect:hfree -w cmds.*

;Unset flood protection variables on connect.
on *:connect:unset %f.*

on *:text:*:#: {
  /*
  Usage: !cadd <command> <user modes> <message>

  Example: !cadd !ohai @- Hello|Hi|Ohai|Go away
  If an operator or regular user says "!ohai", the script will spam 4 lines to the channel.

  <user modes> can be @%+ and whatever else the server might support.
  They're the characters on the left side of user's nick on the nicklist.
  "-" represents regular users in this case.
  */
  if ($1 == !cadd) && ((!%f.cadd) || ($nick == $mid(#,2))) {
    set -eu5 %f.cadd 1
    hadd cmds. $+ # $2-
    hsave -i cmds. $+ # Commands.db #
    describe # $qt($2) command added!
  }
  elseif ((!%f. $+ $1) || ($nick == $mid(#,2))) && ($hget(cmds. $+ #,$1)) {

    ;If you want to replace something, do it here.
    var %x = 1,%m $gettok($v1,1,32),%c $replacex($gettok($v1,2-,32),something random,hello world,omg,oms,$nick,Random User)

    if ($left($nick(#,$nick).pnick,1) isin %m) || ((- isin %m) && ($nick isreg #)) {
      set -eu5 %f. $+ $1 1
      while ($gettok(%c,%x,124)) { describe # $v1 | inc %x }
    }
  }
}

Didn't test it, but it should work.

Last edited by Dazuz; 29/07/16 08:40 AM. Reason: Brainfarts all around