2021-06-04 08:26:47 +02:00
|
|
|
|
;;; tekuti.el --- Tekuti interaction library -*- lexical-binding: t; -*-
|
|
|
|
|
|
|
|
|
|
;; Copyright (C) 2021 Tom Willemse
|
|
|
|
|
|
|
|
|
|
;; Author: Tom Willemse <chelys@data>
|
|
|
|
|
;; Keywords: comm
|
2021-06-25 06:19:25 +02:00
|
|
|
|
;; Package-Requires: (org)
|
2022-03-24 02:58:00 +01:00
|
|
|
|
;; Version: 0.1.0
|
2021-06-04 08:26:47 +02:00
|
|
|
|
|
|
|
|
|
;; This program is free software; you can redistribute it and/or modify
|
|
|
|
|
;; it under the terms of the GNU General Public License as published by
|
|
|
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
;; (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
;; This program is distributed in the hope that it will be useful,
|
|
|
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
;; GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
|
|
|
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
|
|
;; A simple module to help post things to your tekuti blog. You’ll want to
|
|
|
|
|
;; customize the ‘tekuti-host’ variable to point to your own blog. You should be
|
|
|
|
|
;; asked for your credentials, which should then be stored in ~/.authinfo.gpg.
|
|
|
|
|
|
|
|
|
|
;; Currently you should add these headers to your org document that you want to
|
|
|
|
|
;; send up:
|
|
|
|
|
|
|
|
|
|
;; #+TITLE: SOME TITLE
|
|
|
|
|
;; #+DATE: <2021-06-03 Thu 22:45>
|
|
|
|
|
;; #+TAGS: comma,separated
|
2023-04-12 09:42:49 +02:00
|
|
|
|
;; #+COMMENT_STATUS: open
|
2021-06-04 08:26:47 +02:00
|
|
|
|
;; #+COMMENTS_DATE:
|
|
|
|
|
;; #+STATUS: publish
|
|
|
|
|
|
|
|
|
|
;; The main entry point is ‘tekuti-send’. Call this from an org-mode buffer to
|
|
|
|
|
;; export the buffer to HTML and send it up to your blog.
|
|
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
2021-06-25 06:19:25 +02:00
|
|
|
|
(require 'org)
|
|
|
|
|
|
|
|
|
|
(defvar tekuti-host "http://127.0.0.1:8080")
|
|
|
|
|
|
2021-06-25 07:02:52 +02:00
|
|
|
|
(defun tekuti--format-date (&optional date)
|
2021-06-25 06:09:22 +02:00
|
|
|
|
"Format DATE into a date that tekuti understands."
|
|
|
|
|
(format-time-string "%a, %d %b %Y %H:%M:%S %Z"
|
2021-06-25 07:02:52 +02:00
|
|
|
|
(unless (null date)
|
2023-04-12 09:41:02 +02:00
|
|
|
|
(date-to-time date))
|
2021-06-25 06:09:22 +02:00
|
|
|
|
t))
|
|
|
|
|
|
2021-06-04 08:26:47 +02:00
|
|
|
|
(defun tekuti-build-data-from-org ()
|
2021-06-25 07:02:52 +02:00
|
|
|
|
"Parse the current org buffer to collect the necessary metadata."
|
|
|
|
|
(let ((defaults `(("TITLE")
|
|
|
|
|
("DATE" ,(tekuti--format-date))
|
|
|
|
|
("TAGS")
|
|
|
|
|
("STATUS")
|
2023-04-12 09:42:49 +02:00
|
|
|
|
("COMMENT_STATUS")
|
2021-06-25 07:02:52 +02:00
|
|
|
|
("COMMENTS-CLOSED-DATE")
|
|
|
|
|
("BODY")))
|
|
|
|
|
(data (append
|
|
|
|
|
(mapcar
|
|
|
|
|
(lambda (pair)
|
|
|
|
|
(pcase pair
|
|
|
|
|
(`("DATE" ,date)
|
|
|
|
|
(list "DATE" (tekuti--format-date date)))
|
|
|
|
|
(`("COMMENTS_DATE" ,date)
|
|
|
|
|
(list "COMMENTS-CLOSED-DATE"
|
|
|
|
|
(and (not (string-empty-p date))
|
|
|
|
|
(tekuti--format-date date))))
|
|
|
|
|
(_ pair)))
|
2023-04-12 09:42:49 +02:00
|
|
|
|
(org-collect-keywords '("TITLE" "TAGS" "STATUS" "COMMENT_STATUS" "DATE" "COMMENTS_DATE")))
|
2021-06-25 07:02:52 +02:00
|
|
|
|
(list
|
|
|
|
|
(list "BODY"
|
|
|
|
|
(with-current-buffer (org-html-export-as-html nil nil nil t)
|
|
|
|
|
(buffer-substring-no-properties (point-min) (point-max))))))))
|
|
|
|
|
(mapcar (lambda (item)
|
|
|
|
|
(let ((key (car item)))
|
|
|
|
|
`(,key ,@(or (alist-get key data nil nil #'string=)
|
|
|
|
|
(cdr item)))))
|
|
|
|
|
defaults)))
|
2021-06-04 08:26:47 +02:00
|
|
|
|
|
|
|
|
|
(defun tekuti-form-encode-pair (key value)
|
|
|
|
|
(concat (url-hexify-string key) "=" (url-hexify-string value)))
|
|
|
|
|
|
|
|
|
|
(defun tekuti-form-encode-data (data)
|
|
|
|
|
(mapconcat
|
|
|
|
|
(lambda (pair)
|
|
|
|
|
(tekuti-form-encode-pair (downcase (car pair)) (cadr pair)))
|
|
|
|
|
data
|
|
|
|
|
"&"))
|
|
|
|
|
|
2021-06-25 08:00:11 +02:00
|
|
|
|
(defun tekuti--send-finished (status buffer args)
|
|
|
|
|
(pcase-exhaustive status
|
|
|
|
|
(`(:redirect ,url)
|
|
|
|
|
(save-excursion
|
|
|
|
|
(with-current-buffer buffer
|
|
|
|
|
(goto-char (point-min))
|
|
|
|
|
(search-forward "\n\n")
|
|
|
|
|
(backward-char)
|
2023-04-12 09:42:49 +02:00
|
|
|
|
(let ((data (org-collect-keywords '("TITLE" "TAGS" "STATUS" "COMMENT_STATUS" "DATE" "COMMENTS_DATE"))))
|
2021-06-25 08:00:11 +02:00
|
|
|
|
(mapc (lambda (item)
|
|
|
|
|
(let ((key (car item))
|
|
|
|
|
(value (cadr item)))
|
|
|
|
|
(when (and (not (string= key "BODY"))
|
|
|
|
|
(null (alist-get key data nil nil #'string=))
|
|
|
|
|
(not (null value)))
|
|
|
|
|
(insert "#+" key ": " value "\n"))))
|
|
|
|
|
args))))
|
|
|
|
|
(message "Created new post: %s" url))
|
|
|
|
|
(`(:error (error http ,code))
|
|
|
|
|
(message "Failed to create post: %d" code))))
|
2021-06-25 07:02:52 +02:00
|
|
|
|
|
2021-06-04 08:26:47 +02:00
|
|
|
|
;;;###autoload
|
|
|
|
|
(defun tekuti-send ()
|
|
|
|
|
(interactive)
|
|
|
|
|
(let* ((data (tekuti-build-data-from-org))
|
|
|
|
|
(url-request-method "POST")
|
|
|
|
|
(url-request-extra-headers
|
|
|
|
|
`(("Content-Type" . "application/x-www-form-urlencoded")))
|
|
|
|
|
(url-request-data (tekuti-form-encode-data data)))
|
2021-06-25 08:00:11 +02:00
|
|
|
|
(url-retrieve (format "%s/admin/new-post" tekuti-host)
|
|
|
|
|
#'tekuti--send-finished
|
|
|
|
|
(list (current-buffer) data))))
|
2021-06-04 08:26:47 +02:00
|
|
|
|
|
|
|
|
|
(provide 'tekuti)
|
|
|
|
|
;;; tekuti.el ends here
|