diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/net/jao-mullvad.el | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/lib/net/jao-mullvad.el b/lib/net/jao-mullvad.el new file mode 100644 index 0000000..f53840f --- /dev/null +++ b/lib/net/jao-mullvad.el @@ -0,0 +1,148 @@ +;;; jao-mullvad.el --- Calling the mullvad cli -*- lexical-binding: t; -*- + +;; Copyright (C) 2021 jao + +;; Author: jao <mail@jao.io> +;; Keywords: processes + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program 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 General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: + +;; Simple helpers to call mullvad and parse its output + +;;; Code: + +(defvar jao-mullvad-mode-map + (let ((map (make-keymap))) + (suppress-keymap map) + (define-key map [?q] 'bury-buffer) + (define-key map [?n] 'next-line) + (define-key map [?p] 'previous-line) + (define-key map [?g] 'jao-mullvad-status) + (define-key map [?l] 'jao-mullvad-list) + (define-key map [?u] 'jao-mullvad-update-list) + (define-key map [?r] 'jao-mullvad-reconnect) + (define-key map [?d] 'jao-mullvad-disconnect) + (define-key map [?c] 'jao-mullvad-connect) + map)) + +(defvar jao-mullvad--buffer "*mullvad*") + +;;;###autoload +(defun jao-mullvad-mode () + "A very simple mode to show the output of mulvad commands." + (interactive) + (kill-all-local-variables) + (buffer-disable-undo) + (use-local-map jao-mullvad-mode-map) + ;; (setq-local font-lock-defaults '(jao-jao-mullvad-font-lock-keywords)) + (setq-local truncate-lines t) + (setq-local next-line-add-newlines nil) + (setq major-mode 'jao-mullvad-mode) + (setq mode-name "mullvad") + (read-only-mode 1)) + +(defun jao-mullvad--do (things &optional buffer) + "Execute a mullvad command THINGS in the given BUFFER." + (let ((b (or buffer (pop-to-buffer (get-buffer-create jao-mullvad--buffer))))) + (let ((inhibit-read-only t) + (cmd (format "mullvad %s" things))) + (delete-region (point-min) (point-max)) + (message "Running: %s ...." cmd) + (shell-command cmd b) + (message "")) + (jao-mullvad-mode))) + +(defconst jao-mullvad--country-rx "^\\([^ \t\n]+ (...?)\\)$") +(defconst jao-mullvad--city-rx " \\([^ (]+ (...)\\)") + +(defun jao-mullvad--list () + "Compute an alist of available relay countries with their cities." + (with-temp-buffer + (jao-mullvad--do "relay list" (current-buffer)) + (goto-char (point-min)) + (let ((countries) (country)) + (while (not (eobp)) + (cond ((looking-at jao-mullvad--country-rx) + (when country + (setq countries (cons (reverse country) countries))) + (setq country (list (match-string 1)))) + ((looking-at jao-mullvad--city-rx) + (setq country (cons (match-string 1) country)))) + (forward-line 1)) + (reverse countries)))) + +;;;###autoload +(defun jao-mullvad-status () + "Display mullvad connection status, including country, city and server." + (interactive) + (jao-mullvad--do "status") + (when (re-search-forward "[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+" nil t) + (let ((ip (match-string 0)) (country "") (city "") (server "")) + (with-temp-buffer + (jao-mullvad--do "relay list" (current-buffer)) + (goto-char (point-min)) + (when (search-forward ip nil t) + (beginning-of-line) + (when (looking-at "\t\t\\([^( ]+\\) (") + (setq server (match-string 1))) + (when (re-search-backward jao-mullvad--city-rx nil t) + (setq city (string-trim (match-string 0)))) + (when (re-search-backward jao-mullvad--country-rx nil t) + (setq country (match-string 0))))) + (let ((inhibit-read-only t)) + (forward-line 1) + (insert "Connected to " country " " city " - " server "\n") + (goto-char (point-min)))))) + +;;;###autoload +(defun jao-mullvad-connect () + "Choose a country and city and set them to the default relay location." + (interactive) + (let* ((cc (jao-mullvad--list)) + (country (completing-read "Country: " (mapcar #'car cc) nil t)) + (city (completing-read "City: " (cdr (assoc country cc #'string=)))) + (cntr (and (string-match "(\\(...?\\))" country) (match-string 1 country))) + (code (and (string-match "(\\(...\\))" city) (match-string 1 city)))) + (when (y-or-n-p (format "Set location to %s / %s?" country city)) + (jao-mullvad--do (format "relay set location %s %s" cntr code))))) + +;;;###autoload +(defun jao-mullvad-reconnect () + "Ask mullvad to reconnect." + (interactive) + (jao-mullvad--do "reconnect")) + +;;;###autoload +(defun jao-mullvad-disconnect () + "Ask mullvad to disconnect, after confirmation." + (interactive) + (when (y-or-n-p "Disconnect?") (jao-mullvad--do "disconnect"))) + +;;;###autoload +(defun jao-mullvad-list () + "List all available relay locations." + (interactive) + (jao-mullvad--do "relay list")) + +;;;###autoload +(defun jao-mullvad-update-list () + "Update list of available relay locations (background operation)." + (interactive) + (jao-mullvad--do "relay update")) + + +(provide 'jao-mullvad) +;;; jao-mullvad.el ends here |