| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
|
|---|
| 6 |
|
|---|
| 7 |
|
|---|
| 8 |
|
|---|
| 9 |
|
|---|
| 10 |
|
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 |
|
|---|
| 15 |
|
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
(require 'erc) |
|---|
| 30 |
(eval-when-compile (require 'cl)) |
|---|
| 31 |
|
|---|
| 32 |
(defgroup erc-ezbounce nil |
|---|
| 33 |
"Interface to the EZBounce IRC bouncer (a virtual IRC server)" |
|---|
| 34 |
:group 'erc) |
|---|
| 35 |
|
|---|
| 36 |
(defcustom erc-ezb-regexp "^ezbounce!srv$" |
|---|
| 37 |
"Regexp used by the EZBouncer to identify itself to the user." |
|---|
| 38 |
:group 'erc-ezbounce |
|---|
| 39 |
:type 'string) |
|---|
| 40 |
|
|---|
| 41 |
(defcustom erc-ezb-login-alist '() |
|---|
| 42 |
"Alist of logins suitable for the server we're connecting to. |
|---|
| 43 |
|
|---|
| 44 |
The alist's format is as follows: |
|---|
| 45 |
|
|---|
| 46 |
(((server . port) . (username . password)) |
|---|
| 47 |
((server . port) . (username . password)) |
|---|
| 48 |
...)" |
|---|
| 49 |
:group 'erc-ezbounce |
|---|
| 50 |
:type '(repeat |
|---|
| 51 |
(cons (cons :tag "Server" |
|---|
| 52 |
string |
|---|
| 53 |
string) |
|---|
| 54 |
(cons :tag "Login" |
|---|
| 55 |
string |
|---|
| 56 |
string)))) |
|---|
| 57 |
|
|---|
| 58 |
(defvar erc-ezb-action-alist '(("^\\[awaiting login/pass command\\]$" . erc-ezb-identify) |
|---|
| 59 |
("^\\[use /quote CONN <server> to connect\\]$" . erc-ezb-select) |
|---|
| 60 |
("^ID +IRC NICK +TO +TIME$" . erc-ezb-init-session-list) |
|---|
| 61 |
("^$" . erc-ezb-end-of-session-list) |
|---|
| 62 |
(".*" . erc-ezb-add-session)) |
|---|
| 63 |
"Alist of actions to take on NOTICEs from EZBounce.") |
|---|
| 64 |
|
|---|
| 65 |
|
|---|
| 66 |
(defvar erc-ezb-session-list '() |
|---|
| 67 |
"List of detached EZBounce sessions.") |
|---|
| 68 |
(make-variable-buffer-local 'erc-ezb-session-list) |
|---|
| 69 |
|
|---|
| 70 |
(defvar erc-ezb-inside-session-listing nil |
|---|
| 71 |
"Indicate whether current notices are expected to be EZB session listings.") |
|---|
| 72 |
|
|---|
| 73 |
|
|---|
| 74 |
(defun erc-cmd-ezb (line &optional force) |
|---|
| 75 |
"Send EZB commands to the EZBouncer verbatim." |
|---|
| 76 |
(erc-server-send (concat "EZB " line))) |
|---|
| 77 |
(put 'erc-cmd-EZB 'do-not-parse-args t) |
|---|
| 78 |
|
|---|
| 79 |
|
|---|
| 80 |
(defun erc-ezb-get-login (server port) |
|---|
| 81 |
"Return an appropriate EZBounce login for SERVER and PORT. |
|---|
| 82 |
Look up entries in `erc-ezb-login-alist'. If the username or password |
|---|
| 83 |
in the alist is `nil', prompt for the appropriate values." |
|---|
| 84 |
(let ((login (cdr (assoc (cons server port) erc-ezb-login-alist)))) |
|---|
| 85 |
(when login |
|---|
| 86 |
(let ((username (car login)) |
|---|
| 87 |
(password (cdr login))) |
|---|
| 88 |
(when (null username) |
|---|
| 89 |
(setq username (read-from-minibuffer (format "EZBounce user name for %s:%s: " server port)))) |
|---|
| 90 |
(when (null password) |
|---|
| 91 |
(setq password (read-passwd (format "EZBounce password for %s:%s: " server port)))) |
|---|
| 92 |
(cons username password))))) |
|---|
| 93 |
|
|---|
| 94 |
|
|---|
| 95 |
(defun erc-ezb-lookup-action (message) |
|---|
| 96 |
(let ((function-alist erc-ezb-action-alist) |
|---|
| 97 |
found) |
|---|
| 98 |
(while (and (not found) |
|---|
| 99 |
function-alist) |
|---|
| 100 |
(let ((regexp (caar function-alist)) |
|---|
| 101 |
(function (cdar function-alist))) |
|---|
| 102 |
(when (string-match regexp message) |
|---|
| 103 |
(setq found function)) |
|---|
| 104 |
(setq function-alist (cdr function-alist)))) |
|---|
| 105 |
found)) |
|---|
| 106 |
|
|---|
| 107 |
|
|---|
| 108 |
(defun erc-ezb-notice-autodetect (proc parsed) |
|---|
| 109 |
"React on an EZBounce NOTICE request." |
|---|
| 110 |
(let* ((sender (erc-response.sender parsed)) |
|---|
| 111 |
(message (erc-response.contents parsed)) |
|---|
| 112 |
(function (erc-ezb-lookup-action message))) |
|---|
| 113 |
(when (and (string-match erc-ezb-regexp sender) |
|---|
| 114 |
function) |
|---|
| 115 |
(funcall function message))) |
|---|
| 116 |
nil) |
|---|
| 117 |
|
|---|
| 118 |
|
|---|
| 119 |
(defun erc-ezb-identify (message) |
|---|
| 120 |
"Identify to the EZBouncer server." |
|---|
| 121 |
(let ((login (erc-ezb-get-login erc-session-server (erc-port-to-string erc-session-port)))) |
|---|
| 122 |
(unless (null login) |
|---|
| 123 |
(let ((username (car login)) |
|---|
| 124 |
(pass (cdr login))) |
|---|
| 125 |
(erc-server-send (concat "LOGIN " username " " pass)))))) |
|---|
| 126 |
|
|---|
| 127 |
|
|---|
| 128 |
(defun erc-ezb-init-session-list (message) |
|---|
| 129 |
"Reset the EZBounce session list to nil." |
|---|
| 130 |
(setq erc-ezb-session-list nil) |
|---|
| 131 |
(setq erc-ezb-inside-session-listing t)) |
|---|
| 132 |
|
|---|
| 133 |
|
|---|
| 134 |
(defun erc-ezb-end-of-session-list (message) |
|---|
| 135 |
"Indicate the end of the EZBounce session listing." |
|---|
| 136 |
(setq erc-ezb-inside-session-listing nil)) |
|---|
| 137 |
|
|---|
| 138 |
|
|---|
| 139 |
(defun erc-ezb-add-session (message) |
|---|
| 140 |
"Add an EZBounce session to the session list." |
|---|
| 141 |
(when (and erc-ezb-inside-session-listing |
|---|
| 142 |
(string-match "^\\([^ \n]+\\) +\\([^ \n]+\\) +\\([^ \n]+\\) +\\([^ \n]+\\)$" message)) |
|---|
| 143 |
(let ((id (match-string 1 message)) |
|---|
| 144 |
(nick (match-string 2 message)) |
|---|
| 145 |
(to (match-string 3 message))) |
|---|
| 146 |
(add-to-list 'erc-ezb-session-list (list id nick to))))) |
|---|
| 147 |
|
|---|
| 148 |
|
|---|
| 149 |
(defun erc-ezb-select (message) |
|---|
| 150 |
"Select an IRC server to use by EZBounce, in ERC style." |
|---|
| 151 |
(unless (and erc-ezb-session-list |
|---|
| 152 |
(erc-ezb-select-session)) |
|---|
| 153 |
(let* ((server (read-from-minibuffer |
|---|
| 154 |
"IRC server: " "" nil nil 'erc-server-history-list)) |
|---|
| 155 |
(port |
|---|
| 156 |
(erc-string-to-port |
|---|
| 157 |
(read-from-minibuffer "IRC port: " |
|---|
| 158 |
(erc-port-to-string "6667"))))) |
|---|
| 159 |
(erc-server-send (format "CONN %s %s" server port))))) |
|---|
| 160 |
|
|---|
| 161 |
|
|---|
| 162 |
|
|---|
| 163 |
(defun erc-ezb-select-session () |
|---|
| 164 |
"Select a detached EZBounce session." |
|---|
| 165 |
(let ((session (completing-read "Existing Session (RET to enter a new one): " |
|---|
| 166 |
erc-ezb-session-list))) |
|---|
| 167 |
(if (string= session "") |
|---|
| 168 |
nil |
|---|
| 169 |
(erc-server-send (format "REATTACH %s" session))))) |
|---|
| 170 |
|
|---|
| 171 |
|
|---|
| 172 |
|
|---|
| 173 |
(defun erc-ezb-initialize () |
|---|
| 174 |
"Add EZBouncer convenience functions to ERC." |
|---|
| 175 |
(add-hook 'erc-server-NOTICE-functions 'erc-ezb-notice-autodetect)) |
|---|
| 176 |
|
|---|
| 177 |
(provide 'erc-ezbounce) |
|---|
| 178 |
|
|---|
| 179 |
|
|---|
| 180 |
|
|---|
| 181 |
|
|---|