aboutsummaryrefslogtreecommitdiff
path: root/sx-interaction.el
diff options
context:
space:
mode:
Diffstat (limited to 'sx-interaction.el')
-rw-r--r--sx-interaction.el80
1 files changed, 80 insertions, 0 deletions
diff --git a/sx-interaction.el b/sx-interaction.el
index a9203bd..404fb56 100644
--- a/sx-interaction.el
+++ b/sx-interaction.el
@@ -106,5 +106,85 @@ changes."
;; Display the changes in `data'.
(sx--maybe-update-display))))
+
+;;; Commenting
+(defun sx-comment (data text)
+ "Post a comment on DATA given by TEXT.
+DATA can be a question, an answer, or a comment. Interactively,
+it is guessed from context at point.
+If DATA is a comment, the comment is posted as a reply to it.
+
+TEXT is a string. Interactively, it is read from the minibufer."
+ (interactive
+ (list (sx--data-here) 'query))
+ (sx-assoc-let data
+ ;; Get the comment text
+ (when (eq text 'query)
+ (setq text (read-string
+ "Comment text: "
+ (when .comment_id
+ (sx--user-@name .owner))))
+ (while (< (string-width text) 15)
+ (setq text (read-string "Comment text (at least 15 characters): " text))))
+ ;; If non-interactive, `text' could be anything.
+ (unless (stringp text)
+ (error "Comment body must be a string"))
+ ;; And post
+ (let ((result
+ (sx-method-call 'posts
+ :id (or .post_id .answer_id .question_id)
+ :submethod "comments/add"
+ :auth 'warn
+ :url-method "POST"
+ :filter sx-browse-filter
+ :site .site
+ :keywords `((body ,text)))))
+ ;; The api returns the new DATA.
+ (when (> (length result) 0)
+ (sx--add-comment-to-object
+ (elt result 0)
+ (if .post_id
+ (sx--get-post .post_type .site .post_id)
+ data))
+ ;; Display the changes in `data'.
+ (sx--maybe-update-display)))))
+
+(defun sx--get-post (type site id)
+ "Find in the database a post identified by TYPE, SITE and ID.
+TYPE is `question' or `answer'.
+SITE is a string.
+ID is an integer."
+ (let ((db (cons sx-question-mode--data
+ sx-question-list--dataset)))
+ (setq db
+ (cond
+ ((string= type "question") db)
+ ((string= type "answer")
+ (apply #'cl-map 'list #'identity
+ (mapcar (lambda (x) (cdr (assoc 'answers x))) db)))))
+ (car (cl-member-if
+ (lambda (x) (sx-assoc-let x
+ (and (equal (or .answer_id .question_id) id)
+ (equal .site site))))
+ db))))
+
+(defun sx--add-comment-to-object (comment object)
+ "Add COMMENT to OBJECT's `comments' property.
+OBJECT can be a question or an answer."
+ (let ((com-cell (assoc 'comments object))
+ (count-cell (assoc 'comment_count object)))
+ (if com-cell
+ (progn
+ (setcdr
+ com-cell
+ (apply #'vector
+ (append
+ (cl-map 'list #'identity
+ (cdr com-cell))
+ (list comment)))))
+ ;; No previous comments, add it manually.
+ (setcdr object (cons (car object) (cdr object)))
+ (setcar object `(comments . [,comment])))))
+
(provide 'sx-interaction)
;;; sx-interaction.el ends here