[ブログ記事からの移行]
はてなブログAPIで、Emacsから投稿できるようにしてみた。
可能なら記事の編集とかもできるようにしたかったが、メニューみたいなbuffer (nとかpで行移動してEnterで詳細表示みたいな) の作り方が分からないので、投稿だけ。
誰か知ってたら教えて下さい。
使い方
evil-mode 前提のキーバインドだけど
,mbw
(M-x my-hatena-blog-write
) でブログを書き始めて、 ,mbp
(M-x my-hatena-blog-post
)でポスト。
コード
;; for (xml-escape-string)
(require 'xml)
;; see http://developer.hatena.ne.jp/ja/documents/blog/apis/atom
(setq my-hatena-id "your-hatena-id")
(setq my-hatena-blog-api-key "your-api-key")
(setq my-hatena-blog-id "your-hatenablog-domain")
(setq my-hatena-blog-file-path "~/Dropbox/blog.md")
(setq my-hatena-blog-backup-dir "~/Dropbox/blog-entries/")
(setq my-hatena-blog-xml-template "<?xml version='1.0' encoding='utf-8'?>
<entry xmlns='http://www.w3.org/2005/Atom'
xmlns:app='http://www.w3.org/2007/app'>
<title>%s</title>
<author><name>%s</name></author>
<content type='text/plain'>%s</content>
<updated>%s</updated>
<category term='%s' />
<app:control>
<app:draft>%s</app:draft>
</app:control>
</entry>")
(defun my-hatena-blog-build-xml ()
(interactive)
(let ((blog-title (read-string "Title: "
(save-excursion (beginning-of-buffer)
(search-forward-regexp "#* \\(.*\\)" nil t)
(match-string 1))))
(blog-category (read-string "Category: "))
(blog-is-draft (if (y-or-n-p "Send as draft? ") "yes" "no")))
(princ (format my-hatena-blog-xml-template
(xml-escape-string blog-title)
my-hatena-id
(xml-escape-string (buffer-string))
(format-time-string "%Y-%m-%dT%H:%M:%S")
(xml-escape-string blog-category)
blog-is-draft))))
(defun my-hatena-blog-post2 ()
(interactive)
(let* ((url-request-method "POST")
(url-request-extra-headers
`(("Content-Type" . "application/x-www-form-urlencoded")
("Authorization" . ,(concat "Basic " (base64-encode-string (concat my-hatena-id ":" my-hatena-blog-api-key))))))
(url-request-data
(encode-coding-string (my-hatena-blog-build-xml) 'utf-8))
(post-url (format "https://blog.hatena.ne.jp/%s/%s/atom/entry" my-hatena-id my-hatena-blog-id)))
(url-retrieve post-url (lambda (data)
(with-current-buffer (current-buffer)
(if (search-forward-regexp "HTTP/1.1 201 Created" nil t)
(message "Entry created.")
(progn
(message "failed!"))))))));
(defun my-hatena-blog-write ()
(interactive)
(find-file my-hatena-blog-file-path))
(defun my-hatena-blog-post ()
(interactive)
(my-hatena-blog-post2)
(write-file (concat my-hatena-blog-backup-dir (format-time-string "%Y-%m-%d-%H-%M-%S") ".md"))
(move-file-to-trash my-hatena-blog-file-path))
(evil-leader/set-key "mbw" 'my-hatena-blog-write)
(evil-leader/set-key-for-mode 'markdown-mode "mbp" 'my-hatena-blog-post)