init commit
parent
7c244bf69b
commit
9bb2b1d06c
41
README.md
41
README.md
|
@ -1,3 +1,42 @@
|
|||
# consump
|
||||
|
||||
a convoluted pipeline of transformations that creates an html log of tv shows, podcasts, and music from a plain text database.
|
||||
> it's like goodreads for *x*
|
||||
|
||||
CC BY 4.0 2023
|
||||
|
||||
## about
|
||||
|
||||
a convoluted pipeline of transformations that creates an html log of tv shows, podcasts, and music from a plain text database.
|
||||
|
||||
this is what powers <http://tilde.town/~dozens/consume/>
|
||||
|
||||
## features
|
||||
|
||||
- plain text database!
|
||||
- ed?
|
||||
- produces html/css/javascript (js for filtering content type; css for lookin good; html because don't you want to read it??)
|
||||
- rss feed
|
||||
|
||||
## dependencies
|
||||
|
||||
- recutils: <https://www.gnu.org/software/recutils/>
|
||||
- mustache: <https://mustache.github.io/>
|
||||
- csvjson (csvkit): <https://csvkit.readthedocs.io/>
|
||||
- jq: <https://stedolan.github.io/jq/>
|
||||
- (optional) just: <https://github.com/casey/just>
|
||||
|
||||
## getting started
|
||||
|
||||
1. install dependencies
|
||||
|
||||
2. update `templates/feed.mustache` and `templates/html.mustache` to include your own links and information for the generated rss and html. update the `up` recipe in the justfile to put the generated files wherever you want them.
|
||||
|
||||
3. run `just new`. or copy the 'new' script from the justfile into a bash file and run it. NOTE: this script runs ed(1), because that's what I like. If you are not familiar with ed(1), change that part of the script to use $EDITOR. If you would *like* to be familiar with ed(1) then check out the links listed below.
|
||||
|
||||
4. `just html` and `just rss` will build the html and rss respectively. Again, you can cobble these together from the justfile into a bash script if you don't have/want to install just. `just build` will assemble both the html and the rss.
|
||||
|
||||
## resources
|
||||
|
||||
- https://elly.town/d/blog/2015-10-03-ed-tutorial.txt
|
||||
- http://tilde.town/wiki/learn/editors/ed.html
|
||||
- https://tube.tchncs.de/w/g1ZKSzvDaqbpWQQgxGfW3z
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
%rec: review
|
||||
%doc: a review of some media i consumed
|
||||
%key: id
|
||||
%unique: id
|
||||
%type: id int
|
||||
%type: created date
|
||||
%type: episode,title line
|
||||
%typedef: type enum podcast listening watching playing
|
||||
%auto: id created
|
||||
%mandatory: title body
|
||||
%allowed: id created type title episode body
|
||||
%sort: created
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
database := "db/database.rec"
|
||||
|
||||
# show all commands
|
||||
default:
|
||||
just --list --unsorted
|
||||
|
||||
# create new entry
|
||||
new:
|
||||
#!/usr/bin/env sh
|
||||
read -p "type (p[o]dcast [l]istening [w]atching [p]laying): " typeshort
|
||||
read -p "title: " title
|
||||
read -p "episode? " episode
|
||||
echo "CAUTION: Incoming ed!"
|
||||
tmpfile=$(mktemp)
|
||||
ed "$tmpfile"
|
||||
body=$(< "$tmpfile")
|
||||
rm "$tmpfile"
|
||||
case "$typeshort" in
|
||||
"o") type="podcast";;
|
||||
"l") type="listening";;
|
||||
"w") type="watching";;
|
||||
"p") type="playing";;
|
||||
*) echo "Unknown type!"; exit 1;;
|
||||
esac
|
||||
recins --verbose -t review \
|
||||
-f "type" -v "$type" \
|
||||
-f "title" -v "$title" \
|
||||
-f "episode" -v "$episode" \
|
||||
-f "body" -v "$body" \
|
||||
db/database.rec
|
||||
|
||||
# rec -> json
|
||||
_json:
|
||||
recsel -S created {{database}} \
|
||||
| sed -e 's/^body: /body: <p>/' -e 's/^\+ /+ <p>/' -e '/<p>/ s/$/<\/p>/' \
|
||||
| rec2csv \
|
||||
| csvjson \
|
||||
| jq 'reverse \
|
||||
| map(.body |= gsub("\n"; "\n\n"))' \
|
||||
| jq '. | { data: . }'
|
||||
|
||||
# html
|
||||
html:
|
||||
just _json \
|
||||
| mustache - templates/html.mustache \
|
||||
> www/index.html
|
||||
|
||||
# rss
|
||||
rss:
|
||||
just _json \
|
||||
| mustache - templates/feed.mustache \
|
||||
> www/feed.xml
|
||||
|
||||
# build html and rss
|
||||
build: html rss
|
||||
|
||||
# upload
|
||||
up:
|
||||
rsync -azP --exclude=.git www/ tilde:public_html/consume/
|
||||
|
||||
# build and upload
|
||||
all: build up
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||
<channel>
|
||||
<title>dozens consumes</title>
|
||||
<link>https://tilde.town/~dozens/consume/index.html</link>
|
||||
<description>shows movies games podcasts and music</description>
|
||||
<atom:link rel="self" type="application/rss+xml" href="https://tilde.town/~dozens/consume/feed.xml"/>
|
||||
{{#data}}
|
||||
<item>
|
||||
<title><![CDATA[{{title}}]]></title>
|
||||
<link>https://tilde.town/~dozens/consume/index.html#{{id}}</link>
|
||||
<pubDate>{{created}}</pubDate>
|
||||
<guid>https://tilde.town/~dozens/consume/index.html#{{id}}</guid>
|
||||
<description>
|
||||
<![CDATA[
|
||||
<p>{{created}}</p>
|
||||
{{#episode}}
|
||||
<p>Episode: {{.}}</p>
|
||||
{{/episode}}
|
||||
{{{body}}}
|
||||
]]>
|
||||
</description>
|
||||
</item>
|
||||
{{/data}}
|
||||
</channel>
|
||||
</rss>
|
|
@ -0,0 +1,102 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
|
||||
<link rel="alternate" type="application/rss+xml" href="https://tilde.town/~dozens/consume/feed.xml" title="dozens consumes" />
|
||||
<title>consump</title>
|
||||
<style>
|
||||
body {
|
||||
max-width: 80ch;
|
||||
margin: 3rem auto;
|
||||
line-height: 1.8;
|
||||
font-size: 20px;
|
||||
}
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
h1, h2 {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
}
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
nav a {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav>
|
||||
<p>
|
||||
Filter by:
|
||||
<a id="filterAll" href="#">All</a> |
|
||||
<a id="filterWatching" href="#">Watching</a> |
|
||||
<a id="filterListening" href="#">Listening</a> |
|
||||
<a id="filterPlaying" href="#">Playing</a> |
|
||||
<a id="filterPodcast" href="#">Podcast</a>
|
||||
</p>
|
||||
</nav>
|
||||
<h1>All The Media I Consume</h1>
|
||||
<p><a href="https://www.goodreads.com/user/show/409485-chrisman">except for books</a></p>
|
||||
<header>
|
||||
<main>
|
||||
{{#data}}
|
||||
<article class={{type}}>
|
||||
<h2 id="{{id}}">{{title}}</h2>
|
||||
<p>
|
||||
<small>
|
||||
<date>
|
||||
{{created}}
|
||||
</date>
|
||||
{{#episode}}
|
||||
<span> | Episode: {{.}}</span>
|
||||
{{/episode}}
|
||||
</small>
|
||||
</p>
|
||||
{{{body}}}
|
||||
</article>
|
||||
{{/data}}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
<script>
|
||||
// clicky links
|
||||
const filterAll = document.querySelector('#filterAll');
|
||||
const filterWatching = document.querySelector('#filterWatching');
|
||||
const filterListening = document.querySelector('#filterListening');
|
||||
const filterPlaying = document.querySelector('#filterPlaying');
|
||||
const filterPodcast = document.querySelector('#filterPodcast');
|
||||
|
||||
// dom nodes
|
||||
const watching = document.querySelectorAll('.watching')
|
||||
const listening = document.querySelectorAll('.listening')
|
||||
const playing = document.querySelectorAll('.playing')
|
||||
const podcast = document.querySelectorAll('.podcast')
|
||||
const all = document.querySelectorAll('.watching, .listening, .playing, .podcast')
|
||||
|
||||
// event listeners
|
||||
function hideandshow(fn) {
|
||||
return function(e) {
|
||||
e.preventDefault()
|
||||
all.forEach(x => {
|
||||
x.style.display = 'none';
|
||||
})
|
||||
fn.forEach(x => {
|
||||
x.style.display = 'block';
|
||||
})
|
||||
}
|
||||
}
|
||||
filterAll.addEventListener('click', hideandshow(all))
|
||||
filterWatching.addEventListener('click', hideandshow(watching))
|
||||
filterListening.addEventListener('click', hideandshow(listening))
|
||||
filterPlaying.addEventListener('click', hideandshow(playing))
|
||||
filterPodcast.addEventListener('click', hideandshow(podcast))
|
||||
</script>
|
Loading…
Reference in New Issue