diff --git a/.editorconfig b/.editorconfig index 270aad7..c9e3e2a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,6 +1,6 @@ root = true -[*.sh] +[*.{sh,conf,conf.dist}] charset = utf-8 indent_style = space indent_size = 2 diff --git a/icscheck.sh b/icscheck.sh new file mode 120000 index 0000000..2e732a0 --- /dev/null +++ b/icscheck.sh @@ -0,0 +1 @@ +icscheck/icscheck.sh \ No newline at end of file diff --git a/icscheck/.gitignore b/icscheck/.gitignore new file mode 100644 index 0000000..ed87aad --- /dev/null +++ b/icscheck/.gitignore @@ -0,0 +1,4 @@ +/*.conf + +# ics storage +/store diff --git a/icscheck/icscheck.conf.dist b/icscheck/icscheck.conf.dist new file mode 100644 index 0000000..36206f8 --- /dev/null +++ b/icscheck/icscheck.conf.dist @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +# Configuration file for icscheck.sh +# https://winklerfamilie.eu/git/SmallThings/icsutils.git + +local icsconf_url="https://somethi.ng" +local icsconf_output="${HOME}/my.ics" + +# icsError +# Called if the download from ${icsconf_url} failed +icsError() { + echo ICS Error +} + +# icsChanged +icsChanged() { + echo ICS Changed. Generate ${icsconf_output} + [ ! e "${2:-}" ] && printf "First " + printf 'change of %s -> %s\n' "${1:-}" "${2:-}" +} + diff --git a/icscheck/icscheck.sh b/icscheck/icscheck.sh new file mode 100755 index 0000000..3f44395 --- /dev/null +++ b/icscheck/icscheck.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash + +# Author: Martin Winkler +# License: Please refer to the repository +# Origin: https://winklerfamilie.eu/git/SmallThings/icsutils.git + + +# Exit on error inside any functions or subshells. +set -o errtrace +# Do not allow use of undefined vars. Use ${VAR:-} to use an undefined VAR +set -o nounset +# Catch the error in case mysqldump fails (but gzip succeeds) in `mysqldump |gzip` +set -o pipefail + +icsusage() { + cat< +icscheck() { + readonly origin="$(cd "$(dirname -- "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)" + + local arg= + local ics_name= + local ics_url= + local ics_output= + local ics_config= + local diff_ignore= + local renew=0 + + color_red= ; [ -t 1 ] && color_red='\033[0;31m' + color_less= ; [ -t 1 ] && color_less='\033[0m' # No Color + + for arg in "${@}" ; do + case "${1:-}" in + --help|-h) + icsusage && return 0 ;; + --renew|-r) + renew=1 && shift ;; + --) + shift && break ;; + esac + done + + ics_name="${1:-"icscheck"}" + ics_config="${origin}/${ics_name}.conf" + . "${ics_config}" 2>/dev/null || { error "${ics_config} not found" && return 1; } + + ics_url="${icsconf_url:?"$(error "URL to ics file must not be empty.")"}" + ics_output="${icsconf_output:?"$(error "Download destination must not be empty")"}" + + readonly ics_temp_dir="/tmp/icscheck" + readonly ics_store_dir="${origin}/store" + readonly ics_down_file="$ics_temp_dir/${ics_name}_new.ics" + readonly ics_store_file="${ics_store_dir}/${ics_name}.last.ics" + readonly ics_diff="${ics_store_dir}/${ics_name}.diff" + + mkdir -p "${ics_temp_dir}" "${ics_store_dir}" + + wget -O "$ics_down_file" "$ics_url" >/dev/null 2>&1 + + # -s : exists and size greater zero + if [ ! -s "$ics_down_file" ] || [ ! -r "$ics_down_file" ]; then + icsError + exit 1 + fi + + # Delete storage if manual renew is requested + (( renew )) && rm -f "${ics_store_file}" + + # Find differences in download and send notification + diff_ignore="^DTSTAMP:.*" + diff <(grep -vE "$diff_ignore" "$ics_down_file") <(grep -vE "$diff_ignore" "$ics_store_file" 2>/dev/null) > "$ics_diff" 2>/dev/null + if [ $? -eq 1 ]; then + icsChanged "${ics_down_file}" "${ics_store_file}" "${ics_diff}" + + # Save download for next comparison + cp -f "$ics_down_file" "$ics_store_file" + fi +} + +icscheck "${@}"