anchor.diff:                       :apology-msg (gethash "apology-msg" object)
                        :punish-msg (gethash "punish-msg" object)
                        :active-on (gethash "active-on" object))))
  -        (v:info :rules "Loaded ~d rules." (hash-table-count data))))))
  +        (v:info :rules "Loaded ~d rules." (hash-table-count data)))))
  +  (setf (whitelist rules) (config-tree :rules :whitelist)))
   
   (defmethod stop ((rules rules))
     (with-open-file (stream *save-file* :direction :output :if-exists :supersede :if-does-not-exist :create)
       (yason:encode (rules rules) stream)
  -    (v:info :rules "Saved ~d rules." (hash-table-count (rules rules)))))
  +    (v:info :rules "Saved ~d rules." (hash-table-count (rules rules))))
  +  (setf (config-tree :rules :whitelist) (whitelist rules)))
   
   (defun rule-format (event rule probation-count message)
     (format-message event message
  
positive.code: 
  (defparameter *apology-regex* (cl-ppcre:create-scanner "^(Colleen:\\s*)?(Sorry for|I apologize for|I'm sorry for)\\s+(breaking|violating|breaching|not minding|disregarding|saying)?\\s*(the\\s+)?(\\w+).*" :case-insensitive-mode T))
  (define-handler (privmsg-event event) ()
    (let ((name-format (format NIL "~a/~a" (name (server event)) (nick event)))
          (server-format (format NIL "~a/~a" (name (server event)) (channel event))))
      (unless (cl-ppcre:register-groups-bind (NIL NIL NIL NIL name) (*apology-regex* (message event))
                (let ((rule (gethash name (rules module))))
                  (when (and rule (find server-format (active-on rule) :test #'string-equal))
                    (if (gethash name-format (users-on-probation rule))
                        (progn
                          (v:info :rules "~a is apologizing for ~a" (nick event) name)
                          (remhash name-format (users-on-probation rule))
                          (respond event (rule-format event rule (probation rule) (apology-msg rule))))
                        (respond event "~a: You don't need to apologize for ~a, silly!" (nick event) (name rule))))
                  T))
        
        (loop for rule being the hash-value of (rules module)
           if (and (find server-format (active-on rule) :test #'string-equal)
                   (cl-ppcre:scan (regex rule) (string-downcase (message event))))
           do 
             (let ((probation-count (gethash name-format (users-on-probation rule))))
               (unless probation-count
                 (setf probation-count (probation rule)))
               (setf probation-count (1- probation-count))
  
               (if (> 0 probation-count)
                   (let ((message (rule-format event rule probation-count (punish-msg rule))))
                     (v:warn :rules "~a violated rule ~a" (nick event) (name rule))
                     (remhash name-format (users-on-probation rule))
                     (case (rule-type rule)
                       (:KICK (irc:kick (channel event) (nick event) :reason message))
                       (:BAN (irc:channel-mode (channel event) "+b" :extra (nick event))
                             (irc:kick (channel event) (nick event) :reason message))
                       (:KILL (irc:kill (nick event) message))
                       (:MUTE (irc:channel-mode (channel event) "-v" :extra (nick event))
                              (respond event message))
                       (:SCOLD (respond event message))
                       (:REWARD (respond event message))
                       (T (respond event "WTF?"))))
                   (progn
                     (v:warn :rules "~a breached rule ~a" (nick event) (name rule))
                     (setf (gethash name-format (users-on-probation rule)) probation-count)
                     (respond event (rule-format event rule probation-count (breach-msg rule))))))))))
  
  (define-group rules)
  
  
negative.code:                 (delete (format NIL "~a/~a" server channel) (active-on rule) :test #'string-equal))
            (respond event "Rule ~a has been deactivated for ~a/~a" name server channel))
          (respond event "A rule with that name does not exist!"))))
  
  (define-command (rules whitelisted) () (:documentation "Show a list of all whitelisted users.")
    (respond event "Whitelist: ~{~a~^, ~}" (whitelist module)))
  
  (define-command (rules whitelist) (&optional nick server) (:authorization T :documentation "Add a user to the whitelist.")
    (unless nick (setf nick (nick event)))
    (unless server (setf server (name (server event))))
    (pushnew (format NIL "~a/~a" (string-upcase server) (string-upcase nick))
             (whitelist module) :test #'string-equal)
    (respond event "User ~a whitelisted!" nick))
  
  (define-command (rules blacklist) (&optional nick server) (:authorization T :documentation "Remove a user from the whitelist.")
    (unless nick (setf nick (nick event)))
    (unless server (setf server (name (server event))))
    (setf (whitelist module)
          (delete (format NIL "~a/~a" (string-upcase server) (string-upcase nick))
                  (whitelist module) :test #'string-equal))
    (respond event "User ~a removed from the whitelist!" nick))
  