Merge the clojure-project and the buchdesmonats.mkd

This commit is contained in:
Aaron Fischer 2015-06-09 09:49:33 +02:00
commit c8c58220ca
10 changed files with 252 additions and 0 deletions

9
.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
/target
/classes
/checkouts
pom.xml
pom.xml.asc
*.jar
*.class
/.lein-*
/.nrepl-port

31
README.md Normal file
View file

@ -0,0 +1,31 @@
# About
Scrape the book list from the "Book of the month" project and generate a nice
looking visual representation of the book covers.
# Running
lein uberjar
java -jar target/buchdesmonats-1.1-standalone.jar
# License
Copyright (C) 2014 Aaron Mueller <mail@aaron-mueller.de>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

11
project.clj Normal file
View file

@ -0,0 +1,11 @@
(defproject buchdesmonats "1.1"
:description "A simple tool to fetch all books of the month from the cthn.de project."
:url "http://cthn.de/projects/buch_des_monats"
:license {:name "MIT License"
:url "http://opensource.org/licenses/MIT"}
:dependencies [[org.clojure/clojure "1.6.0"]
[enlive "1.1.5"]
[me.raynes/fs "1.4.5"]
[clj-http "0.9.2"]]
:main ^:skip-aot buchdesmonats.core
:profiles {:uberjar {:aot :all}})

10
public/main.js Normal file
View file

@ -0,0 +1,10 @@
$(function() {
$('#covers').imagesLoaded(function() {
$('#covers').masonry({
columnWidth: 265,
gutter: 5,
isFitWidth: true,
itemSelector: '.cover-item'
});
});
});

46
public/styles.css Normal file
View file

@ -0,0 +1,46 @@
@import url(http://fonts.googleapis.com/css?family=Gilda+Display);
body {
background-color: #CEC3A7;
}
h1 {
color: #7D5D5E;
text-align: center;
font-family: 'Gilda Display', serif;
font-size: 6em;
}
a {
color: #3F544B;
}
a:hover {
text-decoration: none;
color: black;
}
body > p {
width: 70%;
border-top: 3px solid #3F544B;
padding: 5px 0 25px 0;
font-family: 'Gilda Display', serif;
}
body > p,
#covers {
margin: auto;
}
.cover-item {
width: 265px;
margin-bottom: 5px;
border: 1px solid #FFE5C6;
}
.cover-item:hover {
opacity: 0.7;
}
.cover-item img {
width: 265px;
vertical-align: top;
}

File diff suppressed because one or more lines are too long

4
public/vendors/jquery-2.1.0.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,94 @@
;;; Copyright (C) 2014 Aaron Mueller <mail@aaron-mueller.de>
;;;
;;; Permission is hereby granted, free of charge, to any person obtaining a copy of
;;; this software and associated documentation files (the "Software"), to deal in
;;; the Software without restriction, including without limitation the rights to
;;; use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
;;; the Software, and to permit persons to whom the Software is furnished to do so,
;;; subject to the following conditions:
;;;
;;; The above copyright notice and this permission notice shall be included in all
;;; copies or substantial portions of the Software.
;;;
;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
;;; FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
;;; COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
;;; IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
;;; CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
(ns buchdesmonats.core
(:gen-class)
(:require [net.cgrand.enlive-html :as html]
[clj-http.client :as http-client]
[clojure.string :as str]
[clojure.java.io :as io]
[me.raynes.fs :as fs]))
(defn imgurl->bytes [lovelybooks-url]
(-> (java.net.URL. lovelybooks-url)
html/html-resource
(html/select [:div.bookcoverXXL :> :div :> :img])
first
(get-in [:attrs :src])
(#(str "http:" %))
(http-client/get {:as :byte-array})
:body))
(defn encode-url-part [part]
(java.net.URLEncoder/encode part "UTF-8"))
(defn encode-url [url]
(let [parts (map encode-url-part (re-find #"\/autor\/([^/]+)\/([^/]+)\/?" url))
author (nth parts 1)
book-title (nth parts 2)]
(str "http://lovelybooks.de/autor/" author "/" book-title)))
(defn url->file [lovelybooks-url target-dir]
(let [[_ author title] (re-find #".\/autor\/([^\/]+)\/(.+)-([0-9]+)-.\/$" lovelybooks-url)]
(-> (str author "_" title ".jpg")
str/lower-case
(str/replace #"[^a-z0-9-_.]" "")
(#(io/file target-dir %)))))
(defn scrape-book-urls [github-url]
(->> (http-client/get github-url)
:body
str/split-lines
(map #(second (re-find #"^\* .*\[.+\]\((.+)\)" %)))
(remove nil?)))
(defn scrape-book-cover [url target-dir]
(let [target-file (url->file url target-dir)
encoded-url (encode-url url)]
(with-open [out (io/output-stream target-file)]
(.write out (imgurl->bytes encoded-url)))))
(defn find-missing-covers [books-url target-dir]
(remove #(fs/exists? (url->file % target-dir))
(scrape-book-urls books-url)))
(html/defsnippet cover-item-model "buchdesmonats/layout.html" [:div#covers :> :div]
[link title]
[:a] (html/set-attr :href link)
[:img] (html/set-attr :src (url->file link "book-covers") :title title))
(html/deftemplate index-template "buchdesmonats/layout.html"
[cover-urls]
[:#covers] (html/content
(map #(cover-item-model % "zu Lovely Books")
cover-urls)))
(defn generate-html [book-urls target-dir]
(let [content (apply str (index-template book-urls))]
(with-open [out (io/writer (io/file "public" "index.html"))]
(.write out content))))
(defn -main [& args]
(let [github-url "https://raw.github.com/CTHN/wiki-data/master/pages/projects/buch_des_monats.mkd"
target-dir (io/file "public" "book-covers")]
(fs/mkdirs target-dir)
(generate-html (scrape-book-urls github-url) "public")
(doall (pmap #(scrape-book-cover % target-dir)
(find-missing-covers github-url target-dir)))
(System/exit 0)))

View file

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>cthn.de -- Buch des Monats</title>
<link rel="stylesheet" href="styles.css">
<script src="vendors/jquery-2.1.0.min.js"></script>
<script src="vendors/masonry-3.1.5.pkgd.min.js"></script>
<script src="vendors/imagesloaded-3.1.4.pkgd.min.js"></script>
<script src="main.js"></script>
</head>
<body>
<h1>Buch des Monats</h1>
<p>Handerlesen und für gut befunden seit 2010
von <a href="https://twitter.com/mezzomix22" rel="author">Michael
Reutter</a>. Jeden Monat ein neues Buch aus seiner Sammlung zu den
Themengebieten Netzkultur, Geektum, Computerspiele und
Cyberpunk. Als <a href="http://cthn.de/projects/buch_des_monats">CTHN-Projekt</a>
begonnen ist diese Bücherliste mittlerweile Anlaufstelle für so manchen
Leser der nach neuem Stoff sucht. Die Buchcover stammen
von <a href="http://lovelybooks.de/">Lovely Books</a>, <a href="https://github.com/aaronmueller/buchdesmonats">der Code</a>
von <a href="https://aaron-mueller.de/">Aaron Mueller</a>.</p>
<div id="covers">
<div class="cover-item">
<a href="#">
<img src="#" alt="LovelyBooks cover" title="Book title">
</a>
</div>
</body>
</html>