Skip to content

Instantly share code, notes, and snippets.

@TuringMachinegun
Created September 7, 2020 14:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TuringMachinegun/dde781e5f6667e373db5423f2517ae93 to your computer and use it in GitHub Desktop.
Save TuringMachinegun/dde781e5f6667e373db5423f2517ae93 to your computer and use it in GitHub Desktop.
Post markdown with images to micro.blog in emacs
(require 'request)
(setq mb-emacs-app-token "123456789") ;; create this in account -> app tokens -> edit apps
(setq mb-micropub-endpoint "https://micro.blog/micropub")
(setq mb-destination-address "https://your.micro.blog")
(setq mb-image-upload-timeout 20) ;; seconds
(defun mb-get-media-endpoint ()
(cdr (assoc "media-endpoint"
(let (result)
(request
mb-micropub-endpoint
:params '(("q" . "config"))
:type "GET"
:sync t
:timeout: 10
:parser 'json-read
:headers `(("Content-Type" . "application/json")
("Authorization".,(format "Bearer %s" mb-emacs-app-token)))
:complete (cl-function
(lambda (&key data &allow-other-keys)
(setq result data))))
(if result
result
(error "Can't get media endpoint")))
#'string=)))
(defun mb-upload-image (img-path media-endpoint)
"Post inline images."
(cdr (assoc "url"
(let ((result))
(request
(concat media-endpoint
(if (boundp 'mb-destination-address) (concat "?mp-destination=" mb-destination-address)))
:type "POST"
:files `(("file" . ,img-path))
:headers `(("Content-Type" . "multipart/form-data")
("Authorization".,(format "Bearer %s" mb-emacs-app-token)))
:sync t
:timeout mb-image-upload-timeout
:parser 'json-read
:success (cl-function
(lambda (&key data &allow-other-keys)
(setq result data))))
(if result
result
(error "Error in uploading.")))
#'string=)))
(defun mb-markdown-upload-images-substitute-links ()
"Upload images to micro.blog and substitute their local links with the upload locations."
(interactive)
(save-excursion
(save-restriction
(let ((media-endpoint (mb-get-media-endpoint)))
(widen)
(goto-char (point-min))
(while (re-search-forward markdown-regex-link-inline nil t)
(let ((start (match-beginning 0))
(imagep (match-beginning 1))
(end (match-end 0))
(file (match-string-no-properties 6)))
(when (and imagep
(not (zerop (length file))))
(when (file-exists-p file)
(let* ((abspath (if (file-name-absolute-p file)
file
(concat default-directory file)))
(img-upload-url (save-match-data (mb-upload-image abspath media-endpoint))))
(replace-match img-upload-url t t nil 6))))))))))
(defun mb-post-buffer ()
"Post current buffer to micro.blog (possibly as draft)."
(interactive)
(if (yes-or-no-p "Are you sure you want to post this?")
(save-restriction
(widen)
(let ((buffer-contents (buffer-substring-no-properties (point-min) (point-max)))
(mb-post-name (read-string "Enter post name (leave empty if none):"))
(mb-post-status `(post-status . [,(if (yes-or-no-p "Post as draft?") "draft" "published")])))
;; copy content of current buffer to new buffer,
;; then upload eventual linked images, substitute links with the upload locations, send buffer to microblog
(with-current-buffer (generate-new-buffer "post2mb")
(goto-char (point-min))
(insert buffer-contents)
(goto-char (point-min))
(mb-markdown-upload-images-substitute-links)
(request
(concat mb-micropub-endpoint
(if (boundp 'mb-destination-address) (concat "?mp-destination=" mb-destination-address)))
:type "POST"
:data (json-encode `((type . ["h-entry"])
(properties
(content . [,(buffer-substring-no-properties (point-min) (point-max))])
(name . [,mb-post-name]) ,mb-post-status)))
:headers `(("Content-Type" . "application/json")
("Authorization".,(format "Bearer %s" mb-emacs-app-token)))
:success (cl-function
(lambda (&key data &allow-other-keys)
(message "Success.")))))))))
@TuringMachinegun
Copy link
Author

Hi Thadeej, I'm also no Lisp programmer, so let's see if I'm of any help!

What about if instead of setting the token as a variable, you create a function which, when called, returns the token?
Something like this (didn't test it):

(defun get-mb-emacs-app-token ()
   "Return mb token from .authinfo.gpg"
  (plist-get (car (auth-source-search :host "micro.blog")) :secret)
)

Then the headers section in the requests just becomes

                  :headers  `(("Content-Type" . "application/json")
                              ("Authorization".,(format "Bearer %s" (get-mb-emacs-app-token))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment