aboutsummaryrefslogtreecommitdiff
path: root/emacs/.emacs.d/lisp/my/my-openlibrary.el
diff options
context:
space:
mode:
authorYuchen Pei <id@ypei.org>2023-06-17 17:20:29 +1000
committerYuchen Pei <id@ypei.org>2023-06-17 17:20:29 +1000
commit093ffa5fbf7143f4668bb0a3dc9659a5cc836e12 (patch)
tree1ed4e14b2a43b8e338f4ad6a04d969b99b9239be /emacs/.emacs.d/lisp/my/my-openlibrary.el
parentabc686827ae38ee715d9eed1c5c29161c74127e6 (diff)
Moving things one level deeper
To ease gnu stow usage. Now we can do stow -t ~ emacs
Diffstat (limited to 'emacs/.emacs.d/lisp/my/my-openlibrary.el')
-rw-r--r--emacs/.emacs.d/lisp/my/my-openlibrary.el147
1 files changed, 147 insertions, 0 deletions
diff --git a/emacs/.emacs.d/lisp/my/my-openlibrary.el b/emacs/.emacs.d/lisp/my/my-openlibrary.el
new file mode 100644
index 0000000..559ecba
--- /dev/null
+++ b/emacs/.emacs.d/lisp/my/my-openlibrary.el
@@ -0,0 +1,147 @@
+;;; my-openlibrary.el -- openlibrary client -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023 Free Software Foundation.
+
+;; Author: Yuchen Pei <id@ypei.org>
+;; Package-Requires: ((emacs "28.2"))
+
+;; This file is part of dotfiles.
+
+;; dotfiles is free software: you can redistribute it and/or modify it under
+;; the terms of the GNU Affero General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; dotfiles 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 Affero General
+;; Public License for more details.
+
+;; You should have received a copy of the GNU Affero General Public
+;; License along with dotfiles. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; openlibrary client.
+
+;;; Code:
+
+
+;;; an openlibrary client
+(require 'generic-search)
+(require 'my-net)
+
+(defvar my-openlibrary-host "https://openlibrary.org")
+(defun my-openlibrary-api-book-by-olid (olid)
+ (my-url-fetch-json
+ (format "%s/api/books?bibkeys=OLID:%s&format=json&jscmd=data"
+ my-openlibrary-host olid)))
+
+(defun my-openlibrary-html-book-by-url (url)
+ (list
+ (cons 'description
+ (string-trim
+ (dom-texts
+ (dom-by-class
+ (my-url-fetch-dom url)
+ "book-description-content restricted-view"))))))
+
+(defun my-grok-openlibrary (url)
+ "grok openlibrary.
+title, subtitle, description, subjects, authors (by_statement?), classification, publisher, publish_places, publish_date, subjects, cover"
+ (when (string-match
+ (concat my-openlibrary-host "/books/\\([^/]+\\)") url)
+ (my-grok-openlibrary-make-info
+ (append
+ (my-openlibrary-api-book-by-olid (match-string 1 url))
+ (my-openlibrary-html-book-by-url url)))))
+
+(defun my-grok-openlibrary-make-info (info)
+ (list
+ (cons "Title" (alist-get 'title info))
+ (cons "Subtitle" (alist-get 'subtitle info))
+ (cons "Authors" (string-join
+ (mapcar (lambda (author) (alist-get 'name author))
+ (alist-get 'authors info))
+ ", "))
+ (cons "Pages"
+ (when (alist-get 'number_of_pages info)
+ (number-to-string (alist-get 'number_of_pages info))))
+ (cons "OpenLibrary-link" (alist-get 'url info))
+ (cons "OpenLibrary-ID" (string-join (alist-get 'openlibrary info) ","))
+ (cons "ISBN" (string-join
+ (vconcat
+ (alist-get 'isbn_13
+ (alist-get 'identifiers info))
+ (alist-get 'isbn_10
+ (alist-get 'identifiers info)))
+ ", "))
+ (cons "Dewey-Decimal" (alist-get 'dewey_decimal_class info))
+ (cons "Subject" (string-join
+ (seq-take
+ (remove-duplicates
+ (mapcar (lambda (subject) (alist-get 'name subject))
+ (alist-get 'subjects info))
+ :test 'string=)
+ 20)
+ ", "))
+ (cons "Cover" (alist-get 'large (alist-get 'cover info)))
+ (cons "Published" (alist-get 'publish_date info))
+ (cons "Description" (alist-get 'description info))))
+
+(defun my-openlibrary-api-book-by-isbn (isbn)
+ (my-url-fetch-json
+ (format
+ "%s/api/books?bibkeys=ISBN:%s&format=json&jscmd=data"
+ my-openlibrary-host isbn)))
+
+(defun my-grok-openlibrary-isbn (isbn)
+ (unless isbn (error "isbn not supplied"))
+ (let* ((info-json (alist-get (intern (format "ISBN:%s" isbn))
+ (my-openlibrary-api-book-by-isbn isbn)))
+ (url (alist-get 'url info-json))
+ (info-html (my-openlibrary-html-book-by-url url)))
+ (my-grok-openlibrary-make-info
+ (append info-json info-html))))
+
+(defun my-openlibrary-api-search (query)
+ (my-url-fetch-json
+ (format "%s/search.json?q=%s" my-openlibrary-host query)))
+
+(defun my-openlibrary-format-result (info)
+ (format "%s - %s [%s] (%s)"
+ (string-join (alist-get 'author_name info) ", ")
+ (alist-get 'title info)
+ (string-join (alist-get 'isbn info) ",")
+ (alist-get 'publish_date info)))
+
+(defun my-openlibrary-action (info)
+ (interactive)
+ (my-org-create-node
+ (my-grok-openlibrary-isbn (elt (alist-get 'isbn info) 0))
+ t))
+
+(defun my-openlibrary-show-more-info ()
+ (interactive)
+ (pp (my-grok-openlibrary-isbn
+ (elt
+ (alist-get 'isbn (get-text-property (point) 'button-data))
+ 0))))
+
+(defvar my-openlibrary-button-keymap
+ (let ((kmap (make-sparse-keymap)))
+ (set-keymap-parent kmap button-map)
+ (define-key kmap "p" 'my-openlibrary-show-more-info)
+ kmap))
+
+(defun my-openlibrary-search (query)
+ (interactive "sQuery: ")
+ (generic-search-open
+ (alist-get 'docs (my-openlibrary-api-search query))
+ (format "openlibrary-query:%s" query)
+ `((formatter . my-openlibrary-format-result)
+ (default-action . my-openlibrary-action)
+ (keymap . ,my-openlibrary-button-keymap))))
+
+(provide 'my-openlibrary)
+;;; my-openlibrary.el ends here