Function: gravatar--service-libravatar

gravatar--service-libravatar is a byte-compiled function defined in gravatar.el.gz.

Signature

(gravatar--service-libravatar ADDR CALLBACK)

Documentation

Find domain that hosts avatars for email address ADDR.

Source Code

;; Defined in /usr/src/emacs/lisp/image/gravatar.el.gz
(defun gravatar--service-libravatar (addr callback)
  "Find domain that hosts avatars for email address ADDR."
  ;; implements https://wiki.libravatar.org/api/
  (save-match-data
    (if (not (string-match ".+@\\(.+\\)" addr))
        (funcall callback "https://seccdn.libravatar.org/avatar")
      (let ((domain (match-string 1 addr))
            (records '(("_avatars-sec" . "https")
                       ("_avatars" . "http")))
            func)
        (setq func
              (lambda (result)
                (cond
                 ((and
                   result               ;there is a result
                   (let* ((answers (dns-get 'answers result))
                          (data (mapcar (lambda (record)
                                          (dns-get 'data (cdr record)))
                                        ;; We may get junk data back (or CNAME;
                                        ;; ignore).
                                        (and (eq (dns-get 'type answers) 'SRV)
                                             answers)))
                          (priorities (mapcar (lambda (r)
                                                (dns-get 'priority r))
                                              data))
                          (max-priority (apply #'max 0 priorities))
                          (sum 0)
                          top)
                     ;; Attempt to find all records with the same maximal
                     ;; priority, and calculate the sum of their weights.
                     (dolist (ent data)
                       (when (= max-priority (dns-get 'priority ent))
                         (setq sum (+ sum (dns-get 'weight ent)))
                         (push ent top)))
                     ;; In case there is more than one maximal priority
                     ;; record, choose one at random, while taking the
                     ;; individual record weights into consideration.
                     (catch 'done
                       (dolist (ent top)
                         (when (and (or (= 0 sum)
                                        (<= 0 (random sum)
                                            (dns-get 'weight ent)))
                                    ;; Ensure that port and domain data are
                                    ;; valid. In case non of the results
                                    ;; were valid, `catch' will evaluate to
                                    ;; nil, and the next cond clause will be
                                    ;; tested.
                                    (<= 1 (dns-get 'port ent) 65535)
                                    (string-match-p "\\`[-.0-9A-Za-z]+\\'"
                                                    (dns-get 'target ent)))
                           (funcall callback
                                    (url-normalize-url
                                     (format "%s://%s:%s/avatar"
                                             (cdar records)
                                             (dns-get 'target ent)
                                             (dns-get 'port ent))))
                           (throw 'done t))
                         (setq sum (- sum (dns-get 'weight ent))))))))
                 ((setq records (cdr records))
                  ;; In case there are at least two methods.
                  (dns-query-asynchronous
                   (concat (caar records) "._tcp." domain)
                   func 'SRV))
                 (t                     ;fallback
                  (funcall callback "https://seccdn.libravatar.org/avatar")))))
        (dns-query-asynchronous
         (concat (caar records) "._tcp." domain)
         func 'SRV t)))))