165 lines
3.3 KiB
Bash
Executable File
165 lines
3.3 KiB
Bash
Executable File
#!/bin/sh
|
|
# generate a Atom feed from a directory, recursively
|
|
# using POSIX sh
|
|
# AUTHOR: Case Duckworth <acdw@acdw.net>
|
|
# LICENSE: MIT
|
|
|
|
usage() {
|
|
cat <<END
|
|
$0: generate an Atom feed from directories of files
|
|
INVOCATION:
|
|
$0 [-h] [-c CONFIG] DIRECTORY...
|
|
|
|
OPTIONS:
|
|
-h show this help
|
|
-c CONFIG change the CONFIG file.
|
|
Default: $PWD/$0.conf.sh
|
|
END
|
|
}
|
|
|
|
# FEED VARIABLES
|
|
FEED_TITLE=example
|
|
FEED_SUBTITLE="an example"
|
|
FEED_URL="https://example.com/atom.xml"
|
|
SITE_URL="https://example.com"
|
|
FEED_ID="${SITE_URL#*//}"
|
|
FEED_AUTHOR="nobody"
|
|
FEED_COPYRIGHT="(c) 2020 CC-BY-SA $FEED_AUTHOR"
|
|
FEED_UPDATED=$(date -u +'%FT%TZ')
|
|
|
|
# FUNCTIONS
|
|
|
|
recent_files() { # recent_files DIRECTORY FIND_ARG...
|
|
# list files, in order of recency
|
|
# BOO: REQUIRES GNU FIND :( :( :( :(
|
|
# possibly look into https://unix.stackexchange.com/questions/9247/
|
|
# for more possibilities if you don't have GNU find.
|
|
dir="$1"
|
|
shift
|
|
|
|
find "$dir" -maxdepth 1 \
|
|
"$@" \
|
|
-not -name '.*' \
|
|
-printf '%T@\t%p\n' |
|
|
sort -nr |
|
|
cut -f2
|
|
}
|
|
|
|
# ENTRY FUNCTIONS
|
|
|
|
skip_entry() {
|
|
return 1
|
|
}
|
|
|
|
entry_url() {
|
|
basename="${1#$DIRECTORY}"
|
|
echo "$FEED_URL/$basename"
|
|
}
|
|
|
|
entry_title() {
|
|
awk '/^#+[ ]\S/{
|
|
for(i=2;i<=NF;i++) {
|
|
printf $i;
|
|
if (i!=NF) printf " ";
|
|
}
|
|
printf "\n";exit}' "$1"
|
|
}
|
|
|
|
entry_summary() {
|
|
return 1
|
|
}
|
|
|
|
entry_author() {
|
|
echo "$FEED_AUTHOR"
|
|
}
|
|
|
|
entry_content() {
|
|
cat "$1"
|
|
}
|
|
|
|
entry_updated() {
|
|
# requires stat(1).
|
|
# probably another way.
|
|
# possibly using ls(1).
|
|
stat -c '%y' "$1" |
|
|
awk '{
|
|
sub(/\..*/,"",$2);
|
|
sub(/[0-9][0-9]/,"&:",$3);
|
|
print $1"T"$2$3;}'
|
|
}
|
|
|
|
# ATOM FUNCTIONS
|
|
|
|
atom_header() {
|
|
cat <<END
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<feed xmlns="http://www.w3.org/2005/Atom">
|
|
<title>$FEED_TITLE</title>
|
|
<subtitle>$FEED_SUBTITLE</subtitle>
|
|
<link href="$FEED_URL" rel="self" />
|
|
<link href="$SITE_URL" />
|
|
<id>$FEED_ID</id>
|
|
<generator uri="https://git.sr.ht/~acdw/shatom" version="infinite">shatom</generator>
|
|
<rights>$FEED_COPYRIGHT</rights>
|
|
<updated>$FEED_UPDATED</updated>
|
|
END
|
|
}
|
|
|
|
atom_footer() {
|
|
cat <<END
|
|
</feed>
|
|
END
|
|
}
|
|
|
|
atom_entry() { # atom_entry FILE
|
|
ENTRY_URL="$(entry_url "$1")"
|
|
ENTRY_TITLE="$(entry_title "$1")"
|
|
ENTRY_SUMMARY="$(entry_summary "$1")"
|
|
ENTRY_AUTHOR="$(entry_author "$1")"
|
|
ENTRY_CONTENT="$(entry_content "$1")"
|
|
ENTRY_UPDATED="$(entry_updated "$1")"
|
|
cat <<END
|
|
<entry>
|
|
<id>$ENTRY_URL</id>
|
|
<link rel="alternate" href="$ENTRY_URL" />
|
|
<title>$ENTRY_TITLE</title>
|
|
<summary>$ENTRY_SUMMARY</summary>
|
|
<updated>$ENTRY_UPDATED</updated>
|
|
<author><name>$ENTRY_AUTHOR</name></author>
|
|
<content type="text"><![CDATA[$ENTRY_CONTENT]]></content>
|
|
</entry>
|
|
END
|
|
}
|
|
|
|
main() {
|
|
CONFIGFILE="$PWD/$0.conf.sh"
|
|
case "$1" in
|
|
-h)
|
|
usage
|
|
exit 0
|
|
;;
|
|
-c)
|
|
CONFIGFILE="$2"
|
|
shift 2
|
|
;;
|
|
esac
|
|
|
|
if [ -f "CONFIGFILE" ]; then
|
|
. "$CONFIGFILE"
|
|
fi
|
|
|
|
atom_header
|
|
for DIR; do
|
|
for entry in $(recent_files "$DIR" -type f); do
|
|
if skip_entry "$entry"; then continue; fi
|
|
|
|
atom_entry "$entry"
|
|
done
|
|
done
|
|
atom_footer
|
|
}
|
|
|
|
if [ $DEBUG ]; then set -x; fi
|
|
|
|
main "$@"
|