Skip to content

Instantly share code, notes, and snippets.

@ruario
Last active Sep 15, 2022
Embed
What would you like to do?
A small script to convert my Gemtext journal into an atom feed
#!/usr/bin/env bash
BASE_DOMAIN="ruario.flounder.online"
MICROLOG_FILENAME="journal.gmi"
MICROLOG_URL="//$BASE_DOMAIN/$MICROLOG_FILENAME"
ATOM_FILENAME="${MICROLOG_FILENAME%.gmi}-atom.xml"
ATOM_URL="//$BASE_DOMAIN/$ATOM_FILENAME"
MICROLOG_TITLE="Ruari's Journal"
AUTHOR_NAME=ruario
MAX_FEEDS=20
LINE_LENGTH=55
date_convert () {
if [ `uname -s` = Linux ]; then
date -ud "$1" +'%FT%H:%M:00Z'
else
date -ujf '%F %H:%M %z' "$1" +'%FT%H:%M:00Z'
fi
}
safe_echo () {
printf '%s\n' "$1" | sed 's/\&/\&#x26;/g;s/</\&#x3C;/g'
}
clip_line () {
while IFS= read -r l;
do
if [ "$PREFORMAT" = ON ]; then
printf '%s\n' "$l"
else
case "$l" in
'* '*) # Lists
printf '%s\n' "$l" | fmt -w "$(($LINE_LENGTH - 2))" | sed -E 's/^([^\*])/ \1/'
;;
'=>'*) # Links
printf '%s\n' "$l" | sed -E 's/^=>[[:blank:]]*([^[:blank:]]+)[[:blank:]]+(.*)/~ \2:\n\1\n/;s/^=>[[:blank:]]*([^[:blank:]]+)/~ :\n\1/' \
| while IFS= read -r ll;
do
case "$ll" in
~*)
printf '%s\n' "$ll" | fmt -w "$(($LINE_LENGTH - 2))" | sed -E 's/^([^\~])/ \1/'
;;
*)
printf '%s\n' "$ll"
;;
esac
done
;;
'>'*) # Quote
printf '%s\n' "$l" | sed -E 's/^>[[:blank:]]?//' | fmt -w "$(($LINE_LENGTH - 2))" | sed 's/^/> /'
;;
*)
printf '%s\n' "$l" | fmt -w "$LINE_LENGTH"
;;
esac
fi
done
}
PREFORMAT=OFF
PRINT_HEADER=ON
FULL_DATE_AVAILABLE=NO
NEW_SECTION_START=NO
CLOSE_ENTRY=NO
FEED_COUNTER=0
{
while IFS= read -r LINE;
do
if [ "$NEW_SECTION_START" = YES ]; then
if [ "$PRINT_HEADER" = ON ]; then
cat <<EOF
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>$MICROLOG_TITLE</title>
<link rel="self" href="$ATOM_URL"/>
<link href="$MICROLOG_URL"/>
<updated>$(date_convert "$JRNLDAY $JRNLTIME")</updated>
<author>
<name>$AUTHOR_NAME</name>
<uri>gemini://$BASE_DOMAIN/</uri>
</author>
<id>gemini:$MICROLOG_URL</id>
EOF
PRINT_HEADER=OFF
fi
if [ "$SECTION_INTRO" = YES ]; then
if [ "$CLOSE_ENTRY" = YES ]; then
if [ "$FEED_COUNTER" -ge "$(( $MAX_FEEDS - 1 ))" ]; then
break
fi
cat <<EOF
</pre></div></content>
</entry>
EOF
FEED_COUNTER="$(( $FEED_COUNTER + 1 ))"
fi
CLOSE_ENTRY=YES
cat <<EOF
<entry>
<title>@${JRNLTIME}$JRNLTITLE</title>
<link rel="alternate" href="$MICROLOG_URL"/>
<id>gemini:$MICROLOG_URL/$JRNLDAY-$(echo "$JRNLTIME" | cut -d' ' -f1 | tr -d ':')</id>
<updated>$(date_convert "$JRNLDAY $JRNLTIME")</updated>
<summary type="text">$JRNLSUMMARY</summary>
<content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><pre>
EOF
safe_echo "$FIRSTLINE" | clip_line
SECTION_INTRO=NO
fi
case "$LINE" in
'## '*)
JRNLDAY=$(echo $LINE | cut -d' ' -f2-)
;;
'### '*)
JRNLTIME=$(echo $LINE | cut -d' ' -f2-)
NEW_SECTION_START=NO
SECTION_INTRO=YES
;;
'```'*)
if [ "$PREFORMAT" = OFF ]; then
PREFORMAT=ON
else
PREFORMAT=OFF
fi
;;
'')
break
;;
*)
safe_echo "$LINE" | clip_line
;;
esac
elif [ "$FULL_DATE_AVAILABLE" = YES ]; then
case "$LINE" in
[[:alnum:]\>=@\'\"~]*)
JRNLSUMMARY="$(printf '%s\n' "$LINE" | sed -E 's/^=>[[:blank:]]*[^[:blank:]]+[[:blank:]]+//;s/\&/\&#x26;/g;s/</\&#x3C;/g')"
JRNLTITLE="$(printf '%s\n' "$JRNLSUMMARY" | cut -c 1-49 | sed "s/$/…/")"
FIRSTLINE="$LINE"
NEW_SECTION_START=YES
;;
*)
:
;;
esac
else
case "$LINE" in
'## '*)
JRNLDAY=$(echo $LINE | cut -d' ' -f2-)
;;
'### '*)
FULL_DATE_AVAILABLE=YES
JRNLTIME=$(echo $LINE | cut -d' ' -f2-)
SECTION_INTRO=YES
;;
*)
:
;;
esac
fi
done < $MICROLOG_FILENAME
cat <<EOF
</pre></div></content>
</entry>
</feed>
EOF
} | cat -s > $ATOM_FILENAME
echo "Created: $ATOM_FILENAME"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment