;;; iarc.el -- internet archive client -*- lexical-binding: t -*- ;; Copyright (C) 2025 Free Software Foundation, Inc. ;; Author: Yuchen Pei ;; Package-Requires: ((emacs "30.1")) ;; This file is part of dotted. ;; dotted 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. ;; dotted 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 dotted. If not, see . ;;; Commentary: ;; internet archive client. ;;; Code: (require 'infobox) (defvar-keymap iarc-mode-map :parent tabulated-list-mode-map "F" #'iarc-toggle-follow-mode "i" #'iarc-infobox "n" #'iarc-next-line "p" #'iarc-previous-line "RET" #'iarc-item-at-point ) (define-derived-mode iarc-mode tabulated-list-mode "IArc" (hl-line-mode 1) (setq tabulated-list-format [("★ " 3 iarc-compare-favourites :right-align t) ("Title" 60 t)]) (setq tabulated-list-padding 2) (tabulated-list-init-header) (setq revert-buffer-function #'iarc-list-refresh)) (defvar iarc-search-dataset nil) (defvar iarc-follow-mode nil "Whether follow mode is on.") (defun iarc-toggle-follow-mode () (interactive) (setq iarc-follow-mode (not iarc-follow-mode))) (defun iarc-previous-line () (interactive) (previous-line) (when iarc-follow-mode (iarc-infobox))) (defun iarc-next-line () (interactive) (next-line) (when iarc-follow-mode (iarc-infobox))) (defun iarc-compare-favourites (x y) (> (let-alist (car x) (or .fields.num_favorites 0)) (let-alist (car y) (or .fields.num_favorites 0)))) (defun iarc-list-print-entry (info) (let-alist (alist-get 'fields info) (list info (vector (format "%d" (or .num_favorites 0)) .title)))) (defun iarc-list-refresh (&rest _) (interactive) (setq tabulated-list-entries (seq-map 'iarc-list-print-entry iarc-search-dataset)) (tabulated-list-print)) (defun iarc () (let ((buf (get-buffer-create "*IArc*"))) (with-current-buffer buf (iarc-mode) (iarc-list-refresh)) (pop-to-buffer-same-window buf))) (defvar iarc-host "https://archive.org") (defun iarc-api-search (query) (my-url-fetch-json (format "%s/services/search/beta/page_production/?user_query=title:(%s)&hits_per_page=100&page=1&aggregations=false" iarc-host query))) (defun iarc-search (query) (interactive "sIArc Query: ") (setq iarc-search-dataset (let-alist (iarc-api-search query) .response.body.hits.hits)) (iarc)) (defun iarc-infobox () (interactive) (let ((help-window-select (not iarc-follow-mode))) (iarc-render-info (alist-get 'fields (tabulated-list-get-id))))) (defun iarc-render-info (info) (infobox-render (infobox-translate info (infobox-default-specs info)) `(iarc-render-infobox ,info) (called-interactively-p 'interactive))) (defun iarc-item-at-point () (interactive) (iarc-item (alist-get 'identifier (alist-get 'fields (tabulated-list-get-id))))) (define-derived-mode iarc-item-mode tabulated-list-mode "IArc Item" (hl-line-mode 1) (setq revert-buffer-function #'iarc-list-refresh)) (defvar-local iarc-item-id nil "The item identifier for the iarc-item mode") (defvar-local iarc-item-data nil "The content of the iarc-item mode") (defun iarc-item (id) "List content of item with ID" (let* ((buf (get-buffer-create (format "*IArc %s*" id))) (out (seq-map (lambda (s) (split-string s "\t")) (string-lines (with-temp-buffer (call-process "ia" nil t nil "ls" "-v" "-c" "name,mtime,size" id) (buffer-string)))))) (with-current-buffer buf (setq tabulated-list-format (vconcat (seq-map (lambda (c) (list c 20)) (car out)))) (setq tabulated-list-padding 2) (iarc-item-mode) (tabulated-list-init-header) (setq iarc-item-data (cdr out)) (iarc-item-list-refresh)) (pop-to-buffer-same-window buf))) (defun iarc-item-list-refresh () (setq tabulated-list-entries (seq-map 'iarc-item-list-print-entry iarc-item-data)) (tabulated-list-print)) (defun iarc-item-list-print-entry (info) (list info (vconcat info))) (provide 'iarc) ;;; iarc.el ends here