notify of changes by email

master
Y 2020-02-08 23:02:52 +01:00
parent 726d238281
commit 90c3e7aee9
1 changed files with 66 additions and 6 deletions

View File

@ -8,17 +8,19 @@
#
# From EPSI “edtmobilityeng” to ICS, for the current school year. Usage:
#
# epsiEDTtoICS.sh -u <user> [ -c [ <path> | - ] ] [ -j ]
# epsiEDTtoICS.sh -u <user> [ -p [ <path> | - ] [ -w <count> ] ] [ -j ]
# epsiEDTtoICS.sh -u <user> [ -c [ <path> | - ] ] [ -j ] [ -m <to> ]
# epsiEDTtoICS.sh -u <user> [ -p [ <path> | - ] [ -w <count> ] ] [ -j ] [ -m <to> ]
# <user>: EPSI Login (firstname.lastname)
# <path>: Location where the ICS file is created (-c) or patched (-p)
# <count>: Number of weeks to update (including the current one), if -p is specified
# <to>: Comma-separated list of email recipients (needs sendmail in the PATH)
#
# If no path is given, “-” is assumed, which is a placeholder for the standard output.
# If neither -c nor -p is given, “-c -” is assumed.
# If -p is used with “-” as a path, then only the updated weeks are sent to the standard output.
# If -p is given without -w, the default count of updated weeks is 5.
# If -j is used, logs are sent to systemd-journald instead of the standard error (needs systemd-cat).
# If -m is used, the given recipients are notified of changes between runs
LANG8BIT=fr_FR@euro
@ -27,14 +29,16 @@ PATCH=
OUTPUT=-
MAXOFFSET=
JOURNAL=
TO=
readonly -a LEVELS=( emerg alert crit err warning notice info debug )
while getopts u:c:p:w:j arg; do case "$arg" in
while getopts u:c:p:w:jm: arg; do case "$arg" in
u) LOGIN="$OPTARG" ;;
c) OUTPUT="${OPTARG:--}"; PATCH= ;;
p) OUTPUT="${OPTARG:--}"; PATCH=true ;;
w) MAXOFFSET="${OPTARG//[^0-9]}" ;;
j) JOURNAL=true ;;
m) TO="$OPTARG" ;;
esac; done
# $1: log level ∈ [0 … 7]
@ -72,6 +76,10 @@ function check_parameters_and_set_defaults() {
JOURNAL=
log 4 "Command “systemd-cat” not found"
fi
if [ -n "$TO" ] && ! which sendmail >/dev/null; then
TO=
log 4 "Command “sendmail” not found"
fi
MAXOFFSET=$((${MAXOFFSET:-5}*7))
}
@ -83,9 +91,61 @@ function lf_to_crlf() {
sed 's/$/\r/'
}
function write_output() {
function crlf_to_lf() {
tr -d '\r'
}
# &0: standard ical, with long lines wrapped
# &1: long lines are unwrapped
function unwrap_ical_long_lines() {
sed ':n;N;s/\n //;tn;P;D'
}
# $1: path to the old file
# $2: path to the new file
function format_diff_and_send_mail() {
{
echo "To: $TO"
echo "Subject: Changes in EPSI calendar"
echo
diff -u8 \
<(crlf_to_lf <"$1" | unwrap_ical_long_lines | grep -vE '^DTSTAMP:|^UID:') \
<(crlf_to_lf <"$2" | unwrap_ical_long_lines | grep -vE '^DTSTAMP:|^UID:') \
| awk '
function out() {
if (inDiff+inEvent==2) printf("%s", diff)
inDiff=0
inEvent=0
}
/BEGIN:VEVENT/ { inEvent=1; diff="\n"; next }
$0 ~ /^[-+]/ { inDiff=1 }
/^@|END:VEVENT/ { out() }
{ diff=diff $0 "\n" }' \
| while IFS='' read -r l; do
case "$l" in
'')
echo; continue ;;
?DT*)
h="$(sed -r 's/^.DT(.*):.*/\1/' <<<"$l")"
v="$(date -d $(sed -r 's/.*:(....)(..)(..T..)(..)(..Z)/\1-\2-\3:\4:\5/' <<<"$l"))" ;;
*)
IFS=: read -r h v <<<"${l#?}" ;;
esac
printf '%s %11s: %s\n' "${l:0:1}" "$h" "$v"
done
} \
| lf_to_crlf \
| sendmail -t
}
function write_output_and_send_mail() {
[ "$OUTPUT" == - ] && cat || {
cat >"${OUTPUT}.tmp" && mv -f "${OUTPUT}.tmp" "$OUTPUT" || {
cat >"${OUTPUT}.tmp" \
&& {
[ -n "$TO" ] && format_diff_and_send_mail "$OUTPUT" "${OUTPUT}.tmp"
mv -f "${OUTPUT}.tmp" "$OUTPUT"
} \
|| {
log 3 "Failed to write to: $OUTPUT"
exit 20
}
@ -304,7 +364,7 @@ function main() {
} \
| fold_long_lines \
| lf_to_crlf \
| write_output
| write_output_and_send_mail
}
main