blob: 06e857a78b274b348372991b2fa2ed78ef0b0844 (
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
(ns weepinbell.storage.edn-storage
"EDN file-based storage middle layer.
Entry function is use-store, which makes a valid storage vtable."
(:require [fast-edn.core :as edn]
[clojure.java.io :as io]
[weepinbell.utils.url :refer [get-domain get-target get-path url=]]
[weepinbell.storage.spec]
[clojure.string :refer [join]]))
(defn unload-data
"Write to data file, replacing everything."
[datasource data]
(when-let [data-with-string (map pr-str data)]
(spit datasource (join "\n" data-with-string))))
;; predicates used for filtering webmention
(defn- st-pair-equal-pred [source target wm]
(let [wm-source (get-in wm [:webmention :source])
wm-target (get-in wm [:webmention :target])]
(and (some? source) (some? target)
(some? wm-source) (some? wm-target)
(url= source wm-source)
(url= target wm-target))))
(defn- id-equal-pred [id wm]
(= id (get-in wm [:webmention :id])))
(defn- get-predicate [source target]
(if target
#(st-pair-equal-pred source target %)
#(id-equal-pred source %)))
(defn- domain-equal [domain wm]
(= domain
(-> wm get-target get-domain)))
(defn- path-equal [path wm]
(= path
(-> wm get-target get-path)))
;; end predicates
(defn with-webmentions
"Opens the data file and applies function f to a lazy sequence of parsed Webmentions."
[datasource f]
(with-open [r (io/reader datasource)]
(->> (line-seq r)
(map edn/read-string)
f)))
(defn get-wm
([datasource id] (get-wm datasource id nil))
([datasource source target]
(let [pred (get-predicate source target)]
(with-webmentions datasource
#(first (filter pred %))))))
(defn delete-wm
([datasource id] (delete-wm datasource id nil))
([datasource source target]
(let [pred (get-predicate source target)]
(with-webmentions datasource
#(->> %
(remove pred)
(unload-data datasource))))))
(defn get-wms-by-domain
([datasource domain]
(get-wms-by-domain datasource domain nil))
([datasource domain path]
(with-webmentions datasource
#(cond->> %
true (filter (partial domain-equal domain))
(some? path) (filter (partial path-equal path))
true (sort-by (fn [x] (:modified (:webmention x))))
true vec))))
(defn first-line-empty? [path]
(with-open [rdr (io/reader path)]
(let [line (line-seq rdr)]
(empty? line))))
(defn append-wm
"Append an accepted webmention to .edn data file."
[datasource data]
(let [newline? (if (first-line-empty? datasource) "" "\n")
line (str newline? (pr-str data))]
(spit datasource line :append true)))
(defn update-wm
"Update an existing webmention"
([datasource id new-data]
(delete-wm datasource id)
(append-wm datasource new-data))
([datasource source target new-data]
(delete-wm datasource source target)
(append-wm datasource new-data)))
;; make storage vtable
(def file-exists? #(.exists (io/file %)))
(defn use-store [datasource]
(when (not (file-exists? datasource))
(io/make-parents datasource)
(spit datasource ""))
{:append (partial append-wm datasource)
:update (partial update-wm datasource)
:delete (partial delete-wm datasource)
:get (partial get-wm datasource)
:get-by-domain (partial get-wms-by-domain datasource)})
|