153 lines
3.0 KiB
Plaintext
153 lines
3.0 KiB
Plaintext
|
#!/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/gemshimfeed.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="example.com"
|
||
|
FEED_COPYRIGHT="(c) 2020 CC-BY-SA nobody"
|
||
|
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++)print $i;}'
|
||
|
}
|
||
|
|
||
|
entry_summary() {
|
||
|
return 1
|
||
|
}
|
||
|
|
||
|
entry_author() {
|
||
|
echo "nobody"
|
||
|
}
|
||
|
|
||
|
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/gemshimfeed" version="infinite>GemShimFeed</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/gemshimfeed.conf.sh"
|
||
|
case "$1" in
|
||
|
-h)
|
||
|
usage
|
||
|
exit 0
|
||
|
;;
|
||
|
-c)
|
||
|
CONFIGFILE="$2"
|
||
|
shift 2
|
||
|
;;
|
||
|
esac
|
||
|
|
||
|
. "$CONFIGFILE" || :
|
||
|
|
||
|
atom_header
|
||
|
for DIR; do
|
||
|
for entry in $(recent_files "$DIR" -type f); do
|
||
|
if skip_file "$entry"; then continue; fi
|
||
|
|
||
|
atom_entry "$entry"
|
||
|
done
|
||
|
done
|
||
|
atom_footer
|
||
|
}
|