Initial commit.
[lurk.git] / murk.el
1 ;;; MURK --- Multiserver Unibuffer iRc Klient -*- lexical-binding:t -*-
2
3 ;; Copyright (C) 2024 plugd
4
5 ;; Author: plugd <plugd@thelambdalab.xyz>
6 ;; Created: 11 May 2024
7 ;; Version: 0.0
8 ;; Keywords: network
9 ;; Homepage: http://thelambdalab.xyz/metalurk
10 ;; Package-Requires: ((emacs "26"))
11
12 ;; This file is not part of GNU Emacs.
13
14 ;; This program is free software: you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation, either version 3 of the License, or
17 ;; (at your option) any later version.
18
19 ;; This program is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 ;; GNU General Public License for more details.
23
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with this file.  If not, see <http://www.gnu.org/licenses/>.
26
27 ;;; Commentary:
28
29 ;;; Code:
30
31 (provide 'murk)
32
33
34 ;;; Customizations
35
36 (defgroup murk nil
37   "Multiserver Unibuffer iRc Klient"
38   :group 'network)
39
40 (defcustom murk-nick "plugd"
41   "Default nick.")
42
43 (defcustom murk-default-quit-msg "Bye"
44   "Default quit message when none supplied.")
45
46 (defcustom murk-networks
47   '(("libera" "irc.libera.chat" 6697)
48     ("tilde" "tilde.chat" 6697))
49   "IRC networks.")
50
51
52 ;;; Faces
53 ;;
54
55
56 ;;; Global variables
57 ;;
58
59 (defvar murk-version "Murk v0.0"
60   "Value of this string is used in response to CTCP version queries.")
61
62 (defvar murk-notice-prefix "-!-")
63 (defvar murk-error-prefix "!!!")
64 (defvar murk-prompt-string ">")
65
66 ;;; Utility procedures
67 ;;
68
69 (defun murk--filtered-join (&rest args)
70   (string-join (seq-filter (lambda (el) el) args) " "))
71
72 (defun murk--as-string (obj)
73   (if obj
74       (with-output-to-string (princ obj))
75     nil))
76
77 ;;; Network processes
78 ;;
79
80 (defvar murk-connection-table nil
81   "An alist associating servers to connection information.
82 This includes the process and the response string.")
83
84 (defun murk-connection-process (server)
85   (elt (assoc server murk-connection-table) 1))
86
87 (defun murk-connection-response (server)
88   (elt (assoc server murk-connection-table) 2))
89
90 (defun murk-set-connection-response (server string)
91   (setf (elt (assoc server murk-connection-table) 3) string))
92
93 (defun murk-connection-close (server)
94   (setq murk-connection-table (assoc-delete-all server murk-connection-table)))
95
96 (defun murk-make-server-filter (server)
97   (lambda (proc string)
98     (dolist (line (split-string (concat (murk-connection-response server) string)
99                                 "\n"))
100       (if (string-suffix-p "\r" line)
101           (murk-eval-msg-string server (string-trim line))
102         (murk-set-connection-response line)))))
103
104 (defun murk-make-server-sentinel (server)
105   (lambda (proc string)
106     (unless (equal "open" (string-trim string))
107       (murk-display-error "Disconnected from server.")
108       (murk-remove-contexts-for-server server)
109       (murk-render-prompt)
110       (murk-connection-close server))))
111
112 (defun murk-start-process (server)
113   (let* ((row (assoc server murk-networks))
114          (host (elt row 1))
115          (port (elt row 2))
116          (flags (seq-drop row 3)))
117     (make-network-process :name (concat "lurk" server)
118                           :host host
119                           :service port
120                           :family nil
121                           :filter (murk-make-server-filter server)
122                           :sentinel (murk-make-server-sentinel server)
123                           :nowait nil
124                           :tls-parameters (if (memq :notls flags)
125                                               nil
126                                             (cons 'gnutls-x509pki
127                                                   (gnutls-boot-parameters
128                                                    :type 'gnutls-x509pki
129                                                    :hostname host)))
130                           :buffer "*lurk*")))
131
132 (defvar murk-ping-period 60)
133
134 ;; IDEA: Have a single ping timer which pings all connected hosts
135
136 (defun murk-connect (server)
137   (if (assoc server murk-connection-table)
138       (murk-display-error "Already connected to this network.")
139     (if (not (assoc server murk-networks))
140         (murk-display-error "Network '" server "' is unknown.")
141       (murk-start-process server)
142       (murk-send-msg (murk-msg nil nil "USER" murk-nick 0 "*" murk-nick))
143       (murk-send-msg (murk-msg nil nil "NICK" murk-nick)))))
144
145 ;;; Contexts and Servers
146 ;;
147
148 ;; A context is a list (server name ...) where name is a string
149 ;; representing either a channel name or nick, and server is a symbol
150 ;; identifying the server.
151 ;;
152 ;; Each server has a special context (server) used for messages
153 ;; to/from the server itself.
154
155 (defvar murk-current-context nil)
156 (defvar murk-context-members nil)
157
158 ;;; Main start procedure
159 ;;
160
161 (defun metalurk)
162
163 ;;; metalurk.el ends here