106 lines
4.3 KiB
EmacsLisp
106 lines
4.3 KiB
EmacsLisp
(use-package s
|
|
:straight t)
|
|
|
|
(require 'url)
|
|
(require 'url-util)
|
|
|
|
(defconst org-movies--omdb-apikey ""
|
|
"API key for OMDb. Overwrite in custom.el")
|
|
|
|
(defun org-movies--omdb-fetch (url)
|
|
"Retrieve JSON data from OMDb using URL and return it as an alist.
|
|
Errors when the request fails or the API reports an error."
|
|
(let ((buffer (url-retrieve-synchronously url t t)))
|
|
(unless buffer
|
|
(error "Failed to contact OMDb"))
|
|
(with-current-buffer buffer
|
|
(unwind-protect
|
|
(progn
|
|
(goto-char (or (bound-and-true-p url-http-end-of-headers)
|
|
(point-min)))
|
|
(let* ((response (decode-coding-string
|
|
(buffer-substring (point) (point-max))
|
|
'utf-8))
|
|
(data (json-read-from-string response)))
|
|
(when (string= (alist-get "Response" data nil nil #'string=) "False")
|
|
(error (alist-get "Error" data nil nil #'string=)))
|
|
data))
|
|
(kill-buffer buffer)))))
|
|
|
|
(defun org-movies--extract-title-year ()
|
|
"Return cons of movie title and optional year from current headline."
|
|
(save-excursion
|
|
(condition-case nil
|
|
(progn
|
|
(org-back-to-heading t)
|
|
(let* ((raw (org-no-properties (org-get-heading t t t t)))
|
|
(trimmed (s-trim raw))
|
|
(parts (s-match (rx string-start
|
|
(group (+? any))
|
|
(? (seq " " "(" (group (= 4 digit)) ")"))
|
|
string-end)
|
|
trimmed)))
|
|
(cons (s-trim (if parts (nth 1 parts) trimmed))
|
|
(when parts (nth 2 parts)))))
|
|
(error (error "No headline available for movie lookup")))))
|
|
|
|
(define-minor-mode org-movies-mode
|
|
"Helper functions for movies.org"
|
|
:keymap (list
|
|
(cons (kbd "C-c C-i") #'org-movies-template)))
|
|
|
|
|
|
|
|
(defun org-movies-template ()
|
|
"Convert imdb url at point to a diary entry."
|
|
(interactive nil 'org-movies-mode)
|
|
(let* ((ctx (org-element-context))
|
|
(link (when (eq (car ctx) 'link)
|
|
(plist-get (cadr ctx) :raw-link)))
|
|
(direct-imdb (and link
|
|
(nth 1 (s-match
|
|
(rx "imdb.com/title/" (group "tt" (+ digit)))
|
|
link))))
|
|
(movie (if direct-imdb
|
|
(org-movies--omdb-fetch
|
|
(concat "http://omdbapi.com/?apikey=" org-movies--omdb-apikey
|
|
"&i=" direct-imdb))
|
|
(let* ((title-year (org-movies--extract-title-year))
|
|
(title-query (car title-year))
|
|
(year-query (cdr title-year))
|
|
(url (concat "http://omdbapi.com/?apikey=" org-movies--omdb-apikey
|
|
"&type=movie"
|
|
"&t=" (url-hexify-string title-query)
|
|
(if year-query
|
|
(concat "&y=" (url-hexify-string year-query))
|
|
""))))
|
|
(org-movies--omdb-fetch url))))
|
|
(imdb (or direct-imdb
|
|
(alist-get "imdbID" movie nil nil #'string=)
|
|
(error "Missing imdb identifier")))
|
|
(title (alist-get "Title" movie nil nil #'string=))
|
|
(runtime (alist-get "Runtime" movie nil nil #'string=))
|
|
(genre (alist-get "Genre" movie nil nil #'string=))
|
|
(director (alist-get "Director" movie nil nil #'string=))
|
|
(plot (alist-get "Plot" movie nil nil #'string=))
|
|
(poster (alist-get "Poster" movie nil nil #'string=))
|
|
(year (alist-get "Year" movie nil nil #'string=)))
|
|
|
|
(pcase (org-element-type (org-element-at-point))
|
|
('headline (ignore))
|
|
(_ (beginning-of-line)
|
|
(kill-line)
|
|
(org-insert-heading)))
|
|
|
|
(org-edit-headline (concat title " (" year ")"))
|
|
(org-todo "TODO")
|
|
(org-set-property "imdb" imdb)
|
|
(org-set-property "link" (concat "https://imdb.com/title/" imdb))
|
|
(org-set-property "runtime" runtime)
|
|
(org-set-property "genre" genre)
|
|
(org-set-property "director" director)
|
|
(org-set-property "poster" (concat "[[" poster "]]"))
|
|
(org-set-property "plot" plot)
|
|
))
|
|
|
|
(org-movies-mode 1) |