aboutsummaryrefslogtreecommitdiff
path: root/emacs/.emacs.d/lisp/my/my-net.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-net.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-net.el')
-rw-r--r--emacs/.emacs.d/lisp/my/my-net.el113
1 files changed, 113 insertions, 0 deletions
diff --git a/emacs/.emacs.d/lisp/my/my-net.el b/emacs/.emacs.d/lisp/my/my-net.el
new file mode 100644
index 0000000..7713dba
--- /dev/null
+++ b/emacs/.emacs.d/lisp/my/my-net.el
@@ -0,0 +1,113 @@
+;;; my-net.el -- Network related extensions for emacs core -*- 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:
+
+;; Network related extensions for emacs core.
+
+;;; Code:
+
+
+;;; net utilities
+(defvar my-download-dir "~/Downloads")
+
+(defun my-make-file-name-from-url (url)
+ (file-name-nondirectory
+ (directory-file-name
+ (car (url-path-and-query (url-generic-parse-url
+ (url-unhex-string url)))))))
+
+(defun my-fetch-url (url)
+ (interactive "sURL: ")
+ (let ((file-name (expand-file-name (my-make-file-name-from-url url)
+ my-download-dir)))
+ (url-retrieve url 'my-fetch-url-save-and-switch (list file-name))))
+
+(defun my-fetch-url-save-and-switch (status file-name)
+ (unless (plist-get status :error)
+ (my-delete-http-header)
+ (write-file file-name)
+ (let ((coding-system-for-read 'utf-8))
+ (revert-buffer t t))
+ (switch-to-buffer (current-buffer))))
+
+(defun my-kill-http-header ()
+ (my-skip-http-header)
+ (let ((killed (buffer-substring-no-properties (point-min) (point))))
+ (delete-region (point-min) (point))
+ killed))
+
+(defun my-parse-http-header (text)
+ (let ((status) (fields))
+ (with-temp-buffer
+ (insert text)
+ (goto-char (point-min))
+ (re-search-forward "^HTTP.*\\([0-9]\\{3\\}\\).*$")
+ (setq status (match-string 1))
+ (while (re-search-forward "^\\(.*?\\): \\(.*\\)$" nil t)
+ (push (cons (intern (match-string 1)) (match-string 2)) fields)))
+ (list (cons 'status status) (cons 'fields fields))))
+
+(defvar my-client-buffer-name "*my-api*")
+
+(defun my-url-fetch-json (url &optional decompression with-header)
+ (my-url-fetch-internal
+ url
+ (lambda ()
+ (json-read-from-string (decode-coding-string (buffer-string) 'utf-8)))
+ decompression
+ with-header))
+
+(defun my-url-fetch-dom (url &optional decompression with-header)
+ (my-url-fetch-internal
+ url
+ (lambda () (libxml-parse-html-region (point) (point-max)))
+ decompression
+ with-header))
+
+(defun my-url-fetch-internal (url buffer-processor decompression with-header)
+ (with-current-buffer (get-buffer-create my-client-buffer-name)
+ (goto-char (point-max))
+ (insert "[" (current-time-string) "] Request: " url "\n"))
+ (with-current-buffer (url-retrieve-synchronously url t)
+ (let ((header (my-kill-http-header)) (status) (fields))
+ (goto-char (point-min))
+ (setq header (my-parse-http-header header)
+ status (alist-get 'status header)
+ fields (alist-get 'fields header))
+ (with-current-buffer my-client-buffer-name
+ (insert "[" (current-time-string) "] Response: " status "\n"))
+ (when decompression
+ (call-process-region (point) (point-max) "gunzip" t t t)
+ (goto-char (point-min)))
+ (call-interactively 'delete-trailing-whitespace)
+ (if (string= status "200")
+ (unless (= (point) (point-max))
+ (if with-header
+ (list
+ (cons 'header fields)
+ (cons 'json (funcall buffer-processor)))
+ (funcall buffer-processor)))
+ (error "HTTP error: %s" (buffer-substring (point) (point-max)))))))
+
+(provide 'my-net)
+;;; my-net.el ends here