I often want to copy the toot URL after posting a
new toot about a blog post so that I can update
the blog post with it. Since I post from Emacs
using mastodon.el, I can probably figure out how
to get the URL after tooting. A quick-and-dirty
way is to retrieve the latest status.
(defvar my-mastodon-toot-posted-hook nil "Called with the item.")
(defun my-mastodon-copy-toot-url (toot)
(interactive (list (my-mastodon-latest-toot)))
(kill-new (alist-get 'url toot)))
(add-hook 'my-mastodon-toot-posted-hook #'my-mastodon-copy-toot-url)
(defun my-mastodon-latest-toot ()
(interactive)
(require 'mastodon-http)
(let* ((json-array-type 'list)
(json-object-type 'alist))
(car
(mastodon-http--get-json
(mastodon-http--api
(format "accounts/%s/statuses?count=1&limit=1&exclude_reblogs=t"
(mastodon-auth--get-account-id)))
nil :silent))))
(with-eval-after-load 'mastodon-toot
(when (functionp 'mastodon-toot-send)
(advice-add
#'mastodon-toot-send
:after
(lambda (&rest _)
(run-hook-with-args 'my-mastodon-toot-posted-hook (my-mastodon-latest-toot)))))
(when (functionp 'mastodon-toot--send)
(advice-add
#'mastodon-toot--send
:after
(lambda (&rest _)
(run-hook-with-args 'my-mastodon-toot-posted-hook (my-mastodon-latest-toot))))))
I considered overriding the keybinding in
mastodon-toot-mode-map
, but I figured using
advice would mean I can copy things even after
automated toots.
A more elegant way to do this might be to modify
mastodon-toot-send
to run-hook-with-args
a
variable with the response
as an argument, but
this will do for now.
I used a hook in my advice so that I can change
the behaviour from other functions. For example, I
have some code to compose a toot with a link to
the current post. After I send a toot, I want to
check if the toot contains the current entry's
permalink. If it has and I don't have a Mastodon
toot field yet, maybe I can automatically set that
property, assuming I end up back in the Org Mode
file I started it from.
(defun my-mastodon-org-maybe-set-toot-url (toot)
(when (derived-mode-p 'org-mode)
(let ((permalink (org-entry-get-with-inheritance "EXPORT_ELEVENTY_PERMALINK")))
(when (and permalink
(string-match (regexp-quote permalink) (alist-get 'content toot))
(not (org-entry-get-with-inheritance "MASTODON")))
(save-excursion
(goto-char (org-find-property "EXPORT_ELEVENTY_PERMALINK"
permalink))
(org-entry-put
(point)
"EXPORT_MASTODON"
(alist-get 'url toot))
(message "Toot URL set: %s, republish if needed" toot))))))
(add-hook 'my-mastodon-toot-posted-hook #'my-mastodon-org-maybe-set-toot-url)
If I combine that with a development copy of my
blog that ignores most of my posts so it compiles
faster and a function that copies just the current
post's files over, I can quickly make a post
available at its permalink (which means the link
in the toot will work) before I recompile the rest
of the blog, which takes a number of minutes.
(defun my-org-11ty-copy-just-this-post ()
(interactive)
(when (derived-mode-p 'org-mode)
(let ((file (org-entry-get-with-inheritance "EXPORT_ELEVENTY_FILE_NAME"))
(path my-11ty-base-dir))
(call-process "chmod" nil nil nil "ugo+rwX" "-R" (expand-file-name file (expand-file-name "_local" path)))
(call-process "rsync" nil (get-buffer-create "*rsync*") nil "-avze" "ssh"
(expand-file-name file (expand-file-name "_local" path))
(concat "web:/var/www/static-blog/" file))
(browse-url (concat (replace-regexp-in-string "/$" "" my-blog-base-url)
(org-entry-get-with-inheritance "EXPORT_ELEVENTY_PERMALINK"))))))
The proper blog updates (index page, RSS/ATOM
feeds, category pages, prev/next links, etc.) can happen when the
publishing is finished.
So my draft workflow is:
- Write the post.
- Export it to the local
NODE_ENV=dev npx eleventy --serve --quiet
with ox-11ty.
- Check that it looks okay locally.
- Use
my-org-11ty-copy-just-this-post
and confirm that it looks fine.
- Compose a toot with my-mastodon-11ty-toot-post
and check if sending it updates the Mastodon
toot.
- Re-export the post.
- Run my blog publishing process.
NODE_ENV=production npx eleventy --quiet
and then rsync.
Let's see if this works…