Subject: bug#72831: [PATCH] gnus-icalendar: Allow comments in event replies

From: Eli Zaretskii <[email-masked]>
Date: Wed, 28 Aug 2024 14:02:42 +0300

> From: Ferdinand Pieper <[email-masked]>
> Date: Tue, 27 Aug 2024 11:58:32 +0200
> 
> Tags: patch
> 
> The iCalendar RFC allows comments in an event reply to e.g. indicate a reason for declining. This patch implements sending an additional comment if the usual functions `gnus-icalendar-reply-[accept,decline,tentative]` (bound to `i a`, `i d`, `i t`) are called with a prefix argument.
> 
> Please let me know any feedback regarding the patch and commit message formatting.
> 
> Notably this only implements the comment functionality for the functions mentioned above and does not include the buttons defined in `gnus-icalendar-event:inline-reply-buttons`, as I am not sure how the `read-string` for the user's comment should be implemented for them.

Thanks.

Robert, Andrew, and Alexandre: would you please review the proposed
changes below and comment?

> >From 8ff07723b407d56de72ddfea98b8931951bb7ad8 Mon Sep 17 00:00:00 2001
> From: fpi <[email-masked]>
> Date: Mon, 19 Aug 2024 17:18:11 +0200
> Subject: [PATCH] Allow comments to organizer in ical event replies
> 
> * lisp/gnus/gnus-icalendar.el
> (gnus-icalendar-event--build-reply-event-body): Add optional COMMENT
> argument to be inserted into the reply.
> (gnus-icalendar-event-reply-from-buffer): Add COMMENT argument to be
> passed through to gnus-icalendar-event--build-reply-event-body
> (gnus-icalendar-reply-accept):
> (gnus-icalendar-reply-tentative):
> (gnus-icalendar-reply-decline): If interactively called with a prefix
> argument ask user for a COMMENT to add to the reply.
> ---
>  lisp/gnus/gnus-icalendar.el | 52 ++++++++++++++++++++++++++-----------
>  1 file changed, 37 insertions(+), 15 deletions(-)
> 
> diff --git a/lisp/gnus/gnus-icalendar.el b/lisp/gnus/gnus-icalendar.el
> index af7284b88e8..7a295fb9ed2 100644
> --- a/lisp/gnus/gnus-icalendar.el
> +++ b/lisp/gnus/gnus-icalendar.el
> @@ -309,7 +309,7 @@ gnus-icalendar-event-from-buffer
>  ;;; gnus-icalendar-event-reply
>  ;;;
>  
> -(defun gnus-icalendar-event--build-reply-event-body (ical-request status identities)
> +(defun gnus-icalendar-event--build-reply-event-body (ical-request status identities &optional comment)
>    (let ((summary-status (capitalize (symbol-name status)))
>          (attendee-status (upcase (symbol-name status)))
>          reply-event-lines)
> @@ -319,6 +319,10 @@ gnus-icalendar-event--build-reply-event-body
>  	  (if (string-match "^[^:]+:" line)
>  	      (replace-match (format "\\&%s: " summary-status) t nil line)
>  	    line))
> +         (update-comment
> +           (line)
> +           (if comment (format "COMMENT:%s" comment)
> +             line))
>  	 (update-dtstamp ()
>  			 (format-time-string "DTSTAMP:%Y%m%dT%H%M%SZ" nil t))
>  	 (attendee-matches-identity
> @@ -341,6 +345,7 @@ gnus-icalendar-event--build-reply-event-body
>  		    (cond
>  		     ((string= key "ATTENDEE") (update-attendee-status line))
>  		     ((string= key "SUMMARY") (update-summary line))
> +		     ((string= key "COMMENT") (update-comment line))
>  		     ((string= key "DTSTAMP") (update-dtstamp))
>  		     ((member key '("ORGANIZER" "DTSTART" "DTEND"
>  				    "LOCATION" "DURATION" "SEQUENCE"
> @@ -363,12 +368,17 @@ gnus-icalendar-event--build-reply-event-body
>                        attendee-status user-full-name user-mail-address)
>                reply-event-lines))
>  
> +      ;; add comment line if not existing
> +      (when (and comment (not (gnus-icalendar-find-if (lambda (x) (string-match "^COMMENT" x))
> +                                                      reply-event-lines)))
> +        (push (format "COMMENT:%s" comment) reply-event-lines))
> +
>        (mapconcat #'identity `("BEGIN:VEVENT"
>                                ,@(nreverse reply-event-lines)
>                                "END:VEVENT")
>                   "\n"))))
>  
> -(defun gnus-icalendar-event-reply-from-buffer (buf status identities)
> +(defun gnus-icalendar-event-reply-from-buffer (buf status identities &optional comment)
>    "Build a calendar event reply for request contained in BUF.
>  The reply will have STATUS (`accepted', `tentative' or  `declined').
>  The reply will be composed for attendees matching any entry
> @@ -396,7 +406,7 @@ gnus-icalendar-event-reply-from-buffer
>                                "PRODID:Gnus"
>                                "VERSION:2.0"
>                                zone
> -                              (gnus-icalendar-event--build-reply-event-body event status identities)
> +                              (gnus-icalendar-event--build-reply-event-body event status identities comment)
>                                "END:VCALENDAR")))
>  
>            (mapconcat #'identity (delq nil contents) "\n"))))))
> @@ -878,13 +888,13 @@ gnus-icalendar-send-buffer-by-mail
>        (insert "Subject: " subject)
>        (message-send-and-exit))))
>  
> -(defun gnus-icalendar-reply (data)
> +(defun gnus-icalendar-reply (data &optional comment)
>    (let* ((handle (car data))
>           (status (cadr data))
>           (event (caddr data))
>           (reply (gnus-icalendar-with-decoded-handle handle
>                    (gnus-icalendar-event-reply-from-buffer
> -                   (current-buffer) status (gnus-icalendar-identities))))
> +                   (current-buffer) status (gnus-icalendar-identities) comment)))
>           (organizer (gnus-icalendar-event:organizer event)))
>  
>      (when reply
> @@ -1009,25 +1019,37 @@ gnus-icalendar-save-event
>      (when data
>        (gnus-icalendar-save-part data))))
>  
> -(defun gnus-icalendar-reply-accept ()
> -  "Accept invitation in the current article."
> +(defun gnus-icalendar-reply-accept (&optional comment-p)
> +  "Accept invitation in the current article.
> +
> +With a prefix `\\[universal-argument]' prompt for a comment to include
> +in the reply."
>    (interactive nil gnus-article-mode gnus-summary-mode)
>    (with-current-buffer gnus-article-buffer
> -    (gnus-icalendar-reply (list gnus-icalendar-handle 'accepted gnus-icalendar-event))
> +    (gnus-icalendar-reply (list gnus-icalendar-handle 'accepted gnus-icalendar-event)
> +                          (when comment-p (read-string "Comment: ")))
>      (setq-local gnus-icalendar-reply-status 'accepted)))
>  
> -(defun gnus-icalendar-reply-tentative ()
> -  "Send tentative response to invitation in the current article."
> +(defun gnus-icalendar-reply-tentative (&optional comment-p)
> +  "Send tentative response to invitation in the current article.
> +
> +With a prefix `\\[universal-argument]' prompt for a comment to include
> +in the reply."
>    (interactive nil gnus-article-mode gnus-summary-mode)
>    (with-current-buffer gnus-article-buffer
> -    (gnus-icalendar-reply (list gnus-icalendar-handle 'tentative gnus-icalendar-event))
> +    (gnus-icalendar-reply (list gnus-icalendar-handle 'tentative gnus-icalendar-event)
> +                          (when comment-p (read-string "Comment: ")))
>      (setq-local gnus-icalendar-reply-status 'tentative)))
>  
> -(defun gnus-icalendar-reply-decline ()
> -  "Decline invitation in the current article."
> -  (interactive nil gnus-article-mode gnus-summary-mode)
> +(defun gnus-icalendar-reply-decline (&optional comment-p)
> +  "Decline invitation in the current article.
> +
> +With a prefix `\\[universal-argument]' prompt for a comment to include
> +in the reply."
> +  (interactive "P" gnus-article-mode gnus-summary-mode)
>    (with-current-buffer gnus-article-buffer
> -    (gnus-icalendar-reply (list gnus-icalendar-handle 'declined gnus-icalendar-event))
> +    (gnus-icalendar-reply (list gnus-icalendar-handle 'declined gnus-icalendar-event)
> +                          (when comment-p (read-string "Comment: ")))
>      (setq-local gnus-icalendar-reply-status 'declined)))
>  
>  (defun gnus-icalendar-event-export ()
> -- 
> 2.30.2
>