anchor.diff:  (define-constant +min-retry+ 30)
   (define-constant +max-expire+ 86400)
   
  +(define-condition required-argument-missing (error)
  +  ()
  +  (:report (lambda (condition stream)
  +             (format stream "One or more required arguments missing or nil."))))
  +
  +(deftype pushover-priority () `(integer ,+priority-lowest+ ,+priority-emergency+))
   
   (defun send-pushover (&key destination-key title message (token *default-app-token*) device url-title url (priority +priority-normal+) timestamp sound html callback retry expire)
     "Send a Pushover using your app's `TOKEN' to user/group identified by `DESTINATION-KEY', containing `MESSAGE'.
  
positive.code: 
  ;;; TODO.
  
  (defparameter *default-app-token* "")
  
  (define-constant +priority-lowest+ -2)
  (define-constant +priority-low+ -1)
  
negative.code: - `CALLBACK' - an URL for messages that Pushover servers will submit a POST request to when the message was acknowledged by recipent.
  - `RETRY' - how often (in seconds) Pushover should resend the same notification. Minimum value - 30 seconds.
  - `EXPIRE' - for how many seconds the message will continue to be retried unless acknowledged beforehand. Maximum value - 86400 seconds (24 hours)."
  
    ;; rudimentary parameter validation
    (unless (and token
                 destination-key
                 message)
      (signal 'required-argument-missing))
    
    (check-type priority pushover-priority "a valid Pushover message priority value")
    (check-type retry (or null (integer +min-retry+ *)) "a valid Pushover retry time value")
    (check-type expire (or null (integer 0 +max-expire+)) "a valid Pushover expire time value")
  
    ;; actual sending
    (%send-pushover destination-key title message token device url-title url priority timestamp sound html callback retry expire))
  
  (defun %send-pushover (destination-key title message token device url-title url priority timestamp sound html callback retry expire)
    "Sends the actual Pushover message request. Does not do any kind of type/sanity checking on parameters.
  Refer to `SEND-PUSHOVER' documentation for meaning of parameters."
    (let ((params (remove-if #'null
                             (mapcar (lambda (name value)
                                       (when value
                                         (cons name value)))
                                     (list "token" "user" "message" "title" "device" "url" "url_title" "priority" "timestamp" "sound" "html" "callback" "retry" "expire")
                                     (list token destination-key message title device url url_title priority timestamp sound (when html 1) callback retry expire)))))
      (drakma:http-request *pushover-api-endpoint-url*
                           :method :post
                           :external-format-out :UTF-8
                           :parameters params
                           :content "hack"
                           :content-length 4)))
  
  
  ;;; TODO call for querying receipts
  