Compare commits
6 commits
d41e65e406
...
a1989a66eb
Author | SHA1 | Date | |
---|---|---|---|
a1989a66eb | |||
4350856f99 | |||
087165a993 | |||
cf761c40a5 | |||
8bd0ba25e4 | |||
0f663fabc6 |
1 changed files with 61 additions and 26 deletions
83
tekuti.el
83
tekuti.el
|
@ -32,7 +32,7 @@
|
||||||
;; #+TITLE: SOME TITLE
|
;; #+TITLE: SOME TITLE
|
||||||
;; #+DATE: <2021-06-03 Thu 22:45>
|
;; #+DATE: <2021-06-03 Thu 22:45>
|
||||||
;; #+TAGS: comma,separated
|
;; #+TAGS: comma,separated
|
||||||
;; #+COMMENT_STATUS: open
|
;; #+COMMENTS: on
|
||||||
;; #+COMMENTS_DATE:
|
;; #+COMMENTS_DATE:
|
||||||
;; #+STATUS: publish
|
;; #+STATUS: publish
|
||||||
|
|
||||||
|
@ -43,7 +43,11 @@
|
||||||
|
|
||||||
(require 'org)
|
(require 'org)
|
||||||
|
|
||||||
(defvar tekuti-host "http://127.0.0.1:8080")
|
(defvar tekuti-host "http://127.0.0.1:8080"
|
||||||
|
"The host where tekuti is running.
|
||||||
|
This should be the base URL of your blog. Where adding ‘/admin’
|
||||||
|
will get you into the admin area of your blog. This shouldn't end
|
||||||
|
with a ‘/’.")
|
||||||
|
|
||||||
(defun tekuti--format-date (&optional date)
|
(defun tekuti--format-date (&optional date)
|
||||||
"Format DATE into a date that tekuti understands."
|
"Format DATE into a date that tekuti understands."
|
||||||
|
@ -52,18 +56,8 @@
|
||||||
(date-to-time date))
|
(date-to-time date))
|
||||||
t))
|
t))
|
||||||
|
|
||||||
(defun tekuti-build-data-from-org ()
|
(defun tekuti--parse-data-keyword (pair)
|
||||||
"Parse the current org buffer to collect the necessary metadata."
|
"Ensure that both the key and value in PAIR match what tekuti needs."
|
||||||
(let ((defaults `(("TITLE")
|
|
||||||
("DATE" ,(tekuti--format-date))
|
|
||||||
("TAGS")
|
|
||||||
("STATUS")
|
|
||||||
("COMMENT_STATUS")
|
|
||||||
("COMMENTS-CLOSED-DATE")
|
|
||||||
("BODY")))
|
|
||||||
(data (append
|
|
||||||
(mapcar
|
|
||||||
(lambda (pair)
|
|
||||||
(pcase pair
|
(pcase pair
|
||||||
(`("DATE" ,date)
|
(`("DATE" ,date)
|
||||||
(list "DATE" (tekuti--format-date date)))
|
(list "DATE" (tekuti--format-date date)))
|
||||||
|
@ -71,29 +65,64 @@
|
||||||
(list "COMMENTS-CLOSED-DATE"
|
(list "COMMENTS-CLOSED-DATE"
|
||||||
(and (not (string-empty-p date))
|
(and (not (string-empty-p date))
|
||||||
(tekuti--format-date date))))
|
(tekuti--format-date date))))
|
||||||
|
(`("STATUS" ,status)
|
||||||
|
(let ((accepted-values '("publish" "draft" "private")))
|
||||||
|
(if (member status accepted-values)
|
||||||
|
pair
|
||||||
|
(error "Unknown post status: %s; Accepted values are: %s"
|
||||||
|
status accepted-values))))
|
||||||
|
(`("COMMENTS" ,status)
|
||||||
|
(if (string= status "on")
|
||||||
|
pair
|
||||||
|
(error "Unknown value for comments: %s; Can only be ‘on’ or absent"
|
||||||
|
status)))
|
||||||
(_ pair)))
|
(_ pair)))
|
||||||
(org-collect-keywords '("TITLE" "TAGS" "STATUS" "COMMENT_STATUS" "DATE" "COMMENTS_DATE")))
|
|
||||||
|
(defun tekuti-build-data-from-org ()
|
||||||
|
"Parse the current org buffer to collect the necessary metadata."
|
||||||
|
(let ((defaults `(("TITLE")
|
||||||
|
("DATE" ,(tekuti--format-date))
|
||||||
|
("TAGS")
|
||||||
|
("STATUS")
|
||||||
|
("COMMENTS")
|
||||||
|
("COMMENTS-CLOSED-DATE")
|
||||||
|
("BODY")))
|
||||||
|
(data (append
|
||||||
|
(mapcar
|
||||||
|
#'tekuti--parse-data-keyword
|
||||||
|
(org-collect-keywords '("TITLE" "TAGS" "STATUS" "COMMENTS" "DATE" "COMMENTS_DATE")))
|
||||||
(list
|
(list
|
||||||
(list "BODY"
|
(list "BODY"
|
||||||
(with-current-buffer (org-html-export-as-html nil nil nil t)
|
(with-current-buffer (org-html-export-as-html nil nil nil t)
|
||||||
(buffer-substring-no-properties (point-min) (point-max))))))))
|
(buffer-substring-no-properties (point-min) (point-max))))))))
|
||||||
|
(seq-remove
|
||||||
|
(lambda (pair) (and (string= "COMMENTS" (car pair))
|
||||||
|
(null (cdr pair))))
|
||||||
(mapcar (lambda (item)
|
(mapcar (lambda (item)
|
||||||
(let ((key (car item)))
|
(let ((key (car item)))
|
||||||
`(,key ,@(or (alist-get key data nil nil #'string=)
|
`(,key ,@(or (alist-get key data nil nil #'string=)
|
||||||
(cdr item)))))
|
(cdr item)))))
|
||||||
defaults)))
|
defaults))))
|
||||||
|
|
||||||
(defun tekuti-form-encode-pair (key value)
|
(defun tekuti-form-encode-pair (key value)
|
||||||
|
"Make sure KEY and VALUE are properly form-encoded."
|
||||||
(concat (url-hexify-string key) "=" (url-hexify-string value)))
|
(concat (url-hexify-string key) "=" (url-hexify-string value)))
|
||||||
|
|
||||||
(defun tekuti-form-encode-data (data)
|
(defun tekuti-form-encode-data (data)
|
||||||
|
"Convert DATA from an alist to a form-encoded string."
|
||||||
(mapconcat
|
(mapconcat
|
||||||
(lambda (pair)
|
(lambda (pair)
|
||||||
(tekuti-form-encode-pair (downcase (car pair)) (cadr pair)))
|
(tekuti-form-encode-pair (downcase (car pair)) (cadr pair)))
|
||||||
data
|
data
|
||||||
"&"))
|
"&"))
|
||||||
|
|
||||||
(defun tekuti--send-finished (status buffer args)
|
(defun tekuti--send-finished (status buffer args updatep)
|
||||||
|
"Callback for when the request to tekuti finishes.
|
||||||
|
STATUS is the full data structure sent on by ‘url-retrieve’.
|
||||||
|
BUFFER is the buffer that was published. ARGS is a list
|
||||||
|
containing the data that was collected from the buffer to make
|
||||||
|
the request. UPDATEP is a boolean indicating whether a post was
|
||||||
|
updated or created."
|
||||||
(pcase-exhaustive status
|
(pcase-exhaustive status
|
||||||
(`(:redirect ,url . ,_)
|
(`(:redirect ,url . ,_)
|
||||||
(save-excursion
|
(save-excursion
|
||||||
|
@ -101,7 +130,7 @@
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(search-forward "\n\n")
|
(search-forward "\n\n")
|
||||||
(backward-char)
|
(backward-char)
|
||||||
(let ((data (org-collect-keywords '("TITLE" "TAGS" "STATUS" "COMMENT_STATUS" "DATE" "COMMENTS_DATE"))))
|
(let ((data (org-collect-keywords '("TITLE" "TAGS" "STATUS" "COMMENTS" "DATE" "COMMENTS_DATE"))))
|
||||||
(mapc (lambda (item)
|
(mapc (lambda (item)
|
||||||
(let ((key (car item))
|
(let ((key (car item))
|
||||||
(value (cadr item)))
|
(value (cadr item)))
|
||||||
|
@ -117,28 +146,34 @@
|
||||||
(car (url-path-and-query
|
(car (url-path-and-query
|
||||||
(url-generic-parse-url url))))
|
(url-generic-parse-url url))))
|
||||||
"\n"))))
|
"\n"))))
|
||||||
(message "Created new post: %s" url))
|
(message "%s post: %s" (if updatep "Updated" "Created new") url))
|
||||||
(`(:error (error http ,code) . ,_)
|
(`(:error (error http ,code) . ,_)
|
||||||
(message "Failed to create post: %d" code))))
|
(message "Failed to %s post: %d" (if updatep "update" "create") code))))
|
||||||
|
|
||||||
(defun tekuti--get-update-url ()
|
(defun tekuti--get-update-url ()
|
||||||
|
"Try and get the value of the ‘UPDATE_URL’ property in the current buffer."
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(goto-char (point-min))
|
(goto-char (point-min))
|
||||||
(car (map-elt (org-collect-keywords '("UPDATE_URL")) "UPDATE_URL"))))
|
(car (map-elt (org-collect-keywords '("UPDATE_URL")) "UPDATE_URL"))))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun tekuti-send ()
|
(defun tekuti-send ()
|
||||||
|
"Export and send the current buffer to tekuti.
|
||||||
|
The current buffer should be an ‘org-mode’ buffer that you wish
|
||||||
|
to post to your tekuti blog."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let* ((data (tekuti-build-data-from-org))
|
(let* ((data (tekuti-build-data-from-org))
|
||||||
(url-request-method "POST")
|
(url-request-method "POST")
|
||||||
(url-request-extra-headers
|
(url-request-extra-headers
|
||||||
`(("Content-Type" . "application/x-www-form-urlencoded")))
|
`(("Content-Type" . "application/x-www-form-urlencoded")))
|
||||||
(url-request-data (tekuti-form-encode-data data)))
|
(url-request-data (tekuti-form-encode-data data))
|
||||||
(url-retrieve (format "%s%s" tekuti-host
|
(previous-update-url (tekuti--get-update-url))
|
||||||
(or (tekuti--get-update-url)
|
(updatep (not (null previous-update-url))))
|
||||||
|
(url-retrieve (format "%s%s" (string-trim-right tekuti-host "/")
|
||||||
|
(or previous-update-url
|
||||||
"/admin/new-post"))
|
"/admin/new-post"))
|
||||||
#'tekuti--send-finished
|
#'tekuti--send-finished
|
||||||
(list (current-buffer) data))))
|
(list (current-buffer) data updatep))))
|
||||||
|
|
||||||
(provide 'tekuti)
|
(provide 'tekuti)
|
||||||
;;; tekuti.el ends here
|
;;; tekuti.el ends here
|
||||||
|
|
Loading…
Reference in a new issue