diff options
Diffstat (limited to 'pim/rc/rsvp')
| -rwxr-xr-x | pim/rc/rsvp | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/pim/rc/rsvp b/pim/rc/rsvp new file mode 100755 index 0000000..0e21f04 --- /dev/null +++ b/pim/rc/rsvp @@ -0,0 +1,111 @@ +#!/bin/rc +# pim/rsvp -- answer an invitation. +# +# pim/rsvp accepted 'meet with ben' +# pim/rsvp declined /mnt/pim/calendars/work/events/date/2026/08/24/1000-API-WG +# +# Takes an occurrence path, as pim/agenda -p prints and cal9 plumbs, or a +# pattern to search for. The answer goes to the event's partstat, and +# what happens next is the backend's business: a caldav server with +# calendar-auto-schedule updates your copy and mails the organiser, and +# a published .ics refuses outright, which is the honest answer there. +rfork e + +mtpt=/mnt/pim +days=90 +only=() + +while(~ $1 -*){ + switch($1){ + case -m + mtpt=$2; shift + case -c + only=($only $2); shift + case -n + days=$2; shift + case * + echo 'usage: rsvp [-m mtpt] [-c cal] [-n days] accepted|declined|tentative path|pattern' >[1=2] + exit usage + } + shift +} +if(test $#* -lt 2){ + echo 'usage: rsvp [-m mtpt] [-c cal] [-n days] accepted|declined|tentative path|pattern' >[1=2] + exit usage +} + +want=`{echo $1 | tr a-z A-Z} +shift +switch($want){ +case ACCEPTED DECLINED TENTATIVE + ; +case * + echo 'pim/rsvp: want accepted, declined or tentative' >[1=2] + exit usage +} +pat=$"* + +# an occurrence path names one outright; anything else is a search +occ=() +if(test -f $"pat) + occ=$"pat +if(~ $#occ 0){ + hits=`{pim/show -m $mtpt -n $days $only -a $"pat >[2]/dev/null | sed -n 's/^at *//p'} + if(~ $#hits 0){ + echo 'pim/rsvp: nothing matching '^$"pat >[1=2] + exit notfound + } + # A recurring event matches once per occurrence, and the answer + # applies to the series, so count distinct events rather than hits. + evs=() + for(h in $hits){ + hd=`{basename -d $h} + he=`{sed -n 's/^event: //p' $h} + if(! ~ $#he 0) + evs=($evs `{cleanname $hd/$"he}) + } + evs=`{echo $evs | tr ' ' '\n' | sort -u} + if(! ~ $#evs 1){ + echo 'pim/rsvp: '^$#evs^' events match; be more specific:' >[1=2] + for(x in $evs) + echo ' '^$x >[1=2] + exit ambiguous + } + occ=$hits(1) +} + +# the occurrence points at its event; 9P has no symlinks, so it is a path +d=`{basename -d $"occ} +ev=`{sed -n 's/^event: //p' $"occ} +if(~ $#ev 0){ + echo 'pim/rsvp: '^$"occ^' has no event: line' >[1=2] + exit noevent +} +e=`{cleanname $d/$"ev} + +if(! test -f $e/partstat){ + echo 'pim/rsvp: '^$"e^' has no partstat' >[1=2] + exit nopartstat +} + +# Say why before the write fails. A published .ics has nowhere to put a +# reply and no invitation to reply to, and "permission denied" does not +# explain that. +c=`{echo $"e | sed 's|(/.*/calendars/[^/]+)/.*|\1|'} +caps=`{sed -n 's/^caps //p' $"c/ctl >[2]/dev/null} +# ~ takes its first argument as the subject, so `~ $caps rsvp` asks +# whether "read" is "rsvp". Walk the list instead. +can=() +for(x in $caps) + if(~ $x rsvp) + can=1 +if(! ~ $#caps 0) + if(~ $#can 0){ + echo 'pim/rsvp: '^`{basename $"c}^' is '^$"caps^', it cannot answer invitations' >[1=2] + exit readonly + } + +echo $want >$e/partstat +sum=`{sed -n 's/^summary: //p' $"occ} +echo $"sum^': '^$want +exit 0 |
