diff options
-rw-r--r-- | gemshimfeed | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/gemshimfeed b/gemshimfeed new file mode 100644 index 0000000..a3eb3c0 --- /dev/null +++ b/gemshimfeed | |||
@@ -0,0 +1,152 @@ | |||
1 | #!/bin/sh | ||
2 | # generate a Atom feed from a directory, recursively | ||
3 | # using POSIX sh | ||
4 | # AUTHOR: Case Duckworth <acdw@acdw.net> | ||
5 | # LICENSE: MIT | ||
6 | |||
7 | usage() { | ||
8 | cat <<END | ||
9 | $0: generate an Atom feed from directories of files | ||
10 | INVOCATION: | ||
11 | $0 [-h] [-c CONFIG] DIRECTORY... | ||
12 | |||
13 | OPTIONS: | ||
14 | -h show this help | ||
15 | -c CONFIG change the CONFIG file. | ||
16 | Default: $PWD/gemshimfeed.conf.sh | ||
17 | END | ||
18 | } | ||
19 | |||
20 | # FEED VARIABLES | ||
21 | FEED_TITLE=example | ||
22 | FEED_SUBTITLE="an example" | ||
23 | FEED_URL="https://example.com/atom.xml" | ||
24 | SITE_URL="https://example.com/" | ||
25 | FEED_ID="example.com" | ||
26 | FEED_COPYRIGHT="(c) 2020 CC-BY-SA nobody" | ||
27 | FEED_UPDATED=$(date -u +'%FT%TZ') | ||
28 | |||
29 | # FUNCTIONS | ||
30 | |||
31 | recent_files() { # recent_files DIRECTORY FIND_ARG... | ||
32 | # list files, in order of recency | ||
33 | # BOO: REQUIRES GNU FIND :( :( :( :( | ||
34 | # possibly look into https://unix.stackexchange.com/questions/9247/ | ||
35 | # for more possibilities if you don't have GNU find. | ||
36 | dir="$1" | ||
37 | shift | ||
38 | |||
39 | find "$dir" -maxdepth 1 \ | ||
40 | "$@" \ | ||
41 | -not -name '.*' \ | ||
42 | -printf '%T@\t%p\n' | | ||
43 | sort -nr | | ||
44 | cut -f2 | ||
45 | } | ||
46 | |||
47 | # ENTRY FUNCTIONS | ||
48 | |||
49 | skip_entry() { | ||
50 | return 1 | ||
51 | } | ||
52 | |||
53 | entry_url() { | ||
54 | basename="${1#$DIRECTORY}" | ||
55 | echo "$FEED_URL/$basename" | ||
56 | } | ||
57 | |||
58 | entry_title() { | ||
59 | awk '/^#+[ ]\S/{for(i=2;i<=NF;i++)print $i;}' | ||
60 | } | ||
61 | |||
62 | entry_summary() { | ||
63 | return 1 | ||
64 | } | ||
65 | |||
66 | entry_author() { | ||
67 | echo "nobody" | ||
68 | } | ||
69 | |||
70 | entry_content() { | ||
71 | cat "$1" | ||
72 | } | ||
73 | |||
74 | entry_updated() { | ||
75 | # requires stat(1). | ||
76 | # probably another way. | ||
77 | # possibly using ls(1). | ||
78 | stat -c '%y' "$1" | | ||
79 | awk '{ | ||
80 | sub(/\..*/,"",$2); | ||
81 | sub(/[0-9][0-9]/,"&:",$3); | ||
82 | print $1"T"$2$3;}' | ||
83 | } | ||
84 | |||
85 | # ATOM FUNCTIONS | ||
86 | |||
87 | atom_header() { | ||
88 | cat <<END | ||
89 | <?xml version="1.0" encoding="utf-8"?> | ||
90 | <feed xmlns="http://www.w3.org/2005/Atom"> | ||
91 | <title>$FEED_TITLE</title> | ||
92 | <subtitle>$FEED_SUBTITLE</subtitle> | ||
93 | <link href="$FEED_URL" rel="self" /> | ||
94 | <link href="$SITE_URL" /> | ||
95 | <id>$FEED_ID</id> | ||
96 | <generator uri="https://git.sr.ht/~acdw/gemshimfeed" version="infinite>GemShimFeed</generator> | ||
97 | <rights>$FEED_COPYRIGHT</rights> | ||
98 | <updated>$FEED_UPDATED</updated> | ||
99 | END | ||
100 | } | ||
101 | |||
102 | atom_footer() { | ||
103 | cat <<END | ||
104 | </feed> | ||
105 | END | ||
106 | } | ||
107 | |||
108 | atom_entry() { # atom_entry FILE | ||
109 | ENTRY_URL="$(entry_url "$1")" | ||
110 | ENTRY_TITLE="$(entry_title "$1")" | ||
111 | ENTRY_SUMMARY="$(entry_summary "$1")" | ||
112 | ENTRY_AUTHOR="$(entry_author "$1")" | ||
113 | ENTRY_CONTENT="$(entry_content "$1")" | ||
114 | ENTRY_UPDATED="$(entry_updated "$1")" | ||
115 | cat <<END | ||
116 | <entry> | ||
117 | <id>$ENTRY_URL</id> | ||
118 | <link rel="alternate" href="$ENTRY_URL" /> | ||
119 | <title>$ENTRY_TITLE</title> | ||
120 | <summary>$ENTRY_SUMMARY</summary> | ||
121 | <updated>$ENTRY_UPDATED</updated> | ||
122 | <author><name>$ENTRY_AUTHOR</name></author> | ||
123 | <content type="text"><![CDATA[$ENTRY_CONTENT]]></content> | ||
124 | </entry> | ||
125 | END | ||
126 | } | ||
127 | |||
128 | main() { | ||
129 | CONFIGFILE="$PWD/gemshimfeed.conf.sh" | ||
130 | case "$1" in | ||
131 | -h) | ||
132 | usage | ||
133 | exit 0 | ||
134 | ;; | ||
135 | -c) | ||
136 | CONFIGFILE="$2" | ||
137 | shift 2 | ||
138 | ;; | ||
139 | esac | ||
140 | |||
141 | . "$CONFIGFILE" || : | ||
142 | |||
143 | atom_header | ||
144 | for DIR; do | ||
145 | for entry in $(recent_files "$DIR" -type f); do | ||
146 | if skip_file "$entry"; then continue; fi | ||
147 | |||
148 | atom_entry "$entry" | ||
149 | done | ||
150 | done | ||
151 | atom_footer | ||
152 | } | ||