Blame


1 ddc03123 2020-03-28 op (ns blog.core
2 5e8f809e 2020-06-27 op (:require
3 52f2ea18 2020-10-03 op [blog.gemini :as gemini]
4 d8c72311 2021-10-12 op [blog.http :as http]
5 d8c72311 2021-10-12 op [blog.net-gemini :as net-gemini]
6 d8c72311 2021-10-12 op [blog.rss :as rss]
7 5e8f809e 2020-06-27 op [blog.time :as time]
8 5e8f809e 2020-06-27 op [clojure.edn :as edn]
9 5e8f809e 2020-06-27 op [clojure.java.io :as io]
10 5e8f809e 2020-06-27 op [clojure.java.shell :refer [sh]]
11 5e8f809e 2020-06-27 op [ring.adapter.jetty :as jetty]
12 5e8f809e 2020-06-27 op [ring.middleware.content-type :refer [wrap-content-type]]
13 5e8f809e 2020-06-27 op [ring.middleware.resource :refer [wrap-resource]])
14 0ae518ce 2020-11-19 op (:import (java.io File)
15 0ae518ce 2020-11-19 op (java.nio.file Files Paths))
16 5e8f809e 2020-06-27 op (:gen-class))
17 ddc03123 2020-03-28 op
18 ddc03123 2020-03-28 op (defn copy-file [src dst]
19 ddc03123 2020-03-28 op (with-open [in (io/input-stream (io/file src))
20 ddc03123 2020-03-28 op out (io/output-stream (io/file dst))]
21 ddc03123 2020-03-28 op (io/copy in out)))
22 ddc03123 2020-03-28 op
23 52f2ea18 2020-10-03 op (defn post [{:keys [slug gemtext?] :as p}]
24 0ca1be33 2020-12-30 op (let [ext (if gemtext? ".gmi" ".md")
25 0ca1be33 2020-12-30 op path (str "posts/" slug ext)
26 0ca1be33 2020-12-30 op file (io/resource path)]
27 0ca1be33 2020-12-30 op (when-not file
28 0ca1be33 2020-12-30 op (throw (ex-info "51: post not found" {:slug slug
29 0ca1be33 2020-12-30 op :gemtext? gemtext?
30 0ca1be33 2020-12-30 op :path path})))
31 52f2ea18 2020-10-03 op (-> p
32 0ca1be33 2020-12-30 op (assoc :body (slurp file))
33 52f2ea18 2020-10-03 op (update :date time/parse))))
34 ddc03123 2020-03-28 op
35 d72c4e8f 2020-10-05 op (def pages (atom nil))
36 ddc03123 2020-03-28 op (def per-tag (atom {}))
37 ddc03123 2020-03-28 op (def posts (atom []))
38 ddc03123 2020-03-28 op
39 ddc03123 2020-03-28 op (defn add-post! [m]
40 ddc03123 2020-03-28 op (let [p (post m)]
41 ddc03123 2020-03-28 op (swap! posts conj p)
42 ddc03123 2020-03-28 op (doseq [t (:tags m)]
43 ddc03123 2020-03-28 op (swap! per-tag update t conj p))))
44 ddc03123 2020-03-28 op
45 5e8f809e 2020-06-27 op (defn load-posts! []
46 5e8f809e 2020-06-27 op (reset! per-tag {})
47 5e8f809e 2020-06-27 op (reset! posts [])
48 5e8f809e 2020-06-27 op (doseq [p (-> "posts.edn"
49 5e8f809e 2020-06-27 op io/resource
50 5e8f809e 2020-06-27 op slurp
51 5e8f809e 2020-06-27 op edn/read-string)]
52 5e8f809e 2020-06-27 op (add-post! p)))
53 ddc03123 2020-03-28 op
54 d72c4e8f 2020-10-05 op (defn load-pages! []
55 d72c4e8f 2020-10-05 op (reset! pages (->> "pages.edn"
56 d72c4e8f 2020-10-05 op io/resource
57 d72c4e8f 2020-10-05 op slurp
58 d72c4e8f 2020-10-05 op edn/read-string
59 d72c4e8f 2020-10-05 op (map (fn [{:keys [slug] :as p}]
60 d72c4e8f 2020-10-05 op (assoc p :body (as-> slug $
61 d72c4e8f 2020-10-05 op (str "pages/" $ ".gmi")
62 d72c4e8f 2020-10-05 op (io/resource $)
63 d72c4e8f 2020-10-05 op (slurp $))))))))
64 d72c4e8f 2020-10-05 op
65 ddc03123 2020-03-28 op (defn create-dirs! []
66 ddc03123 2020-03-28 op (doseq [d ["resources/out"
67 52f2ea18 2020-10-03 op "resources/out/gemini"
68 d72c4e8f 2020-10-05 op "resources/out/gemini/pages"
69 52f2ea18 2020-10-03 op "resources/out/gemini/post"
70 52f2ea18 2020-10-03 op "resources/out/gemini/tag"
71 9a594f34 2020-10-14 op "resources/out/gemini/img"
72 0ae518ce 2020-11-19 op "resources/out/gemini/cgi"
73 52f2ea18 2020-10-03 op "resources/out/http"
74 52f2ea18 2020-10-03 op "resources/out/http/css"
75 d72c4e8f 2020-10-05 op "resources/out/http/pages"
76 52f2ea18 2020-10-03 op "resources/out/http/post"
77 52f2ea18 2020-10-03 op "resources/out/http/tag"
78 52f2ea18 2020-10-03 op "resources/out/http/img"]]
79 ddc03123 2020-03-28 op (.. (File. d) mkdirs)))
80 ddc03123 2020-03-28 op
81 6f373e6b 2021-05-31 op (def gemini-post :gemtext?)
82 52f2ea18 2020-10-03 op
83 52f2ea18 2020-10-03 op (defn post-pages [{:keys [proto]}]
84 52f2ea18 2020-10-03 op (let [tags (keys @per-tag)
85 52f2ea18 2020-10-03 op ext (if (= proto :gemini) ".gmi" ".html")
86 c7d750b3 2021-08-03 op ffn (if (= proto :gemini) gemini-post identity)
87 c7d750b3 2021-08-03 op ffn' #(when (ffn %)
88 c7d750b3 2021-08-03 op (not (:draft? %)))]
89 ddc03123 2020-03-28 op (map-indexed (fn [i posts]
90 ddc03123 2020-03-28 op {:filename (if (= i 0)
91 52f2ea18 2020-10-03 op (str "index" ext)
92 52f2ea18 2020-10-03 op (str (inc i) ext))
93 ddc03123 2020-03-28 op :tags tags
94 ddc03123 2020-03-28 op :nth (inc i)
95 ddc03123 2020-03-28 op :posts posts
96 ddc03123 2020-03-28 op :has-next true
97 ddc03123 2020-03-28 op :has-prev true})
98 c7d750b3 2021-08-03 op (partition-all 6 (filter ffn' @posts)))))
99 ddc03123 2020-03-28 op
100 ddc03123 2020-03-28 op (defn fix-next-last
101 ddc03123 2020-03-28 op "Fix the :has-prev/:has-next for the post pages. This assumes
102 ddc03123 2020-03-28 op that `(not (empty? post-pages))`"
103 ddc03123 2020-03-28 op [post-pages]
104 ddc03123 2020-03-28 op (-> post-pages
105 ddc03123 2020-03-28 op (->> (into []))
106 ddc03123 2020-03-28 op (update 0 assoc :has-prev false)
107 ddc03123 2020-03-28 op (update (dec (count post-pages)) assoc :has-next false)))
108 ddc03123 2020-03-28 op
109 d72c4e8f 2020-10-05 op (defn render-pages [pagefn proto ext]
110 d72c4e8f 2020-10-05 op (doseq [page @pages
111 d72c4e8f 2020-10-05 op :let [{:keys [slug]} page
112 d72c4e8f 2020-10-05 op filename (str "resources/out/"
113 d72c4e8f 2020-10-05 op (name proto) "/pages/"
114 d72c4e8f 2020-10-05 op slug ext)]]
115 d72c4e8f 2020-10-05 op (spit filename
116 d72c4e8f 2020-10-05 op (pagefn page))))
117 d72c4e8f 2020-10-05 op
118 52f2ea18 2020-10-03 op (defn render-post-list [viewfn proto]
119 52f2ea18 2020-10-03 op (doseq [p (fix-next-last (post-pages {:proto proto}))
120 ddc03123 2020-03-28 op :let [{:keys [filename]} p]]
121 52f2ea18 2020-10-03 op (spit (str "resources/out/" (name proto) "/" filename)
122 52f2ea18 2020-10-03 op (viewfn p))))
123 ddc03123 2020-03-28 op
124 52f2ea18 2020-10-03 op (defn render-post [viewfn proto ext {s :slug, :as post}]
125 52f2ea18 2020-10-03 op (spit (str "resources/out/" (name proto) "/post/" s ext)
126 52f2ea18 2020-10-03 op (viewfn post)))
127 ddc03123 2020-03-28 op
128 52f2ea18 2020-10-03 op (defn render-tags [viewfn proto ext tags]
129 52f2ea18 2020-10-03 op (spit (str "resources/out/" (name proto) "/tags" ext)
130 52f2ea18 2020-10-03 op (viewfn tags)))
131 ddc03123 2020-03-28 op
132 52f2ea18 2020-10-03 op (defn render-tag [viewfn proto ext tag posts]
133 52f2ea18 2020-10-03 op (spit (str "resources/out/" (name proto) "/tag/" tag ext)
134 52f2ea18 2020-10-03 op (viewfn tag posts)))
135 ddc03123 2020-03-28 op
136 4f9bd2e2 2020-03-30 op (defn render-rss []
137 441c3bcd 2020-11-19 op (let [gemposts (->> @posts
138 441c3bcd 2020-11-19 op (filter gemini-post)
139 441c3bcd 2020-11-19 op (map #(dissoc % :body)))]
140 441c3bcd 2020-11-19 op (spit (str "resources/out/gemini/rss.xml")
141 441c3bcd 2020-11-19 op (rss/feed #(str "gemini://gemini.omarpolo.com/post/" % ".gmi")
142 441c3bcd 2020-11-19 op gemposts))
143 441c3bcd 2020-11-19 op (spit (str "resources/out/gemini/rss.gmi")
144 441c3bcd 2020-11-19 op (gemini/feed-page gemposts)))
145 52f2ea18 2020-10-03 op (spit (str "resources/out/http/rss.xml")
146 bade790b 2020-11-05 op (rss/feed #(str "https://www.omarpolo.com/post/" % ".html") @posts)))
147 4f9bd2e2 2020-03-30 op
148 38646594 2021-02-13 op (defn generate-robots-txt []
149 6f373e6b 2021-05-31 op (spit "resources/out/gemini/robots.txt" "# block some bots from accessing gempkg/man
150 38646594 2021-02-13 op User-agent: archiver
151 38646594 2021-02-13 op Disallow: /cgi/gempkg/
152 38646594 2021-02-13 op
153 6f373e6b 2021-05-31 op User-agent: researcher
154 38646594 2021-02-13 op Disallow: /cgi/gempkg/
155 38646594 2021-02-13 op
156 6f373e6b 2021-05-31 op User-agent: archiver
157 6f373e6b 2021-05-31 op Disallow: /cgi/man/
158 6f373e6b 2021-05-31 op
159 38646594 2021-02-13 op User-agent: researcher
160 6f373e6b 2021-05-31 op Disallow: /cgi/man/
161 38646594 2021-02-13 op "))
162 38646594 2021-02-13 op
163 ddc03123 2020-03-28 op (defn copy-dir
164 0ae518ce 2020-11-19 op "Copy the content of resources/`dir` to resources/out/`proto`/`dir`,
165 0ae518ce 2020-11-19 op assuming these two directories exists."
166 9a594f34 2020-10-14 op [dir proto]
167 0ae518ce 2020-11-19 op ;; java sucks at files
168 0ae518ce 2020-11-19 op (sh "cp" "-a"
169 0ae518ce 2020-11-19 op (str "resources/" dir)
170 0ae518ce 2020-11-19 op (str "resources/out/" proto "/")))
171 ddc03123 2020-03-28 op
172 ddc03123 2020-03-28 op (defn copy-assets
173 ddc03123 2020-03-28 op "Copy css and images to their places"
174 ddc03123 2020-03-28 op []
175 9a594f34 2020-10-14 op (copy-dir "img" "http")
176 9a594f34 2020-10-14 op (copy-dir "img" "gemini")
177 c7d750b3 2021-08-03 op (copy-dir "dots" "http")
178 c7d750b3 2021-08-03 op (copy-dir "dots" "gemini")
179 52f2ea18 2020-10-03 op (copy-file "resources/favicon.ico" "resources/out/http/favicon.ico")
180 52f2ea18 2020-10-03 op (copy-file "resources/css/style.css" "resources/out/http/css/style.css"))
181 ddc03123 2020-03-28 op
182 0ae518ce 2020-11-19 op (defn copy-cgi
183 0ae518ce 2020-11-19 op "Copy cgi scripts to their place."
184 0ae518ce 2020-11-19 op []
185 0ae518ce 2020-11-19 op (copy-dir "cgi" "gemini"))
186 0ae518ce 2020-11-19 op
187 52f2ea18 2020-10-03 op (comment (build)
188 40ca3ee3 2020-12-28 op (copy-cgi)
189 52f2ea18 2020-10-03 op (count (filter gemini-post @posts))
190 52f2ea18 2020-10-03 op (gemini/post-page (first @posts))
191 52f2ea18 2020-10-03 op )
192 52f2ea18 2020-10-03 op
193 5e8f809e 2020-06-27 op (defn build
194 ddc03123 2020-03-28 op "Build the blog"
195 ddc03123 2020-03-28 op []
196 ddc03123 2020-03-28 op (create-dirs!)
197 ddc03123 2020-03-28 op (copy-assets)
198 0ae518ce 2020-11-19 op (copy-cgi)
199 4f9bd2e2 2020-03-30 op (render-rss)
200 38646594 2021-02-13 op (generate-robots-txt)
201 d72c4e8f 2020-10-05 op (doseq [[proto ffn ext homefn postfn tagsfn tagfn pagefn]
202 d72c4e8f 2020-10-05 op [[:http identity ".html" http/home-page http/post-page http/tags-page http/tag-page http/custom-page]
203 d72c4e8f 2020-10-05 op [:gemini gemini-post ".gmi" gemini/home-page gemini/post-page gemini/tags-page gemini/tag-page gemini/custom-page]]]
204 d72c4e8f 2020-10-05 op (render-pages pagefn proto ext)
205 52f2ea18 2020-10-03 op (render-post-list homefn proto)
206 52f2ea18 2020-10-03 op (doseq [p (filter ffn @posts)]
207 52f2ea18 2020-10-03 op (render-post postfn proto ext p))
208 52f2ea18 2020-10-03 op (render-tags tagsfn proto ext (keys @per-tag))
209 52f2ea18 2020-10-03 op (doseq [t @per-tag
210 52f2ea18 2020-10-03 op :let [[tag posts] t]]
211 52f2ea18 2020-10-03 op (render-tag tagfn proto ext (name tag) (filter ffn posts)))))
212 ddc03123 2020-03-28 op
213 ddc03123 2020-03-28 op (def j (atom nil))
214 ddc03123 2020-03-28 op
215 5e8f809e 2020-06-27 op (defn serve
216 ddc03123 2020-03-28 op "Serve a preview"
217 ddc03123 2020-03-28 op []
218 ddc03123 2020-03-28 op (reset!
219 ddc03123 2020-03-28 op j
220 ddc03123 2020-03-28 op (jetty/run-jetty (-> (fn [_] {:status 404, :body "not found"})
221 ddc03123 2020-03-28 op (wrap-resource "out")
222 ddc03123 2020-03-28 op (wrap-content-type))
223 30bd347e 2020-08-04 op {:port 3030
224 ddc03123 2020-03-28 op :join? false})))
225 ddc03123 2020-03-28 op
226 5e8f809e 2020-06-27 op (defn clean
227 60905fa3 2020-03-29 op "clean the output directory"
228 60905fa3 2020-03-29 op []
229 52f2ea18 2020-10-03 op (sh "rm" "-rf" "resources/out/http/")
230 52f2ea18 2020-10-03 op (sh "rm" "-rf" "resources/out/gemini/"))
231 60905fa3 2020-03-29 op
232 4696276a 2020-09-22 op (defn local-deploy
233 4696276a 2020-09-22 op "Copy the files to the local server"
234 4696276a 2020-09-22 op []
235 52f2ea18 2020-10-03 op (sh "rsync" "-r" "--delete" "resources/out/http/" "/var/www/omarpolo.local/"))
236 4696276a 2020-09-22 op
237 5e8f809e 2020-06-27 op (defn deploy
238 ddc03123 2020-03-28 op "Copy the files to the server"
239 ddc03123 2020-03-28 op []
240 52f2ea18 2020-10-03 op (sh "rsync" "-r" "--delete" "resources/out/http/" "op:sites/www.omarpolo.com/")
241 38646594 2021-02-13 op (sh "rsync" "-r" "--delete" "resources/out/gemini/" "op:gemini/gemini.omarpolo.com"))
242 d8c72311 2021-10-12 op
243 d8c72311 2021-10-12 op (defn antenna
244 d8c72311 2021-10-12 op "Ping antenna"
245 d8c72311 2021-10-12 op []
246 5dd19ade 2021-10-16 op (net-gemini/ping-antenna "gemini://gemini.omarpolo.com"))
247 ddc03123 2020-03-28 op
248 ddc03123 2020-03-28 op (defn stop-jetty []
249 ddc03123 2020-03-28 op (.stop @j)
250 ddc03123 2020-03-28 op (reset! j nil))
251 ddc03123 2020-03-28 op
252 5e8f809e 2020-06-27 op (defn -main [& actions]
253 5e8f809e 2020-06-27 op (load-posts!)
254 d72c4e8f 2020-10-05 op (load-pages!)
255 5e8f809e 2020-06-27 op (doseq [action actions]
256 5e8f809e 2020-06-27 op (case action
257 d8c72311 2021-10-12 op "clean" (clean)
258 d8c72311 2021-10-12 op "build" (build)
259 d8c72311 2021-10-12 op "deploy" (deploy)
260 d8c72311 2021-10-12 op "antenna" (antenna)
261 5e8f809e 2020-06-27 op
262 5e8f809e 2020-06-27 op (println "unrecognized action" action))))
263 5e8f809e 2020-06-27 op
264 ddc03123 2020-03-28 op (comment
265 6776a2f2 2020-09-20 op (do
266 6776a2f2 2020-09-20 op (load-posts!)
267 d72c4e8f 2020-10-05 op (load-pages!)
268 d72c4e8f 2020-10-05 op ;; (clean)
269 4696276a 2020-09-22 op (build)
270 4696276a 2020-09-22 op (local-deploy))
271 ddc03123 2020-03-28 op (serve)
272 ddc03123 2020-03-28 op (stop-jetty)
273 4696276a 2020-09-22 op
274 4696276a 2020-09-22 op (do
275 4696276a 2020-09-22 op (deploy)
276 4696276a 2020-09-22 op (local-deploy))
277 c7d750b3 2021-08-03 op
278 d8c72311 2021-10-12 op (antenna)
279 d8c72311 2021-10-12 op
280 c7d750b3 2021-08-03 op (do
281 c7d750b3 2021-08-03 op (load-posts!)
282 c7d750b3 2021-08-03 op (load-pages!)
283 c7d750b3 2021-08-03 op ;; (clean)
284 c7d750b3 2021-08-03 op (build)
285 c7d750b3 2021-08-03 op (deploy)
286 c7d750b3 2021-08-03 op (local-deploy))
287 ddc03123 2020-03-28 op )