(defvar servall-endpoint "localhost:5555") (defvar servall-client-buffer-name "*servall-client*") (defun servall-api-wikipedia-search (query) (servall-url-fetch-json (concat servall-endpoint "/wikipedia/search/" query))) (defun servall-api-ytdl-search (query cb) (servall-url-fetch-json-async (concat servall-endpoint "/ytdl/search/" query) cb)) (defun servall-api-wikipedia-org (name) (servall-url-fetch-json (concat servall-endpoint "/wikipedia/org/" name))) (defun servall-api-wikipedia-summary (name) (servall-url-fetch-json (concat servall-endpoint "/wikipedia/summary/" name))) (defun servall-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)))) (defun servall-url-fetch-json (url &optional decompression with-header) (with-current-buffer (get-buffer-create servall-client-buffer-name) (goto-char (point-max)) (insert "[" (current-time-string) "] Request: " url "\n")) (with-current-buffer (url-retrieve-synchronously url t) (servall-url-fetch-json-callback nil nil decompression with-header))) (defun servall-url-fetch-json-async (url cb &optional decompression with-header) (with-current-buffer (get-buffer-create servall-client-buffer-name) (goto-char (point-max)) (insert "[" (current-time-string) "] Request: " url "\n")) (url-retrieve url 'servall-url-fetch-json-callback (list cb decompression with-header) t)) (defun servall-url-fetch-json-callback (unused cb decompression with-header) (let ((header) (status) (fields) (json) (result)) (delete-http-header) (setq header (servall-parse-http-header (car kill-ring)) status (alist-get 'status header) fields (alist-get 'fields header)) (with-current-buffer servall-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)) (setq json (json-read-from-string (decode-coding-string (buffer-string) 'utf-8))) (setq result (if with-header (list (cons 'header fields) (cons 'json json)) json))) (error "HTTP error: %s" (buffer-substring (point) (point-max)))) (if cb (funcall cb result) result))) (provide 'servall-client)