branch: elpa/mastodon commit 6328cd8a2d9a8970515217437b49b2b597d7760a Author: Rahguzar <rahgu...@mailbox.org> Commit: Rahguzar <rahgu...@mailbox.org>
Use url.el for posting attachments The removes the dependency on request. --- lisp/mastodon-http.el | 128 +++++++++++++++++++++++++++----------------------- lisp/mastodon.el | 2 +- 2 files changed, 70 insertions(+), 60 deletions(-) diff --git a/lisp/mastodon-http.el b/lisp/mastodon-http.el index 2f150ff01c..e98af497bc 100644 --- a/lisp/mastodon-http.el +++ b/lisp/mastodon-http.el @@ -31,7 +31,6 @@ ;;; Code: (require 'json) -(require 'request) ; for attachments upload (require 'url) (require 'url-http) (require 'shr) @@ -42,6 +41,7 @@ (autoload 'mastodon-auth--access-token "mastodon-auth") (autoload 'mastodon-toot--update-status-fields "mastodon-toot") +(autoload 'url-insert "url-handlers") (defvar mastodon-http--api-version "v1") @@ -347,73 +347,83 @@ PARAMS is an alist of any extra parameters to send with the request." Then run function CALLBACK with arguements CBARGS. Authorization header is included by default unless UNAUTHENTICED-P is non-nil." (mastodon-http--authorized-request "POST" - (let (;(request-timeout 5) ; this is from request.el no url.el! - (url-request-data (when params + (let ((url-request-data (when params (mastodon-http--build-params-string params)))) (with-temp-buffer (url-retrieve url callback cbargs))))) -;; TODO: test for curl first? +(defun mastodon-http--post-callback (status file caption buffer) + "Callback function called after posting FILE as an attachment with CAPTION. +The toot is being composed in BUFFER. See `url-retrieve' for STATUS." + (unwind-protect + (if-let* ((error-thrown (plist-get status :error))) + (cond + ((= (car (last error-thrown)) 401) + (message "Got error: %S Unauthorized: The access token is invalid" + error-thrown)) + ((= (car (last error-thrown)) 422) + (message "Got error: %S Unprocessable entity: file or file type is unsupported or invalid" + error-thrown)) + (t + (message "Got error: %S Shit went south" + error-thrown))) + (let* ((buf (current-buffer)) + (data (with-temp-buffer + (url-insert buf) + (goto-char (point-min)) + (json-read)))) + (when data + (with-current-buffer buffer + (let ((id (alist-get 'id data))) + ;; update ids: + (if (not mastodon-toot--media-attachment-ids) + ;; add first id: + (push id mastodon-toot--media-attachment-ids) + ;; add new id to end of list to preserve order: + (push id (cdr + (last mastodon-toot--media-attachment-ids)))) + ;; pleroma, PUT the description: + ;; this is how the mangane akkoma web client does it + ;; and it seems easier than the other options! + (when (and caption + (not (string= caption (alist-get 'description data)))) + (let ((url (mastodon-http--api (format "media/%s" id)))) + ;; (message "PUTting image description") + (mastodon-http--put url `(("description" . ,caption))))) + (message "Uploading %s... (done)" file) + (mastodon-toot--update-status-fields)))))) + (kill-buffer (current-buffer)))) + +(defun mastodon-http--post-prep-file (filename) + "Return the request data to upload FILENAME." + (with-temp-buffer + (set-buffer-multibyte nil) + (insert-file-contents-literally filename) + (let ((boundary (buffer-hash))) + (goto-char (point-min)) + (insert "--" boundary "\r\n" + (format "Content-Disposition: form-data; name=\"file\"; filename=\"%s\"\r\n\r\n" + (file-name-nondirectory filename))) + (goto-char (point-max)) + (insert "\r\n" "--" boundary "--" "\r\n") + `(,boundary . ,(buffer-substring-no-properties (point-min) (point-max)))))) + (defun mastodon-http--post-media-attachment (url filename caption) "Make POST request to upload FILENAME with CAPTION to the server's media URL. The upload is asynchronous. On succeeding, `mastodon-toot--media-attachment-ids' is set to the id(s) of the item uploaded, and `mastodon-toot--update-status-fields' is run." - (let* ((file (file-name-nondirectory filename)) - (request-backend 'curl) - (desc `(("description" . ,caption))) - (cb (cl-function - (lambda (&key data &allow-other-keys) - (when data - (let* ((id (alist-get 'id data))) - ;; update ids: - (if (not mastodon-toot--media-attachment-ids) - ;; add first id: - (push id mastodon-toot--media-attachment-ids) - ;; add new id to end of list to preserve order: - (push id (cdr - (last mastodon-toot--media-attachment-ids)))) - ;; pleroma, PUT the description: - ;; this is how the mangane akkoma web client does it - ;; and it seems easier than the other options! - (when (and caption - (not (string= caption (alist-get 'description data)))) - (let ((url (mastodon-http--api (format "media/%s" id)))) - ;; (message "PUTting image description") - (mastodon-http--put url desc))) - (message "Uploading %s... (done)" file) - (mastodon-toot--update-status-fields))))))) - (request - url - :type "POST" - :params desc - :files `(("file" . (,file :file ,filename - :mime-type "multipart/form-data"))) - :parser 'json-read - :headers `(("Authorization" . ,(concat "Bearer " - (mastodon-auth--access-token)))) - :sync nil - :success (apply-partially cb) - :error (cl-function - (lambda (&key error-thrown &allow-other-keys) - (cond - ;; handle curl errors first (eg 26, can't read file/path) - ;; because the '=' test below fails for them - ;; they have the form (error . error message 24) - ((not (proper-list-p error-thrown)) ; not dotted list - (message "Got error: %s. Shit went south." (cdr error-thrown))) - ;; handle mastodon api errors - ;; they have the form (error http 401) - ((= (car (last error-thrown)) 401) - (message "Got error: %s Unauthorized: The access token is invalid" - error-thrown)) - ((= (car (last error-thrown)) 422) - (message "Got error: %s Unprocessable entity: file or file\ - type is unsupported or invalid" - error-thrown)) - (t - (message "Got error: %s Shit went south" - error-thrown)))))))) + (let* ((data (mastodon-http--post-prep-file filename)) + (url-request-method "POST") + (url-request-extra-headers + `(("Authorization" . ,(string-to-unibyte + (concat "Bearer " (mastodon-auth--access-token)))) + ("Content-Type" . ,(format "multipart/form-data; boundary=%s" + (car data))))) + (url-request-data (cdr data))) + (url-retrieve (format "%s?description=%s" url (url-hexify-string caption)) + #'mastodon-http--post-callback + `(,filename ,caption ,(current-buffer))))) (provide 'mastodon-http) ;;; mastodon-http.el ends here diff --git a/lisp/mastodon.el b/lisp/mastodon.el index daf6f28dba..235791ee72 100644 --- a/lisp/mastodon.el +++ b/lisp/mastodon.el @@ -7,7 +7,7 @@ ;; Marty Hiatt <mouse...@disroot.org> ;; Maintainer: Marty Hiatt <mouse...@disroot.org> ;; Version: 1.1.12 -;; Package-Requires: ((emacs "28.1") (request "0.3.0") (persist "0.4") (tp "0.7")) +;; Package-Requires: ((emacs "28.1") (persist "0.4") (tp "0.7")) ;; Homepage: https://codeberg.org/martianh/mastodon.el ;; This file is not part of GNU Emacs.