diff options
Diffstat (limited to 'emacs/.emacs.d/lisp/my')
-rw-r--r-- | emacs/.emacs.d/lisp/my/my-libgen.el | 116 | ||||
-rw-r--r-- | emacs/.emacs.d/lisp/my/my-web.el | 50 | ||||
-rw-r--r-- | emacs/.emacs.d/lisp/my/reddio.el | 53 |
3 files changed, 219 insertions, 0 deletions
diff --git a/emacs/.emacs.d/lisp/my/my-libgen.el b/emacs/.emacs.d/lisp/my/my-libgen.el index 6b65eb1..67e0071 100644 --- a/emacs/.emacs.d/lisp/my/my-libgen.el +++ b/emacs/.emacs.d/lisp/my/my-libgen.el @@ -251,5 +251,121 @@ (filesize-human . ,filesize-human) (extension . ,extension)))) +(defvar my-libfic-download-dir "~/Downloads") +(defun my-libfic-search (query) + (interactive "sQuery: ") + (generic-search-open + (mapcar 'my-libfic-search-parse-tr + (cdr + (dom-by-tag + (my-url-fetch-dom + (format "%s/fiction/?q=%s" + my-libgen-host query)) + 'tr))) + (format "libfic-query:%s" query) + `((formatter . my-libfic-search-format-result) + (default-action . my-grok-libfic-action) + (keymap . ,my-libfic-button-keymap)))) + +(defun my-libfic-search-parse-tr (tr) + (let* ((tds (dom-by-tag tr 'td)) + (author (string-trim (dom-texts (pop tds) ""))) + (series (dom-text (pop tds))) + (title-id (pop tds)) + (title-md5 (car (dom-by-tag title-id 'a))) + (title (dom-text title-md5)) + (md5 (elt (split-string (or (dom-attr title-md5 'href) "") "/") 2)) + (identifier (dom-text (dom-by-class title-id "catalog_identifier"))) + (language (dom-text (pop tds))) + (extension-filesize-human (split-string (dom-text (pop tds)) " / ")) + (extension (downcase (car extension-filesize-human))) + (filesize-human (cadr extension-filesize-human)) + ) + `((author . ,author) + (series . ,series) + (md5 . ,md5) + (title . ,title) + (identifier . ,identifier) + (language . ,language) + (filesize-human . ,filesize-human) + (extension . ,extension)))) + +(defun my-libfic-search-format-result (info) + (format + "%s [%s] %s" + (my-libfic-format-filename info) + (alist-get 'language info) + (alist-get 'filesize-human info))) + +(defun my-libfic-format-filename (info) + (replace-regexp-in-string "[:;]" "_" + (format + "%s - %s (%s) [%s].%s" + (alist-get 'author info) + (alist-get 'title info) + (alist-get 'series info) + (alist-get 'identifier info) + (alist-get 'extension info)))) + +(defun my-grok-libfic-action (info) + (interactive) + (my-org-create-node + (my-grok-libfic-make-info + (my-libfic-update-info info)) + t)) + +(defun my-libfic-update-info (info) + (when-let ((tr-id + (seq-find + (lambda (tr) + (equal "ID:" (dom-text (car (dom-by-tag tr 'td))))) + (dom-by-tag + (my-url-fetch-dom + (format "%s/fiction/%s" my-libgen-host (alist-get 'md5 info))) + 'tr)))) + `((id . ,(dom-text (cadr (dom-by-tag tr-id 'td)))) . ,info))) + +;;; todo: description; publisher; cover +(defun my-grok-libfic-make-info (info) + (list + (cons "libfic-id" (alist-get 'id info)) + (cons "Title" (alist-get 'title info)) + (cons "Series" (alist-get 'series info)) + (cons "Authors" (alist-get 'author info)) + (cons "ISBN" (alist-get 'identifier info)) + (cons "Language" (alist-get 'language info)) + (cons "Filesize-human" (alist-get 'filesize-human info)) + (cons "Extension" (alist-get 'extension info)) + (cons "md5" (alist-get 'md5 info)))) + +(defvar my-libfic-button-keymap + (let ((kmap (make-sparse-keymap))) + (set-keymap-parent kmap button-map) + (define-key kmap "d" 'my-libfic-download-action) + (define-key kmap "p" 'my-libfic-show-more-info) + kmap)) + +(defun my-libfic-show-more-info () + (interactive) + (let ((info (get-text-property (point) 'button-data))) + (pp (my-grok-libfic-make-info (my-libfic-update-info info))))) + +(defun my-libfic-download-action () + (interactive) + (let ((info (get-text-property (point) 'button-data))) + (my-wget-async + (my-libfic-make-download-link-onion + (my-libfic-update-info info)) + (format "%s/%s" (expand-file-name my-libfic-download-dir) + (my-libfic-format-filename info))))) + +(defun my-libfic-make-download-link-onion (info) + (let ((id-head (substring (alist-get 'id info) 0 -3))) + (format "%s/FF/%s%s/%s" + my-libgen-onion-host + (make-string (- 4 (length id-head)) ?0) + id-head + (downcase (alist-get 'md5 info))))) + (provide 'my-libgen) ;;; my-libgen.el ends here diff --git a/emacs/.emacs.d/lisp/my/my-web.el b/emacs/.emacs.d/lisp/my/my-web.el index 311bcf9..95592fd 100644 --- a/emacs/.emacs.d/lisp/my/my-web.el +++ b/emacs/.emacs.d/lisp/my/my-web.el @@ -148,5 +148,55 @@ (kill-new url) (message "Copied link: %s" url))) +;;; webgetter +(require 'my-net) +(defun my-open-spectator-au (url &optional no-overwrite) + (interactive "sspectator.com.au link: ") + (let ((url-request-extra-headers '(("X-Forwarded-For" . "66.249.66.1"))) + (url-user-agent "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")) + (let ((file-name + (if no-overwrite + (my-make-unique-file-name + (my-make-file-name-from-url url) + my-download-dir) + (expand-file-name + (my-make-file-name-from-url url) + my-download-dir)))) + (url-copy-file url file-name (not no-overwrite)) + (browse-url-firefox (format "file://%s" file-name))))) + +(defun my-mastodon-url-p (url) + "Guess if a url is a mastodon post. +e.g. https://hostux.social/@fsf/113709722998924141 +" + (pcase-let* ((urlobj (url-generic-parse-url url)) + (`(,path . _) (url-path-and-query urlobj))) + (string-match-p "^/@[^/]+/[0-9]\\{18\\}$" path))) + +(defun my-hacker-news-url-p (url) + "Check if a url is a hacker news post. +e.g. https://news.ycombinator.com/item?id=42505454" + (let ((urlobj (url-generic-parse-url url))) + (and (equal "news.ycombinator.com" (url-host urlobj)) + (string-match-p "^/item\\?id=[0-9]+$" (url-filename urlobj))))) + +(defun my-stack-overflow-url-p (url) + "Guess whether a url stack overflow question +e.g. +https://emacs.stackexchange.com/questions/40887/in-org-mode-how-do-i-link-to-internal-documentation" + (pcase-let* ((urlobj (url-generic-parse-url url)) + (`(,path . _) (url-path-and-query urlobj))) + (string-match-p "^/questions/[0-9]+/.+$" path)) ) + +(advice-add 'server-visit-files :around #'my-ec-handle-http) +(defun my-ec-handle-http (orig-fun files client &rest args) + ;; (message "GOT %s" files) + (dolist (var files) + (let ((fname (expand-file-name (car var)))) + (when (string-match ".*/\\(https?:/\\)" fname) + (browse-url (replace-match "\\1/" nil nil fname)) + (setq files (delq var files))))) + (apply orig-fun files client args)) + (provide 'my-web) ;;; my-web.el ends here diff --git a/emacs/.emacs.d/lisp/my/reddio.el b/emacs/.emacs.d/lisp/my/reddio.el new file mode 100644 index 0000000..2198e43 --- /dev/null +++ b/emacs/.emacs.d/lisp/my/reddio.el @@ -0,0 +1,53 @@ +;;; reddio.el -- reddit client through reddio -*- lexical-binding: t -*- + +;; Copyright (C) 2024 Free Software Foundation, Inc. + +;; Author: Yuchen Pei <id@ypei.org> +;; Package-Requires: ((emacs "29.4")) + +;; 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 <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; reddit client through reddio. + +;;; Code: + +(defvar reddio-buffer "*reddio*") + +(defun reddio-open-url (url) + (interactive "sReddit link: ") + (when (string-match "/\\(comments/[^/]+\\)/" url) + (with-current-buffer (get-buffer-create reddio-buffer) + (let ((inhibit-read-only t)) + (erase-buffer) + (when (= 0 (call-process "reddio" nil reddio-buffer nil "print" + (match-string 1 url))) + (goto-char (point-min))) + (delete-trailing-whitespace)) + (text-mode) + (view-mode)) + (display-buffer reddio-buffer))) + +(defun reddio-reddit-url-p (url) + "e.g. +https://www.reddit.com/r/linux/comments/cs3os6/introducing_reddio_a_commandline_interface_for/" + (let ((urlobj (url-generic-parse-url url))) + (and (string-match-p "^.*\\<reddit.com$" (url-host urlobj)) + (string-match-p "^/r/[^/]+/comments/[^/]+/.+$" (url-filename urlobj))))) + +(provide 'reddio) +;;; reddio.el ends here |