while I tell ye of my method for posting these moon photos.
The text record
I have a text file at https://www.acdw.net/moon-photos.txt that keeps track of
all the titles for this project, along with a little x
indicating whether they’ve been done or not. This file (or rather, its
copy on my personal computer) is the canonical source of truth for which
moon photos have been taken and which are still available to write.
I’ve written and added to a script to make bookkeeping this file and grabbing a new title each day from this file easier to do.
Grabbing a title
The first couple of days I was doing this, I went to https://www.random.org to
generate a random number between 1 and 400 (the number of lines in my
file). Then I’d manually look up the numbered line (usually by opening
the file in ViM and typing <number>G
, you ViMmers
understand me), and open a new file, copying and pasting in the title.
This process quickly became tedious.
So the first thing I wrote was a quick one-liner to grab myself a title and print it out:
$ sed -n "$((RANDOM % 400))p" moon-photos.txt
Adding numbers
I do a lot of writing at work. So after a few days, I wanted to add the text file to my site and look up titles the old random.org way at work. Adding the file was easy enough, but I didn’t have any line numbers in the web browser, which meant that I had to copy and paste the whole thing every day to ViM at work, then find the line number I wanted. It was too much. So I added line numbers to the beginning of each line, too:
$ cat -n moon-photos.txt > moon-photos.txt~
$ mv moon-photos.txt~ moon-photos.txt
Adding x-s
Around this time, I realized it would be much easier to pull titles
if I just wrote a script on my computer. To make that work, though, I
needed some way to mark titles as completed. I decided a little
x on the left side would work best. So, I added an extra
<TAB>
to the beginning of each line:
$ sed 's/^/ /' < moon-photos.txt > moon-photos.txt~
$ mv moon-photos.txt~ moon-photos.txt
I’ll include the completed script at the bottom of this post. (In fact, I actually started with the script, but I’m writing this narrative kind of backwards in a sort of idiot attempt to make this more interesting.)
Generating a header
Okay, so pulling a title is great, but each post has a whole header block that’s required at the beginning, and each header has a lot of repeated information (and typing). So I wrote this little function to generate a header:
generate_header() {
while :
do
trynum=$(randrange 1 $(wc -l "$1" | cut -d' ' -f1))
getvars $trynum "$1"
if [ -z "$X" ]; then break; fi
done
cat <<-EOH
---
title: "$TITLE"
subtitle: "($((N+0)))"
series: moon photos
tags:
---
EOH
}
randrange
is another little function I pulled from
StackOverflow:
randrange() {
# randrange MIN MAX
MIN="$1"; MAX="$2"
echo $(((RANDOM % (MAX - MIN + 1)) + MIN))
}
And getvars
is a thing I wrote to split a line into
done-ness, number, and title:
getvars() {
# getvars LINE_NUMBER FILE
#X number title
line="$(sed -n "${1}p" "$2")"
X="$(cut -f1 <<<"$line")"
N="$(cut -f2 <<<"$line")"
TITLE="$(cut -f3 <<<"$line")"
}
Emailing it to myself
This worked for a while. It was fun. But soon, it became tedious as well – I didn’t want to bother with using my computer (and remembering to use my computer!) to pull titles and get my posts started. So I thought, Let’s email titleblocks to myself!
It took somea setup with msmtp
, which I won’t get into
here – but here’s the command I used to mail each header to myself:
$ ( echo "Subject: moonphoto: $(date +%F)"; cat "$tmp" ) | msmtp "$email"
Of course, $tmp
is a temporary file I’ve piped the
header to, and $email
is my email address.
Putting it all together
That’s about it – I’ve set up a cron job so that every day at 12:00
AM, moonphoto
(clever name, right?) sends an email to me
with the next moonphoto header block, randomly selected from my
list.
I’ve also added an option to mark a line as done and commit the file in my git repo, as well as the standard usage option.
The script in toto goes thus:
#!/usr/bin/env bash
# write a new moon photo post
blogdir=~/acdw.net/content
titles="$blogdir"/static/moon-photos.txt
email='REDACTED@example.com'
randrange() {
# randrange MIN MAX
MIN="$1"; MAX="$2"
echo $(((RANDOM % (MAX - MIN + 1)) + MIN))
}
getvars() {
# getvars LINE_NUMBER FILE
#X number title
line="$(sed -n "${1}p" "$2")"
X="$(cut -f1 <<<"$line")"
N="$(cut -f2 <<<"$line")"
TITLE="$(cut -f3 <<<"$line")"
}
remove_line() {
# remove_line LINE_NUMBER FILE
tf=$(mktemp)
echo "Marking \"$TITLE\" ($N) done..."
sed "${1} s/^[^x]/x&/" "$2" > "$tf" &&
mv "$tf" "$2" &&
chmod 744 "$2"
}
add_and_commit() {
# add_and_commit LINE_NUMBER FILE
echo "Committing changes..."
pushd "$blogdir"
git add .
git commit -m "Add moonphoto ($1)"
echo "Pushing changes..."
git push
popd
}
generate_header() {
# generate_header FILE
while :
do
trynum=$(randrange 1 $(wc -l "$1" | cut -d' ' -f1))
getvars $trynum "$1"
if [ -z "$X" ]; then break; fi
done
cat <<-EOH
---
title: "$TITLE"
subtitle: "($((N+0)))"
series: moon photos
tags:
---
EOH
}
main() {
MAIL=false;
case "$1" in
(-h)
echo "moonphoto: generate a title"
echo "usage: moonphoto [-h|-l|-m|-x NUM|-c NUM]"
echo "-h: show this help"
echo "-l: list all titles"
echo "-m: email the header"
echo "-x NUM: mark the line NUM as 'done'"
echo "-c NUM: marke line NUM as 'done' and commit changes"
echo
exit 0
;;
(-x)
[[ -n "$2" ]] || exit 1
getvars "$2" "$titles"
remove_line "$N" "$titles"
exit 0
;;
(-c)
[[ -n "$2" ]] || exit 1
getvars "$2" "$titles"
remove_line "$N" "$titles"
add_and_commit "$N" "$titles"
exit 0
(-l)
cat "$titles"
exit 0
;;
(-m) MAIL=true ;;
(*) ;;
esac
tmp="$(mktemp /tmp/mp-XXX.md)"
echo "Generating header > $tmp ..."
generate_header "$titles" | tee "$tmp"
if $MAIL; then
echo "Emailing header to $email..."
(
echo "Subject: moonphoto: $(date +%F)"
cat "$tmp"
) | msmtp "$email"
fi
}
main "$@"