Initial commit
commit
86681ec999
@ -0,0 +1,3 @@
|
|||||||
|
((nil . ((cider-ns-refresh-before-fn . "integrant.repl/halt")
|
||||||
|
(cider-ns-refresh-after-fn . "integrant.repl/init")
|
||||||
|
(cider-clojure-cli-global-options . "-A:dev:cider-nrepl"))))
|
@ -0,0 +1,3 @@
|
|||||||
|
/db/data/dev
|
||||||
|
.nrepl-port
|
||||||
|
.cpcache
|
@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Run once as part of Docker build script to initialize
|
||||||
|
# the database with encryption for user passwords.
|
||||||
|
|
||||||
|
POSTGRES_USER=${POSTGRES_USER:-"dev"}
|
||||||
|
POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-"dev"}
|
||||||
|
|
||||||
|
psql -v ON_ERROR_STOP=1 \
|
||||||
|
--username "$POSTGRES_USER" \
|
||||||
|
--dbname "$POSTGRES_DB" <<-EOSQL
|
||||||
|
SET password_encryption = "scram-sha-256";
|
||||||
|
ALTER USER "$POSTGRES_USER" WITH ENCRYPTED PASSWORD '$POSTGRES_PASSWORD';
|
||||||
|
EOSQL
|
@ -0,0 +1,6 @@
|
|||||||
|
FROM postgres
|
||||||
|
|
||||||
|
# See the section on "Initialization scripts" at
|
||||||
|
# https://hub.docker.com/_/postgres/
|
||||||
|
|
||||||
|
COPY 0001_init.sh /docker-entrypoint-initdb.d/
|
@ -0,0 +1,48 @@
|
|||||||
|
#+TITLE: Database setup
|
||||||
|
|
||||||
|
This directory contains necessities for initializing and running a database
|
||||||
|
locally inside a docker container.
|
||||||
|
|
||||||
|
We want our develpment environment to use the same tech stack that production
|
||||||
|
uses. So rather than suppord a development configuration that uses SQLite and a
|
||||||
|
production configuration that uses PostgreSQL, just use PostgreSQL for both.
|
||||||
|
With Docker, it's easy.
|
||||||
|
|
||||||
|
|
||||||
|
Building requires the following environment variables.
|
||||||
|
|
||||||
|
- `POSTGRES_DB`
|
||||||
|
- `POSTGRES_USER`
|
||||||
|
- `POSTGRES_PASSWORD`
|
||||||
|
|
||||||
|
Running requires the following environment variables.
|
||||||
|
|
||||||
|
- `PGDATA`
|
||||||
|
- `POSTGRES_USER`
|
||||||
|
- `POSTGRES_PASSWORD`
|
||||||
|
|
||||||
|
|
||||||
|
#+BEGIN_SRC sh
|
||||||
|
docker build -t db .
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC sh :tangle run.sh :tangle-mode (identity #o755)
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PGDATA=${PGDATA:-"$(pwd)/data/dev"}
|
||||||
|
POSTGRES_USER=${POSTGRES_USER:-"dev"}
|
||||||
|
POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-"dev"}
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
--name db \
|
||||||
|
-e POSTGRES_PASSWORD=$POSTGRES_PASSWORD \
|
||||||
|
-e POSTGRES_USER=$POSTGRES_USER \
|
||||||
|
-v $PGDATA:/var/lib/postgresql/data \
|
||||||
|
-p 5432:5432 \
|
||||||
|
db
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
#+BEGIN_SRC sh
|
||||||
|
docker start db
|
||||||
|
#+END_SRC
|
@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PGDATA=${PGDATA:-"$(pwd)/data/dev"}
|
||||||
|
POSTGRES_USER=${POSTGRES_USER:-"dev"}
|
||||||
|
POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-"dev"}
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
--name darklimericks-db \
|
||||||
|
-e POSTGRES_PASSWORD=$POSTGRES_PASSWORD \
|
||||||
|
-e POSTGRES_USER=$POSTGRES_USER \
|
||||||
|
-v $PGDATA:/var/lib/postgresql/data \
|
||||||
|
-p 5432:5432 \
|
||||||
|
darklimericks-db
|
@ -0,0 +1,27 @@
|
|||||||
|
{:deps
|
||||||
|
{org.clojure/tools.namespace {:mvn/version "1.0.0"}
|
||||||
|
org.clojure/tools.deps.alpha
|
||||||
|
{:git/url "https://github.com/clojure/tools.deps.alpha.git"
|
||||||
|
:sha "d492e97259c013ba401c5238842cd3445839d020"}
|
||||||
|
hiccup {:mvn/version "1.0.5"}
|
||||||
|
com.taoensso/timbre {:mvn/version "5.1.0"}
|
||||||
|
http-kit {:mvn/version "2.5.0"}
|
||||||
|
integrant {:mvn/version "0.8.0"}
|
||||||
|
integrant/repl {:mvn/version "0.3.2"}
|
||||||
|
seancorfield/next.jdbc {:mvn/version "1.1.610"}
|
||||||
|
org.xerial/sqlite-jdbc {:mvn/version "3.32.3.2"}
|
||||||
|
honeysql {:mvn/version "1.0.444"}
|
||||||
|
metosin/muuntaja {:mvn/version "0.6.7"}
|
||||||
|
metosin/reitit {:mvn/version "0.5.10"}
|
||||||
|
metosin/reitit-http {:mvn/version "0.5.10"}
|
||||||
|
metosin/reitit-interceptors {:mvn/version "0.5.10"}
|
||||||
|
com.layerware/hugsql {:mvn/version "0.5.1"}
|
||||||
|
org.postgresql/postgresql {:mvn/version "42.2.18"}
|
||||||
|
migratus {:mvn/version "1.3.2"}
|
||||||
|
ring/ring-core {:mvn/version "1.8.2"}
|
||||||
|
environ {:mvn/version "1.2.0"}
|
||||||
|
prhyme {:local/root "/home/eihli/code/prhyme/prhyme.jar"}}
|
||||||
|
:paths ["src" "resources"]
|
||||||
|
:aliases {:dev {:extra-paths ["dev"]
|
||||||
|
:extra-deps {hawk {:mvn/version "0.2.11"}
|
||||||
|
ring/ring-devel {:mvn/version "1.8.2"}}}}}
|
@ -0,0 +1,28 @@
|
|||||||
|
(ns db
|
||||||
|
(:require [next.jdbc.sql :as jdbc.sql]
|
||||||
|
[next.jdbc :as jdbc]
|
||||||
|
[honeysql.core :as honey.sql]
|
||||||
|
[integrant.repl.state :refer [system]]
|
||||||
|
[com.darklimericks.db.artists :as artists]
|
||||||
|
[com.darklimericks.db.albums :as albums]
|
||||||
|
[com.darklimericks.server.limericks :as server.limericks]
|
||||||
|
[com.darklimericks.db.limericks :as limericks]))
|
||||||
|
|
||||||
|
(def conn (:database.sql/connection system))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(->> (honey.sql/build :select :* :from :artist)
|
||||||
|
(honey.sql/format)
|
||||||
|
(jdbc.sql/query conn))
|
||||||
|
(artists/insert-artist conn "Optimus Prhyme")
|
||||||
|
(server.limericks/get-artist-and-album-for-new-limerick conn)
|
||||||
|
(artists/artist conn 1)
|
||||||
|
(albums/artist-albums-sql 1)
|
||||||
|
(albums/artist-albums conn 1)
|
||||||
|
(albums/insert-album conn "Limericks Illicit" 1)
|
||||||
|
(albums/insert-album-sql "Limericks Illicit" 1)
|
||||||
|
(artists/artists-by-letter conn "O")
|
||||||
|
(limericks/album-limericks-sql 1)
|
||||||
|
(limericks/album-limericks conn 1)
|
||||||
|
(albums/artist-most-resent-album conn 1)
|
||||||
|
)
|
@ -0,0 +1,13 @@
|
|||||||
|
(ns migrations
|
||||||
|
(:require [migratus.core :as migratus]
|
||||||
|
[integrant.repl.state :as state]))
|
||||||
|
|
||||||
|
(def config {:store :database
|
||||||
|
:migration-dir "migrations/"
|
||||||
|
:init-script "init.sql"
|
||||||
|
:db {:connection-uri (-> state/config :database.sql/connection :jdbcUrl)}})
|
||||||
|
|
||||||
|
(comment
|
||||||
|
state/config
|
||||||
|
(:database.sql/connection state/system)
|
||||||
|
(migratus/init config))
|
@ -0,0 +1,89 @@
|
|||||||
|
(ns user
|
||||||
|
(:require [clojure.tools.deps.alpha.repl :refer [add-lib]]
|
||||||
|
[clojure.tools.namespace.repl :refer [set-refresh-dirs]]
|
||||||
|
[integrant.repl :as repl]
|
||||||
|
[integrant.repl.state :as state]
|
||||||
|
[migratus.core :as migratus]
|
||||||
|
[com.darklimericks.server.handlers :as handlers]
|
||||||
|
[integrant.core :as ig]
|
||||||
|
[hawk.core :as hawk]
|
||||||
|
[clojure.java.io :as io]
|
||||||
|
[com.darklimericks.server.limericks :as limericks]
|
||||||
|
[com.darklimericks.server.util :as util]
|
||||||
|
[com.owoga.prhyme.limerick :as limerick]
|
||||||
|
[com.darklimericks.server.system]
|
||||||
|
[reitit.core :as reitit]))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(-> state/system
|
||||||
|
:app/router
|
||||||
|
(reitit/routes))
|
||||||
|
)
|
||||||
|
|
||||||
|
(set-refresh-dirs "src" "dev" "resources")
|
||||||
|
|
||||||
|
(defn add-project-dep
|
||||||
|
([lib-name lib-version]
|
||||||
|
(let [dep-name (symbol lib-name)
|
||||||
|
dep-version (name lib-version)]
|
||||||
|
(add-lib dep-name {:mvn/version dep-version}))))
|
||||||
|
|
||||||
|
(defn- clojure-file? [_ {:keys [file]}]
|
||||||
|
(re-matches #"[^.].*(\.clj|\.edn)$" (.getName file)))
|
||||||
|
|
||||||
|
(defn- auto-reset-handler [ctx event]
|
||||||
|
(binding [*ns* *ns*]
|
||||||
|
(integrant.repl/reset)
|
||||||
|
ctx))
|
||||||
|
|
||||||
|
(defn auto-reset []
|
||||||
|
(hawk/watch! [{:paths ["src/" "resources/" "dev/"]
|
||||||
|
:filter clojure-file?
|
||||||
|
:handler auto-reset-handler}]))
|
||||||
|
|
||||||
|
(defn init []
|
||||||
|
(repl/halt)
|
||||||
|
(-> "server/config.edn"
|
||||||
|
io/resource
|
||||||
|
slurp
|
||||||
|
ig/read-string
|
||||||
|
ig/prep
|
||||||
|
constantly
|
||||||
|
repl/set-prep!)
|
||||||
|
(repl/prep)
|
||||||
|
(repl/init))
|
||||||
|
|
||||||
|
(defn reset []
|
||||||
|
(repl/halt))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(init)
|
||||||
|
(auto-reset)
|
||||||
|
(limericks/get-artist-and-album-for-new-limerick (-> state/system :database.sql/connection))
|
||||||
|
(let [handler (handlers/limerick-generation-post-handler
|
||||||
|
(-> state/system :database.sql/connection)
|
||||||
|
(-> state/system :app/cache))]
|
||||||
|
(handler {:params {:scheme "A9 A9 B5 B5 A9" #_'((A 9) (A 9) (B 5) (B 5) (A 9))}}))
|
||||||
|
|
||||||
|
(reitit/match-by-path
|
||||||
|
(-> state/system :app/router)
|
||||||
|
"/limericks/1/1")
|
||||||
|
|
||||||
|
(let [router (-> state/system :app/router)]
|
||||||
|
(util/route-name->path {::reitit/router router}
|
||||||
|
:com.darklimericks.server.system/artist))
|
||||||
|
(let [router (-> state/system :app/router)]
|
||||||
|
(util/route-name->path
|
||||||
|
{::reitit/router router}
|
||||||
|
:com.darklimericks.server.system/artist
|
||||||
|
{:artist-id 1}))
|
||||||
|
|
||||||
|
(let [router (-> state/system :app/router)]
|
||||||
|
(->> :com.darklimericks.server.system/artist
|
||||||
|
(#(reitit/match-by-name (::reitit/router {::reitit/router router})
|
||||||
|
%
|
||||||
|
{:artist-id 1}))
|
||||||
|
(reitit/match->path)))
|
||||||
|
|
||||||
|
|
||||||
|
)
|
@ -0,0 +1,3 @@
|
|||||||
|
DROP TABLE artist;
|
||||||
|
DROP TABLE album;
|
||||||
|
DROP TABLE limerick;
|
@ -0,0 +1,17 @@
|
|||||||
|
CREATE TABLE artist (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name VARCHAR(64)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE album (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name VARCHAR(64),
|
||||||
|
artist_id INTEGER NOT NULL REFERENCES artist
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE limerick (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name VARCHAR(64),
|
||||||
|
text VARCHAR(1024),
|
||||||
|
album_id INTEGER NOT NULL REFERENCES album
|
||||||
|
);
|
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,25 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html class="no-js" lang="">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||||
|
<title>DarkLimericks</title>
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
|
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
||||||
|
<!-- Place favicon.ico in the root directory -->
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!--[if lt IE 8]>
|
||||||
|
<p class="browserupgrade">
|
||||||
|
You are using an <strong>outdated</strong> browser. Please
|
||||||
|
<a href="http://browsehappy.com/">upgrade your browser</a> to improve
|
||||||
|
your experience.
|
||||||
|
</p>
|
||||||
|
<![endif]-->
|
||||||
|
|
||||||
|
Hello World!
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1 @@
|
|||||||
|
/home/eihli/src/tachyons/css/tachyons.css
|
@ -0,0 +1 @@
|
|||||||
|
/home/eihli/src/tachyons/css/tachyons.min.css
|
@ -0,0 +1 @@
|
|||||||
|
hi
|
@ -0,0 +1,6 @@
|
|||||||
|
{:app/logging {:min-level :debug}
|
||||||
|
:app/server {:port 8000 :handler #ig/ref :app/handler}
|
||||||
|
:app/cache {}
|
||||||
|
:database.sql/connection {}
|
||||||
|
:app/router {:db #ig/ref :database.sql/connection :cache #ig/ref :app/cache}
|
||||||
|
:app/handler {:router #ig/ref :app/router}}
|
@ -0,0 +1,43 @@
|
|||||||
|
(ns com.darklimericks.db.albums
|
||||||
|
(:require [next.jdbc :as jdbc]
|
||||||
|
[next.jdbc.sql :as jdbc.sql]
|
||||||
|
[honeysql.core :as honey.sql]
|
||||||
|
[honeysql.helpers :as honey.helpers]))
|
||||||
|
|
||||||
|
(defn insert-album-sql [name artist-id]
|
||||||
|
(let [[s & params] (-> (honey.helpers/insert-into :album)
|
||||||
|
(honey.helpers/columns :name :artist-id)
|
||||||
|
(honey.helpers/values
|
||||||
|
[[name artist-id]])
|
||||||
|
honey.sql/format)
|
||||||
|
s (format "%s RETURNING id" s)]
|
||||||
|
(concat [s] params)))
|
||||||
|
|
||||||
|
(defn insert-album [db name artist-id]
|
||||||
|
(jdbc/execute! db (insert-album-sql name artist-id)))
|
||||||
|
|
||||||
|
(defn artist-albums-sql [artist-id]
|
||||||
|
(honey.sql/format
|
||||||
|
(honey.sql/build
|
||||||
|
:select :*
|
||||||
|
:from :album
|
||||||
|
:where [:= :artist_id artist-id]
|
||||||
|
:order-by [[:album.id :desc]])))
|
||||||
|
|
||||||
|
(defn artist-albums [db artist-id]
|
||||||
|
(jdbc/execute! db (artist-albums-sql artist-id)))
|
||||||
|
|
||||||
|
(defn artist-most-recent-album-sql [artist-id]
|
||||||
|
(honey.sql/format
|
||||||
|
(honey.sql/build
|
||||||
|
:select :*
|
||||||
|
:from :album
|
||||||
|
:join [:artist [:= :album.artist_id :artist.id]]
|
||||||
|
:order-by [[:album.id :desc]]
|
||||||
|
:where [:= :artist.id artist-id])))
|
||||||
|
|
||||||
|
(defn artist-most-resent-album [db artist-id]
|
||||||
|
(jdbc/execute! db (artist-most-recent-album-sql artist-id)))
|
||||||
|
|
||||||
|
(defn album [db id]
|
||||||
|
(jdbc.sql/get-by-id db :album id))
|
@ -0,0 +1,42 @@
|
|||||||
|
(ns com.darklimericks.db.artists
|
||||||
|
(:require [next.jdbc :as jdbc]
|
||||||
|
[honeysql.core :as honey.sql]
|
||||||
|
[honeysql.helpers :as honey.helpers]))
|
||||||
|
|
||||||
|
(defn insert-artist-sql [name]
|
||||||
|
(let [[s & params] (-> (honey.helpers/insert-into :artist)
|
||||||
|
(honey.helpers/columns :name)
|
||||||
|
(honey.helpers/values
|
||||||
|
[[name]])
|
||||||
|
honey.sql/format)
|
||||||
|
s (format "%s RETURNING id" s)]
|
||||||
|
(concat [s] params)))
|
||||||
|
|
||||||
|
(defn insert-artist [db name]
|
||||||
|
(jdbc/execute! db (insert-artist-sql name)))
|
||||||
|
|
||||||
|
(defn most-recent-artist-sql []
|
||||||
|
(-> {:select [:*]
|
||||||
|
:from [:artist]
|
||||||
|
:order-by [[:id :desc]]
|
||||||
|
:limit 1}
|
||||||
|
(honey.sql/format)))
|
||||||
|
|
||||||
|
(defn most-recent-artist [db]
|
||||||
|
(jdbc/execute-one! db (most-recent-artist-sql)))
|
||||||
|
|
||||||
|
(defn artists-by-letter [db letter]
|
||||||
|
(jdbc/execute!
|
||||||
|
db
|
||||||
|
(honey.sql/format
|
||||||
|
{:select [:*]
|
||||||
|
:from [:artist]
|
||||||
|
:where [:like :name (str letter "%")]})))
|
||||||
|
|
||||||
|
(defn artist [db id]
|
||||||
|
(jdbc/execute-one!
|
||||||
|
db
|
||||||
|
(honey.sql/format
|
||||||
|
{:select [:*]
|
||||||
|
:from [:artist]
|
||||||
|
:where [:= :id id]})))
|
@ -0,0 +1,42 @@
|
|||||||
|
(ns com.darklimericks.db.limericks
|
||||||
|
(:require [next.jdbc :as jdbc]
|
||||||
|
[honeysql.core :as honey.sql]
|
||||||
|
[honeysql.helpers :as honey.helpers]))
|
||||||
|
|
||||||
|
(defn insert-limerick-sql [name text album-id]
|
||||||
|
(-> (honey.helpers/insert-into :limerick)
|
||||||
|
(honey.helpers/columns :name :text :album-id)
|
||||||
|
(honey.helpers/values
|
||||||
|
[[name text album-id]])
|
||||||
|
honey.sql/format))
|
||||||
|
|
||||||
|
(defn insert-limerick [db name text album-id]
|
||||||
|
(jdbc/execute! db (insert-limerick-sql name text album-id)))
|
||||||
|
|
||||||
|
(defn limerick-sql [limerick-id]
|
||||||
|
(honey.sql/format
|
||||||
|
(honey.sql/build
|
||||||
|
:select :*
|
||||||
|
:from :limerick
|
||||||
|
:where [:= :limerick_id limerick-id])))
|
||||||
|
|
||||||
|
(defn limerick [db limerick-id]
|
||||||
|
(jdbc/execute! db (limerick-sql limerick-id)))
|
||||||
|
|
||||||
|
(defn limericks [db]
|
||||||
|
(jdbc/execute!
|
||||||
|
db
|
||||||
|
(honey.sql/format
|
||||||
|
(honey.sql/build
|
||||||
|
:select :*
|
||||||
|
:from :limerick))))
|
||||||
|
|
||||||
|
(defn album-limericks-sql [album-id]
|
||||||
|
(honey.sql/format
|
||||||
|
(honey.sql/build
|
||||||
|
:select :*
|
||||||
|
:from :limerick
|
||||||
|
:where [:= :album_id album-id])))
|
||||||
|
|
||||||
|
(defn album-limericks [db album-id]
|
||||||
|
(jdbc/execute! db (album-limericks-sql album-id)))
|
@ -0,0 +1 @@
|
|||||||
|
(ns com.darklimericks.db.tasks)
|
@ -0,0 +1,16 @@
|
|||||||
|
(ns com.darklimericks.linguistics.core
|
||||||
|
(:require [com.owoga.prhyme.data.dictionary :as dict]
|
||||||
|
[clojure.string :as string]))
|
||||||
|
|
||||||
|
(defn gen-artist []
|
||||||
|
(->> [(rand-nth (seq dict/adverbs))
|
||||||
|
(rand-nth (seq dict/nouns))]
|
||||||
|
(map string/capitalize)
|
||||||
|
(string/join " ")))
|
||||||
|
|
||||||
|
(defn gen-album []
|
||||||
|
(->> [(rand-nth (seq dict/adjectives))
|
||||||
|
(rand-nth (seq dict/nouns))]
|
||||||
|
(map string/capitalize)
|
||||||
|
(string/join " ")))
|
||||||
|
|
@ -0,0 +1,26 @@
|
|||||||
|
(ns com.darklimericks.server.core
|
||||||
|
(:gen-class)
|
||||||
|
(:require [integrant.core :as ig]
|
||||||
|
[com.darklimericks.server.system :as system]
|
||||||
|
[reitit.coercion]
|
||||||
|
[reitit.coercion.spec]
|
||||||
|
[taoensso.timbre :as timbre]
|
||||||
|
[clojure.java.io :as io]))
|
||||||
|
|
||||||
|
|
||||||
|
(def a (atom {}))
|
||||||
|
|
||||||
|
(defn -main []
|
||||||
|
(try
|
||||||
|
(let [system (->> "server/config.edn"
|
||||||
|
io/resource
|
||||||
|
slurp
|
||||||
|
ig/read-string
|
||||||
|
ig/prep
|
||||||
|
ig/init)]
|
||||||
|
(timbre/info "Running with config: server/config.edn" )
|
||||||
|
system)
|
||||||
|
(catch Throwable e
|
||||||
|
(.printStackTrace e)
|
||||||
|
(System/exit 1))))
|
||||||
|
|
@ -0,0 +1,6 @@
|
|||||||
|
(ns com.darklimericks.server.db
|
||||||
|
(:require [clojure.tools.namespace.repl :as c.t.n.r]))
|
||||||
|
|
||||||
|
(c.t.n.r/disable-unload!)
|
||||||
|
|
||||||
|
(defonce db (atom {}))
|
@ -0,0 +1,55 @@
|
|||||||
|
(ns com.darklimericks.server.example
|
||||||
|
(:require [integrant.core :as ig]
|
||||||
|
[clojure.tools.namespace.repl :refer [set-refresh-dirs]]
|
||||||
|
[integrant.repl :as repl]
|
||||||
|
[org.httpkit.server :as kit]
|
||||||
|
[reitit.http :as http]
|
||||||
|
[hiccup.core :as hiccup]
|
||||||
|
[hiccup.page :as page]
|
||||||
|
[taoensso.timbre :as timbre]
|
||||||
|
[reitit.interceptor.sieppari :as sieppari]))
|
||||||
|
|
||||||
|
(defn home []
|
||||||
|
(page/html5
|
||||||
|
[:head
|
||||||
|
[:meta {:charset "utf-8"}]
|
||||||
|
[:meta {:name "viewport" :content "width=device-width, initial-scale=1.0"}]]
|
||||||
|
[:title "Hello World"]
|
||||||
|
[:body "Goodbye, world!"]))
|
||||||
|
|
||||||
|
(defn home-handler [request]
|
||||||
|
{:status 200
|
||||||
|
:headers {"Content-Type" "text/html; charset=utf-8"}
|
||||||
|
:body (hiccup/html (home))})
|
||||||
|
|
||||||
|
(def routes
|
||||||
|
[["/" {:name ::home
|
||||||
|
:get {:handler home-handler}}]])
|
||||||
|
|
||||||
|
(def config
|
||||||
|
{:app/handler {:router (ig/ref :app/router)}
|
||||||
|
:app/router {:routes routes}
|
||||||
|
:app/server {:port 8000 :handler (ig/ref :app/handler)}})
|
||||||
|
|
||||||
|
(defmethod ig/init-key :app/router [_ {:keys [routes]}]
|
||||||
|
(http/router routes))
|
||||||
|
|
||||||
|
(defmethod ig/init-key :app/handler [_ {:keys [router]}]
|
||||||
|
(http/ring-handler router {:executor sieppari/executor}))
|
||||||
|
|
||||||
|
(defmethod ig/init-key :app/server [_ opts]
|
||||||
|
(timbre/info "Starting server with " opts)
|
||||||
|
(kit/run-server (:handler opts) (dissoc opts :handler)))
|
||||||
|
|
||||||
|
(defmethod ig/halt-key! :app/server [_ server]
|
||||||
|
(timbre/info "Stopping server")
|
||||||
|
(server))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(set-refresh-dirs "src" "dev")
|
||||||
|
(repl/set-prep! (constantly config))
|
||||||
|
(repl/prep)
|
||||||
|
(repl/go)
|
||||||
|
(repl/reset)
|
||||||
|
(repl/halt)
|
||||||
|
)
|
@ -0,0 +1,197 @@
|
|||||||
|
(ns com.darklimericks.server.handlers
|
||||||
|
(:require [taoensso.timbre :as timbre]
|
||||||
|
[hiccup.core :as hiccup]
|
||||||
|
[reitit.ring :as ring]
|
||||||
|
[reitit.core :as reitit]
|
||||||
|
[clojure.string :as string]
|
||||||
|
[clojure.core.async :as async]
|
||||||
|
[com.darklimericks.server.util :as util]
|
||||||
|
[com.darklimericks.db.albums :as db.albums]
|
||||||
|
[com.darklimericks.db.limericks :as db.limericks]
|
||||||
|
[com.darklimericks.db.artists :as db.artists]
|
||||||
|
[com.darklimericks.server.views :as views]
|
||||||
|
[com.darklimericks.server.limericks :as limericks]))
|
||||||
|
|
||||||
|
(defn home-handler [request]
|
||||||
|
(timbre/info "home-handler")
|
||||||
|
{:status 200
|
||||||
|
:headers {"Content-Type" "text/html; charset=utf-8"}
|
||||||
|
:body (hiccup/html (views/home request))})
|
||||||
|
|
||||||
|
(def resource-handler (ring/create-resource-handler {:allow-symlinks? true}))
|
||||||
|
|
||||||
|
(defn limerick-generation-post-handler
|
||||||
|
[db cache]
|
||||||
|
(fn [{{:keys [scheme]} :params :as request}]
|
||||||
|
(let [tasks (:tasks @cache)]
|
||||||
|
(let [task-id (java.util.UUID/randomUUID)
|
||||||
|
limerick-chan (limericks/generate-limerick cache scheme task-id)]
|
||||||
|
(swap! cache assoc-in [:tasks task-id] {:status :pending})
|
||||||
|
(async/go
|
||||||
|
(let [limerick (async/<! limerick-chan)
|
||||||
|
[artist-id album-id] (limericks/get-artist-and-album-for-new-limerick db)]
|
||||||
|
(db.limericks/insert-limerick
|
||||||
|
db
|
||||||
|
(limericks/get-limerick-name limerick)
|
||||||
|
(string/join "\n" limerick)
|
||||||
|
album-id))))
|
||||||
|
{:status 301
|
||||||
|
:headers {"Content-Type" "text/html; charset=utf-8"}
|
||||||
|
:body (views/page "Dark Limericks"
|
||||||
|
[:h1 "Creating your limerick..."]
|
||||||
|
[:div "Submission processing..."]
|
||||||
|
[:h1 "Current limericks"]
|
||||||
|
(views/limerick-tasks tasks))})))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(let [c (async/thread
|
||||||
|
(Thread/sleep 1000)
|
||||||
|
200)]
|
||||||
|
(async/go
|
||||||
|
(let [val (async/<! c)]
|
||||||
|
(println (+ 20 val)))))
|
||||||
|
|
||||||
|
)
|
||||||
|
(defn limericks-get-handler [db cache]
|
||||||
|
(fn [request]
|
||||||
|
(let [artist-id (get-in request [:parameters :path :artist-id])
|
||||||
|
artist (db.artists/artist db artist-id)
|
||||||
|
album-id (get-in request [:parameters :path :album-id])
|
||||||
|
album (db.albums/album db album-id)
|
||||||
|
limericks (db.limericks/album-limericks db album-id)]
|
||||||
|
{:status 200
|
||||||
|
:headers {"Content-Type" "text/html; charset=utf-8"}
|
||||||
|
:body (views/page
|
||||||
|
"Dark Limericks"
|
||||||
|
[:div.flex.items-center.flex-column
|
||||||
|
[:div.f3.pt4.light-yellow
|
||||||
|
(->> artist
|
||||||
|
:artist/name
|
||||||
|
(format "%s LYRICS")
|
||||||
|
(string/upper-case))]
|
||||||
|
[:div.f4.pv3
|
||||||
|
[:strong
|
||||||
|
(->> album
|
||||||
|
:album/name
|
||||||
|
(format "album: %s"))]]
|
||||||
|
(map-indexed
|
||||||
|
(fn [i limerick]
|
||||||
|
(let [i (inc i)
|
||||||
|
limerick-url
|
||||||
|
(format
|
||||||
|
"%s#%s"
|
||||||
|
(util/route-name->path
|
||||||
|
request
|
||||||
|
:com.darklimericks.server.system/album
|
||||||
|
{:artist-id (:artist/id artist)
|
||||||
|
:album-id (:album/id album)})
|
||||||
|
i)]
|
||||||
|
[:a.db.light-yellow
|
||||||
|
{:href limerick-url}
|
||||||
|
(format
|
||||||
|
"%s. %s"
|
||||||
|
i
|
||||||
|
(:limerick/name limerick))]))
|
||||||
|
limericks)
|
||||||
|
(map-indexed
|
||||||
|
(fn [i limerick]
|
||||||
|
(views/limerick i limerick))
|
||||||
|
limericks)
|
||||||
|
[:div.f6.light-yellow.pt4.w-60
|
||||||
|
(string/join
|
||||||
|
" / "
|
||||||
|
["Thanks be to Optimus Prhyme"
|
||||||
|
"by blood honor these words sublime"
|
||||||
|
"sacred heuristics"
|
||||||
|
"glorious limericks"
|
||||||
|
"singularity we climb"])]
|
||||||
|
[:div.f6.washed-yellow.pt3.w-60
|
||||||
|
(string/join
|
||||||
|
" / "
|
||||||
|
["Submissions, comments, corrections"
|
||||||
|
"adorations, exultations, rejections"
|
||||||
|
"all receieved freely"
|
||||||
|
"@owoga.com, eihli"
|
||||||
|
"by Optimus Prhyme's directions"])]])})))
|
||||||
|
|
||||||
|
(defn limerick-generation-get-handler [db cache]
|
||||||
|
(fn [request]
|
||||||
|
(let [tasks (:tasks @cache)]
|
||||||
|
{:status 200
|
||||||
|
:headers {"Content-Type" "text/html; charset=utf-8"}
|
||||||
|
:body (views/page
|
||||||
|
"Dark Limericks"
|
||||||
|
(views/limerick-tasks tasks))})))
|
||||||
|
|
||||||
|
(defn artists-by-letter [db]
|
||||||
|
(fn [{{:keys [letter]} :path-params :as req}]
|
||||||
|
(let [artists (db.artists/artists-by-letter db (string/upper-case letter))]
|
||||||
|
{:status 200
|
||||||
|
:headers {"Content-Type" "text/html; charset=utf-8"}
|
||||||
|
:body (views/page
|
||||||
|
"Dark Limericks"
|
||||||
|
(when artists
|
||||||
|
(let [[right-hand-side-artists
|
||||||
|
left-hand-side-artists]
|
||||||
|
((juxt #(take (quot (inc (count artists)) 2) %)
|
||||||
|
#(drop (quot (inc (count artists)) 2) %))
|
||||||
|
artists)]
|
||||||
|
[:div.bg-near-black.br4.flex
|
||||||
|
[:div.fl.w-50.pa2
|
||||||
|
(for [artist right-hand-side-artists]
|
||||||
|
[:a.washed-yellow
|
||||||
|
{:href (util/route-name->path
|
||||||
|
req
|
||||||
|
:com.darklimericks.server.system/artist
|
||||||
|
{:artist-id (:artist/id artist)})}
|
||||||
|
(:artist/name artist)])]
|
||||||
|
[:div.fl.w-50.pa2
|
||||||
|
(for [artist left-hand-side-artists]
|
||||||
|
[:a.washed-yellow
|
||||||
|
{:href "#"}
|
||||||
|
(:artist/name artist)])]])))})))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(let [artists ["a"]]
|
||||||
|
(partition 1 1 nil artists))
|
||||||
|
((juxt #(take 1 %) #(drop 1 %)) [1 2 3 4])
|
||||||
|
(into [] (take 1) [1 2 3])
|
||||||
|
)
|
||||||
|
|
||||||
|
(defn artist-get-handler [db]
|
||||||
|
(fn [request]
|
||||||
|
(let [artist-id (get-in request [:parameters :path :artist-id])
|
||||||
|
artist (db.artists/artist db artist-id)
|
||||||
|
albums (db.albums/artist-albums db artist-id)
|
||||||
|
limericks (into {} (map
|
||||||
|
#(vector
|
||||||
|
(:album/id %)
|
||||||
|
(db.limericks/album-limericks db (:album/id %)))
|
||||||
|
albums))]
|
||||||
|
{:status 200
|
||||||
|
:headers {"Content-Type" "text/html; charset=utf-8"}
|
||||||
|
:body (views/page
|
||||||
|
"Dark Limericks"
|
||||||
|
[:div
|
||||||
|
[:div.f3.pt3.light-yellow
|
||||||
|
(->> artist
|
||||||
|
:artist/name
|
||||||
|
(format "%s Lyrics")
|
||||||
|
(string/upper-case))]
|
||||||
|
(for [album albums]
|
||||||
|
[:div
|
||||||
|
[:div.f4.pt3.light-yellow.pb3
|
||||||
|
(->> album
|
||||||
|
:album/name
|
||||||
|
(format "album: \"%s\""))]
|
||||||
|
(let [album-url (util/route-name->path
|
||||||
|
request
|
||||||
|
:com.darklimericks.server.system/album
|
||||||
|
{:artist-id (:artist/id artist)
|
||||||
|
:album-id (:album/id album)})]
|
||||||
|
(map-indexed
|
||||||
|
(fn [index limerick]
|
||||||
|
[:a.f5.washed-yellow.db
|
||||||
|
{:href (format "%s#%s" album-url (inc index))}
|
||||||
|
(:limerick/name limerick)])
|
||||||
|
(get limericks (:album/id album))))])])})))
|
@ -0,0 +1,40 @@
|
|||||||
|
(ns com.darklimericks.server.interceptors
|
||||||
|
(:require [reitit.http.interceptors.parameters :refer [parameters-interceptor]]
|
||||||
|
[muuntaja.interceptor :as muuntaja-interceptor]
|
||||||
|
[reitit.interceptor.sieppari :as sieppari]
|
||||||
|
[ring.middleware.keyword-params :refer [keyword-params-request]]
|
||||||
|
[taoensso.timbre :as timbre]
|
||||||
|
[reitit.core :as reitit]
|
||||||
|
[reitit.coercion :as coercion]
|
||||||
|
[reitit.impl :as impl]))
|
||||||
|
|
||||||
|
|
||||||
|
(def format-interceptor (muuntaja-interceptor/format-interceptor))
|
||||||
|
|
||||||
|
(def keywordize-params-interceptor
|
||||||
|
{:enter
|
||||||
|
(fn [{:keys [request] :as ctx}]
|
||||||
|
(update ctx :request keyword-params-request))})
|
||||||
|
|
||||||
|
(def logging-interceptor
|
||||||
|
{:enter (fn [{:keys [request] :as ctx}]
|
||||||
|
(timbre/info
|
||||||
|
(str "Entering " (dissoc request ::reitit/match)))
|
||||||
|
ctx)
|
||||||
|
:exit (fn [{:keys [response] :as ctx}]
|
||||||
|
(timbre/info
|
||||||
|
(str "Exiting " (dissoc response ::reitit/match)))
|
||||||
|
ctx)})
|
||||||
|
|
||||||
|
(def coerce-request-interceptor
|
||||||
|
{:enter
|
||||||
|
(fn [{:keys [request] :as ctx}]
|
||||||
|
(let [{{{:keys [coercion parameters]} :data :as opts} :reitit.core/match} request]
|
||||||
|
(cond
|
||||||
|
(not coercion) ctx
|
||||||
|
(not parameters) ctx
|
||||||
|
:else
|
||||||
|
(if-let [coercers (coercion/request-coercers coercion parameters opts)]
|
||||||
|
(let [coerced (coercion/coerce-request coercers request)]
|
||||||
|
(assoc-in ctx [:request :parameters] coerced))
|
||||||
|
ctx))))})
|
@ -0,0 +1,104 @@
|
|||||||
|
(ns com.darklimericks.server.limericks
|
||||||
|
(:require [clojure.string :as string]
|
||||||
|
[clojure.core.async :as async]
|
||||||
|
[reitit.core :as reitit]
|
||||||
|
[com.darklimericks.db.artists :as artists]
|
||||||
|
[com.darklimericks.db.albums :as albums]
|
||||||
|
[com.darklimericks.db.limericks :as limericks]
|
||||||
|
[com.darklimericks.linguistics.core :as linguistics]
|
||||||
|
[com.owoga.prhyme.limerick :as limerick]
|
||||||
|
[com.owoga.prhyme.data.dictionary :as dict]
|
||||||
|
[com.owoga.prhyme.data.darklyrics :refer [darklyrics-markov-2]]))
|
||||||
|
|
||||||
|
(defn parse-scheme-element [[tokens ctx]]
|
||||||
|
(cond
|
||||||
|
(or (= 5 (count tokens))
|
||||||
|
(= 3 (count tokens)))
|
||||||
|
(do (assert (re-matches #"\w+\d" (first tokens))
|
||||||
|
"Expected a letter followed by an integer.")
|
||||||
|
(let [text (re-find #"[a-zA-Z]+" (first tokens))
|
||||||
|
count (Integer/parseInt (re-find #"\d+" (first tokens)))]
|
||||||
|
[(rest tokens) (conj ctx [text count])]))
|
||||||
|
|
||||||
|
(or (= 4 (count tokens))
|
||||||
|
(= 1 (count tokens)))
|
||||||
|
(do (assert (= (first tokens) (apply str (first ctx))) (format "Expected %s" (first ctx)))
|
||||||
|
[(rest tokens) ctx])
|
||||||
|
|
||||||
|
(= 2 (count tokens))
|
||||||
|
(do (assert (= (first tokens) (apply str (second ctx))) (format "Expected %s" (second ctx)))
|
||||||
|
[(rest tokens) ctx])
|
||||||
|
|
||||||
|
:else
|
||||||
|
(throw (ex-info "Invalid scheme" {:scheme tokens}))))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(parse-scheme-element [["A9" "A9" "B5" "B5" "A9"] []]))
|
||||||
|
|
||||||
|
(defn parse-scheme [scheme-string]
|
||||||
|
(-> (string/split scheme-string #"\s+")
|
||||||
|
(#(vector % []))
|
||||||
|
(parse-scheme-element)
|
||||||
|
(parse-scheme-element)
|
||||||
|
(parse-scheme-element)
|
||||||
|
(parse-scheme-element)
|
||||||
|
(parse-scheme-element)
|
||||||
|
((fn [[tokens [a b]]]
|
||||||
|
[a a b b a]))))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(re-find #"\d+" "alpha 234 aset 34a")
|
||||||
|
(re-find #"[a-zA-Z]+" "apla352 spac")
|
||||||
|
(parse-scheme "a9 a9 b6 b6 a9")
|
||||||
|
(require '[integrant.repl.state :as state])
|
||||||
|
(reitit/match-by-path (:app/router state/system) "/limerick-generation-task")
|
||||||
|
((:app/handler state/system) {:request-method :post
|
||||||
|
:uri "/limerick-generation-task"
|
||||||
|
:body-params {:scheme 23}})
|
||||||
|
)
|
||||||
|
|
||||||
|
(defn get-artist-and-album-for-new-limerick [db]
|
||||||
|
(let [artist (artists/most-recent-artist db)
|
||||||
|
albums (albums/artist-albums db (:artist/id artist))
|
||||||
|
limericks (limericks/album-limericks db (:album/id (first albums)))]
|
||||||
|
(cond
|
||||||
|
(< (count limericks) 10)
|
||||||
|
[(:artist/id artist) (:album/id (first albums))]
|
||||||
|
|
||||||
|
(< (count albums) 5)
|
||||||
|
(let [album-name (linguistics/gen-album)
|
||||||
|
{album-id :album/id} (albums/insert-album db album-name (:id artist))]
|
||||||
|
[(:id artist) album-id])
|
||||||
|
|
||||||
|
:else
|
||||||
|
(let [artist-name (linguistics/gen-artist)
|
||||||
|
{artist-id :artist/id} (artists/insert-artist db artist-name)
|
||||||
|
album-name (linguistics/gen-album)
|
||||||
|
{album-id :album/id} (albums/insert-album db album-name artist-id)]
|
||||||
|
[artist-id album-id]))))
|
||||||
|
|
||||||
|
(defn get-limerick-name [lines]
|
||||||
|
(->> lines
|
||||||
|
(string/join " ")
|
||||||
|
(#(string/split % #"\s+"))
|
||||||
|
shuffle
|
||||||
|
(take 2)
|
||||||
|
(map string/capitalize)
|
||||||
|
(string/join " ")))
|
||||||
|
|
||||||
|
(defn generate-limerick [db scheme task-id]
|
||||||
|
(let [scheme (parse-scheme scheme)]
|
||||||
|
(async/thread
|
||||||
|
(try
|
||||||
|
(let [rhyme-id (java.util.UUID/randomUUID)
|
||||||
|
rhyme (limerick/rhyme-from-scheme
|
||||||
|
dict/prhyme-dict
|
||||||
|
darklyrics-markov-2
|
||||||
|
scheme)]
|
||||||
|
(swap! db update-in [:tasks task-id] assoc :status :finished)
|
||||||
|
(swap! db assoc-in [:limericks rhyme-id] {:text rhyme :task-id task-id})
|
||||||
|
rhyme)
|
||||||
|
(catch Throwable e
|
||||||
|
(println "Exception" e)
|
||||||
|
(swap! db update-in [:tasks task-id] assoc :status :failed)
|
||||||
|
(swap! db assoc-in [:tasks task-id] {:text (.getMessage e)}))))))
|
@ -0,0 +1,84 @@
|
|||||||
|
(ns com.darklimericks.server.system
|
||||||
|
(:require [integrant.core :as ig]
|
||||||
|
[clojure.java.io :as io]
|
||||||
|
[taoensso.timbre :as timbre]
|
||||||
|
[org.httpkit.server :as kit]
|
||||||
|
[next.jdbc :as jdbc]
|
||||||
|
[environ.core :refer [env]]
|
||||||
|
[reitit.http :as http]
|
||||||
|
[reitit.ring :as ring]
|
||||||
|
[reitit.coercion.spec]
|
||||||
|
[reitit.ring.coercion :as coercion]
|
||||||
|
[reitit.interceptor.sieppari :as sieppari]
|
||||||
|
[reitit.http.interceptors.parameters :refer [parameters-interceptor]]
|
||||||
|
[com.darklimericks.server.handlers :as handlers]
|
||||||
|
[com.darklimericks.server.interceptors :as interceptors]
|
||||||
|
[com.darklimericks.server.db :as db]))
|
||||||
|
|
||||||
|
(defmethod ig/prep-key :database.sql/connection [_ _]
|
||||||
|
{:jdbcUrl (str "jdbc:postgresql://localhost:5432/?user="
|
||||||
|
(or (env :postgres-user)
|
||||||
|
"dev")
|
||||||
|
"&password="
|
||||||
|
(or (env :postgres-password)
|
||||||
|
"dev"))})
|
||||||
|
|
||||||
|
(defmethod ig/init-key :database.sql/connection [_ db-spec]
|
||||||
|
(jdbc/get-datasource db-spec))
|
||||||
|
|
||||||
|
(defmethod ig/init-key :app/logging [_ config]
|
||||||
|
(timbre/merge-config! config))
|
||||||
|
|
||||||
|
(defmethod ig/halt-key! :app/logging [_ _])
|
||||||
|
|
||||||
|
(defmethod ig/init-key :app/cache [_ _]
|
||||||
|
(timbre/debug "Initializing cache.")
|
||||||
|
db/db)
|
||||||
|
|
||||||
|
(defmethod ig/halt-key! :app/db [_ db]
|
||||||
|
#_(reset! db {}))
|
||||||
|
|
||||||
|
(defmethod ig/init-key :app/router [_ {:keys [db cache]}]
|
||||||
|
(let [routes [["/" {:name ::home
|
||||||
|
:get {:handler handlers/home-handler}}]
|
||||||
|
["/{letter}.html"
|
||||||
|
{:name ::artists-by-letter
|
||||||
|
:handler (handlers/artists-by-letter db)}]
|
||||||
|
["/limerick-generation-task"
|
||||||
|
{:name ::limerick-generation-task
|
||||||
|
:post {:handler (handlers/limerick-generation-post-handler db cache)}
|
||||||
|
:get {:handler (handlers/limerick-generation-get-handler db cache)}}]
|
||||||
|
["/limericks"
|
||||||
|
["/:artist-id/:album-id"
|
||||||
|
{:name ::album
|
||||||
|
:coercion reitit.coercion.spec/coercion
|
||||||
|
:parameters {:path {:artist-id int?
|
||||||
|
:album-id int?}}
|
||||||
|
:get {:handler (handlers/limericks-get-handler db cache)}}]
|
||||||
|
["/:artist-id"
|
||||||
|
{:name ::artist
|
||||||
|
:coercion reitit.coercion.spec/coercion
|
||||||
|
:parameters {:path {:artist-id int?}}
|
||||||
|
:get {:handler (handlers/artist-get-handler db)}}]]
|
||||||
|
["/assets/*" handlers/resource-handler]]]
|
||||||
|
(http/router
|
||||||
|
routes
|
||||||
|
{:data {:interceptors [interceptors/coerce-request-interceptor
|
||||||
|
interceptors/logging-interceptor
|
||||||
|
interceptors/format-interceptor
|
||||||
|
(parameters-interceptor)
|
||||||
|
interceptors/keywordize-params-interceptor]}})))
|
||||||
|
|
||||||
|
(defmethod ig/init-key :app/handler [_ {:keys [router]}]
|
||||||
|
(http/ring-handler
|
||||||
|
router
|
||||||
|
(ring/create-default-handler)
|
||||||
|
{:executor sieppari/executor}))
|
||||||
|
|
||||||
|
(defmethod ig/init-key :app/server [_ {:keys [handler] :as opts}]
|
||||||
|
(timbre/info (format "Starting server on port %d" (:port opts)))
|
||||||
|
(kit/run-server handler (dissoc opts :handler)))
|
||||||
|
|
||||||
|
(defmethod ig/halt-key! :app/server [_ server]
|
||||||
|
(timbre/info "Stopping server.")
|
||||||
|
(server))
|
@ -0,0 +1,10 @@
|
|||||||
|
(ns com.darklimericks.server.util
|
||||||
|
(:require [reitit.core :as reitit]))
|
||||||
|
|
||||||
|
(defn route-name->path
|
||||||
|
([request name]
|
||||||
|
(route-name->path request name {}))
|
||||||
|
([request name params]
|
||||||
|
(->> name
|
||||||
|
(#(reitit/match-by-name (::reitit/router request) % params))
|
||||||
|
reitit/match->path)))
|
@ -0,0 +1,89 @@
|
|||||||
|
(ns com.darklimericks.server.views
|
||||||
|
(:require [hiccup.form :as form]
|
||||||
|
[hiccup.page :as page]
|
||||||
|
[clojure.string :as string]
|
||||||
|
[com.darklimericks.server.util :as util]))
|
||||||
|
|
||||||
|
(defn page [title & body]
|
||||||
|
(page/html5
|
||||||
|
[:head
|
||||||
|
[:meta {:charset "utf-8"}]
|
||||||
|
[:meta {:name "viewport" :content "width=device-width, initial-scale=1.0"}]
|
||||||
|
(page/include-css "/assets/tachyons.css")
|
||||||
|
[:title title]
|
||||||
|
[:link {:rel "shortcut icon" :href "/assets/favicon.ico"}]]
|
||||||
|
[:body.tc.washed-yellow.bg-near-black.avenir
|
||||||
|
[:h1
|
||||||
|
[:a.link.dim.washed-yellow {:href "/"} "DarkLimericks.com"]]
|
||||||
|
[:div.w-50-ns.w-90.center.bg-dark-gray.pa2
|
||||||
|
[:div.f6.lh-copy.flex.justify-between
|
||||||
|
[:a.washed-yellow {:href "#"} "SUBMIT LIMERICKS"]
|
||||||
|
[:span.dark-yellow "METAL LIMERICKS - CURRENTLY 0 ALBUMS FROM 0+ BANDS"]
|
||||||
|
[:a.washed-yellow {:href "#"} "LINKS"]]
|
||||||
|
[:div.flex.items-stretch.w-100.bg-near-black
|
||||||
|
(let [letters (map (comp str char) (range 97 123))]
|
||||||
|
(for [letter letters]
|
||||||
|
[:a.washed-yellow.bg-mid-gray.w-100.pv2.flex-grow-1
|
||||||
|
{:href (format "/%s.html" letter)
|
||||||
|
:style "margin: 1px;"}
|
||||||
|
(string/upper-case letter)]))]
|
||||||
|
[:div.flex.items-center.justify-center.pv2
|
||||||
|
[:span.f6.ph2 "Search the darkness for limericks heartless"]
|
||||||
|
[:form.ph2
|
||||||
|
{:method "GET" :action "#"}
|
||||||
|
[:input.bg-white
|
||||||
|
{:type "text"
|
||||||
|
:name "search"
|
||||||
|
:id "search"
|
||||||
|
:value ""}]]]
|
||||||
|
[:div.bg-near-black.br4.pa2
|
||||||
|
body]
|
||||||
|
|
||||||
|
[:div.flex.items-center.justify-center.pv2
|
||||||
|
[:span.f6.ph2 "Search the darkness for limericks heartless"]
|
||||||
|
[:form.ph2
|
||||||
|
{:method "GET" :action "#"}
|
||||||
|
[:input.bg-white
|
||||||
|
{:type "text"
|
||||||
|
:name "search"
|
||||||
|
:id "search"
|
||||||
|
:value ""}]]]
|
||||||
|
|
||||||
|
[:div.flex.items-stretch.w-100.bg-near-black
|
||||||
|
(let [letters (map (comp str char) (range 97 123))]
|
||||||
|
(for [letter letters]
|
||||||
|
[:a.washed-yellow.bg-mid-gray.w-100.pv2.flex-grow-1
|
||||||
|
{:href (format "/%s.html" letter)
|
||||||
|
:style "margin: 1px;"}
|
||||||
|
(string/upper-case letter)]))]
|
||||||
|
|
||||||
|
[:div.f6.lh-copy.flex.justify-between
|
||||||
|
[:a.washed-yellow {:href "#"} "SUBMIT LIMERICKS"]
|
||||||
|
[:span.dark-yellow "METAL LIMERICKS - CURRENTLY 0 ALBUMS FROM 0+ BANDS"]
|
||||||
|
[:a.washed-yellow {:href "#"} "LINKS"]]]]))
|
||||||
|
|
||||||
|
(defn home [request]
|
||||||
|
(page "Dark Limericks"
|
||||||
|
(form/form-to
|
||||||
|
[:post (util/route-name->path request :com.darklimericks.server.system/limerick-generation-task)]
|
||||||
|
(form/text-field "scheme")
|
||||||
|
(form/submit-button "Generate dark limerick"))))
|
||||||
|
|
||||||
|
(defn limerick-tasks [tasks]
|
||||||
|
[:ul
|
||||||
|
(for [[task-id task] tasks]
|
||||||
|
[:li (format
|
||||||
|
"%s - %s"
|
||||||
|
task-id
|
||||||
|
(if (:rhyme task)
|
||||||
|
(string/join " / " (:rhyme task))
|
||||||
|
(:status task)))])])
|
||||||
|
|
||||||
|
(defn limerick [i lim]
|
||||||
|
(let [lines (string/split (:limerick/text lim) #"\n")
|
||||||
|
name (:limerick/name lim)]
|
||||||
|
[:div.tc
|
||||||
|
[:a {:name (inc i)}
|
||||||
|
[:h3.f3.washed-yellow (format "%s. %s" (inc i) name)]]
|
||||||
|
(for [line lines]
|
||||||
|
[:div line])]))
|
Loading…
Reference in New Issue