summaryrefslogtreecommitdiff
path: root/src/weepinbell/processor/wrapper.clj
blob: be43a5b291c1e741f5960f80b1b0029b6cdce6be (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
(ns weepinbell.processor.wrapper
  "Wrapper component wraps a qualified webmention while processing, part of the pipeline.
   It adds metadata and extra, and return complete webmention map ready for storage."
  (:require [clojure.java.io :as io]
            [weepinbell.http.downloader :refer [download-file]]
            [weepinbell.utils.url :refer [get-base relative? normalize]]
            [weepinbell.metadata.jf2 :as jf2]
            [weepinbell.metadata.jf2-spec]
            [taoensso.timbre :as timbre]
            [weepinbell.utils.digest :refer [digest]]
            [clojure.string :refer [split]]))

(defn- proxy-photo
  "Download a photo to /data/avatars to serve from our server."
  [photo-base raw-photo]
  (let [photo-url (str raw-photo)
          ;; TODO might need to use MIME-type to get ext
        file-ext (str "." (last (split photo-url #"\.")))
        filename  (str (digest photo-url) file-ext)
        local-path (str "data/avatars/" filename)
        public-path (str "/avatars/" filename)]
                 ;; download photo if not exists
    (when-not (.exists (io/file local-path))
      (timbre/info "Downloading author photo to serve locally")
      (download-file photo-url local-path))
    (str photo-base public-path)))

(defn- complete-url
  "Prepend base URL if a URL is relative."
  [source-base url]
  (if (relative? url)
    (normalize (str source-base url))
    url))

;; wrappers
(defn- wrap-webmention-basics
  "Wrap basic webmention data, :source :target :id and :modified.
   Will use current system time in milliseconds for :modified."
  [{:keys [s t]} id]
  {:webmention {:source s, :target t,
                :id (or id (digest (str s t))),
                :modified (System/currentTimeMillis)}})

(defn- wrap-jf2
  "Parses JF2 from source html, and associate :jf2 key to it."
  [data source-html]
  (assoc data :jf2 (-> source-html jf2/parse)))

(defn- wrap-extra
  "Wrap extra data, i.e. proxied photo."
  [data photo-base]
  (let [{:keys [webmention jf2]} data]
    (if-let [photo (get-in jf2 [:author :photo])]
      (assoc data :extra
             {:proxied-photo
              (->> photo
                   (complete-url (get-base (:source webmention)))
                   (proxy-photo photo-base))})
      data)))

(defn wrap
  "Part of the processor pipeline. Takes :source-html from last
   handler of the pipeline, parses data from it, wraps data
   to :new-data in the data map, and proceed with ok signal."
  [data config]
  (when (:ok? data)
    (let [{:keys [source-html wm id]} data
          new-data (-> wm (wrap-webmention-basics id)
                       (wrap-jf2 source-html)
                       (wrap-extra (:base-url config)))]
      (-> data
          (assoc :new-data new-data)
          (assoc :ok? true)))))