#!/bin/sh # vi:syntax=bash # Copyright 2024 Paul Hänsch # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above # copyright notice and this permission notice appear in all copies. # # THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. . "$_EXEC/cgilite/cgilite.sh" . "$_EXEC/acl.sh" . "$_EXEC/tools.sh" . "$_EXEC/datetime.sh" tags='' ntags='' dir='' depth='' glob_system_pages=false label='' labeltype='' altlabel='' cnt=0 set -- "$@" -- while [ $# -gt 0 ]; do case $1 in --system) glob_system_pages=true; shift 1;; --depth) depth="$2" shift 2;; \#*) tags="${tags}${tags:+ }${1###}"; shift 1;; \!*) ntags="${ntags}${ntags:+ }${1##!}"; shift 1;; --date|--from) fromdate="$2"; shift 2;; --weekstart|--ws|-ws) ws="$2"; shift 2;; --) shift 1; break;; *) if [ ! "$dir" ]; then dir="$1" set -- "$@" "$1"; shift 1; elif [ ! "$depth" ]; then depth="$1"; shift 1; else set -- "$@" "$1"; shift 1; fi;; esac; done [ "$*" ] || set -- "." [ "$depth" -ge 0 -o "$depth" -le 0 ] 2>&- || depth=0 read DY DM DD <<-EOF $(isdate "$fromdate" \ && date -ud "$fromdate" +"%Y %m %d" \ || date -u +"%Y %m %d" ) EOF case $ws in 0|[sS]*) ws=0;; 1|[mM]*) ws=1;; *) ws=0;; esac rrexpand() { # Recurrence Expansion # read recurring event specifications and expand them to a list of # single events within the specified time frame local dstart="$1" dend="$2" local junk1 start end rrfreq rrint rrend evtitle evlink junk2 while read -r junk1 start end rrfreq rrint rrend evtitle evlink junk2; do [ ! "$start" ] && continue # empty line [ "$rrend" -eq -1 ] && rrend=9999999999 if [ "$start" -lt "$dend" ] && [ "$end" -gt "$dstart" -o "$rrend" -gt "$dstart" ]; then case $rrint in day) rrex_day;; week) rrex_week;; month) rrex_month;; year) rrex_year;; weekday) [ "$rrfreq" -ge 0 ] && rrex_weekday \ || rrex_lastweekday ;; *): printf '%i %i %s %s\n' "$start" "$end" "$evtitle" "$evlink" ;; esac fi done } rrex_day() { # helper for rrexpand daily/N-day expansion local nstart nend nend=$(( rrfreq * 86400 - (dstart - end) % (rrfreq * 86400) + dstart )) nstart=$(( start - end + nend)) while [ "$nstart" -lt "$rrend" -a "$nstart" -lt "$dend" ]; do [ "$nstart" -ge "$start" ] \ && printf '%i %i %s %s\n' "$nstart" "$nend" "$evtitle" "$evlink" nstart="$((nstart + rrfreq * 86400))" nend="$((nstart - start + end))" done } rrex_week() { # helper for rrexpand weekly/N-week expansion local nstart nend nend=$(( 0 * 604800 - (dstart - end) % (rrfreq * 604800) + dstart )) nstart=$(( start - end + nend)) while [ "$nstart" -lt "$rrend" -a "$nstart" -lt "$dend" ]; do [ "$nstart" -ge "$start" -a "$nstart" -ge "$dstart" ] \ && printf '%i %i %s %s\n' "$nstart" "$nend" "$evtitle" "$evlink" nstart="$((nstart + rrfreq * 7 * 86400))" nend="$((nstart - start + end))" done } rrex_month() { # helper for rrexpand monthly/N-month expansion local nstart nend { read _y _m _d; read y m d start_time; } <<-EOF $(date -ud @$dstart +"%Y %_m %_d" date -ud @$start +"%Y %_m %_d %T" ) EOF _m=$((_y * 12 + _m)) m=$((y * 12 + m)) while :; do m=$(( rrfreq - ((_m - m - 1) % rrfreq + 1) + _m )) nstart="$(printf '%04i-%02i-%02i' "$(( (m - 1) / 12 ))" "$(( (m - 1) % 12 + 1 ))" "$d")" if isdate "$nstart" && [ "$(date -ud "$nstart" +%s)" -ge "$dstart" ]; then break fi >/dev/null _m="$((_m + rrfreq))" done nstart="$(date -ud "$nstart $start_time" +%s)" nend="$((end - start + nstart))" while [ "$nstart" -lt "$rrend" -a "$nstart" -lt "$dend" ]; do [ "$nstart" -ge "$start" ] \ && printf '%i %i %s %s\n' "$nstart" "$nend" "$evtitle" "$evlink" m="$((m + rrfreq))" nstart="$(printf '%04i-%02i-%02i' "$(( (m - 1) / 12 ))" "$(( (m - 1) % 12 + 1 ))" "$d")" nstart="$(date -ud "$nstart $start_time" +%s)" nend="$((nstart - start + end))" done } rrex_year() { # helper for rrexpand yearly/N-year expansion local nstart nend { read _y _m _d; read y m d start_time; } <<-EOF $(date -ud @$dstart +"%Y %_m %_d" date -ud @$start +"%Y %_m %_d %T" ) EOF while :; do y=$(( rrfreq - ((_y - y - 1) % rrfreq + 1) + _y )) nstart="$(printf '%04i-%02i-%02i' "$y" "$m" "$d")" if isdate "$nstart" && [ "$(date -ud "$nstart" +%s)" -ge "$dstart" ]; then break fi >/dev/null _y="$((_y + rrfreq))" done nstart="$(date -ud "$nstart $start_time" +%s)" nend="$((end - start + nstart))" while [ "$nstart" -lt "$rrend" -a "$nstart" -lt "$dend" ]; do [ "$nstart" -ge "$start" ] \ && printf '%i %i %s %s\n' "$nstart" "$nend" "$evtitle" "$evlink" y="$((y + rrfreq))" nstart="$(printf '%04i-%02i-%02i' "$y" "$m" "$d")" nstart="$(date -ud "$nstart $start_time" +%s)" nend="$((nstart - start + end))" done } rrex_weekday() { # helper for rrexpand: Nth weekday of a month (e.g. 2nd tuesday, etc.) local nstart nend nth=$(( ( $(date -ud @$start +%_d) - 1) / 7)) nend=$(( 0 * 604800 - (dstart - end) % 604800 + dstart )) nstart=$(( start - end + nend)) while [ "$nstart" -lt "$rrend" -a "$nstart" -lt "$dend" ]; do [ "$nstart" -ge "$start" -a "$nstart" -ge "$dstart" ] \ && [ "$(( ( $(date -ud @$nstart +%_d) -1) / 7 ))" -eq "$nth" ] \ && printf '%i %i %s %s\n' "$nstart" "$nend" "$evtitle" "$evlink" nstart="$((nstart + 7 * 86400))" nend="$((nstart - start + end))" done } rrex_lastweekday() { # helper for rrexpand: Nth last weekday of a month (e.g. 2nd last tuesday, etc.) local nstart nend Y m d nth read Y m d <<-EOF $(date -ud @$start +"%Y %_m %_d") EOF nth=$(( ( $(numdays $Y $m) - d ) / 7)) nend=$(( 0 * 604800 - (dstart - end) % 604800 + dstart )) nstart=$(( start - end + nend)) while [ "$nstart" -lt "$rrend" -a "$nstart" -lt "$dend" ]; do read Y m d <<-EOF $(date -ud @$nstart +"%Y %_m %_d") EOF [ "$nstart" -ge "$start" -a "$nstart" -ge "$dstart" ] \ && [ "$(( ( $(numdays $Y $m) - d ) / 7 ))" -eq "$nth" ] \ && printf '%i %i %s %s\n' "$nstart" "$nend" "$evtitle" "$evlink" nstart="$((nstart + 7 * 86400))" nend="$((nstart - start + end))" done } events="$( for dir in "$@"; do page_glob "$dir" "$depth" done \ | sort -u \ | while read -r page; do pagedir="$(page_abs "$page")" if [ -f "$_DATA/pages/${pagedir}/#events" ] \ && acl_read "$pagedir" \ && has_tags "$pagedir" $tags \ && ! has_tag "$pagedir" $ntags then cat "$_DATA/pages/${pagedir}/#events" fi done )" cal_list() { # Print list view for upcoming events local lday='' events sdate=$(date -ud "${DY}-${DM}-${DD}" +%s) events="$( printf %s\\n "$events" \ | rrexpand "$sdate" "$((sdate + 42 * 86400))" \ | sort -n )" printf '' date -ud "@$start" +'
  • ' } cal_month() { local ws events calmonth local iday idow mname dcnt dow dcal start end title link n calmonth="$(GET calmonth || printf %i "$((DY * 12 + DM))")" DY="$(( (calmonth - 1) / 12 ))" DM="$(( (calmonth - 1) % 12 + 1 ))" read -r iday idow mname <<-EOF $(date -ud "${DY}-${DM}-01" +"%s %u %B") EOF dcnt=$((iday - idow * 86400 + ws * 86400)) dow=$ws dcal="$(date -ud @"$dcnt" +%d)" events="$( printf %s\\n "$events" \ | rrexpand "$dcnt" "$((dcnt + 42 * 86400))" \ | sort -n )" printf '' printf '' \ "./?calmonth=$((DY * 12 + DM -1))" "$mname" "./?calmonth=$((DY * 12 + DM + 1))" for n in 0 1 2 3 4 5 6; do date -ud @"$((dcnt + n * 86400))" +''; done printf '' while :; do [ $dow = $ws ] && printf '' printf '\n' [ $dow = $(( (ws + 6) % 7)) ] && printf '\n' dcnt=$(( dcnt + 86400 )) dow=$(( (dow + 1) % 7 )) [ $dcal -lt 28 ] \ && dcal=$((dcal + 1)) \ || dcal=$(date -ud @"$dcnt" +%d) [ $dcnt -gt $((iday + 28 * 86400)) -a $dcal -le 7 -a $dow = $ws ] \ && break done printf '
    <%s>
    %a
    ' "$dcal" evlist="$( printf %s "${events}${events:+${BR}}" \ | while read start end title link; do if [ "$((start / 86400))" -lt "$((dcnt / 86400))" -a "$end" -gt "$dcnt" ]; then printf '
  • %s
  • ' \ "$(UNSTRING "${link%%#*}" |URL)" \ "$(UNSTRING "${link#*#}" |URL)" \ "$(UNSTRING "$title" |HTML)" elif [ "$((start / 86400))" -eq "$((dcnt / 86400))" ]; then printf '
  • %s - %s
  • ' \ "$(date -ud @"$start" +%H:%M)" \ "$(UNSTRING "${link%%#*}" |URL)" \ "$(UNSTRING "${link#*#}" |URL)" \ "$(UNSTRING "$title" |HTML)" fi done )" [ "$evlist" ] && printf '
      %s
    ' "$evlist" printf '
    ' } # cal_list cal_month