source: tags/debian_version_0_6_3/command.lisp

Last change on this file was 76, checked in by Erik Huelsmann, 19 years ago

Make default behaviours obey rpl_isupport parameters advertized by the server.

  • variable.lisp (*default-isupport-values*): New.
  • utility.lisp (irc-string-downcase): New. Method to do case mapping required to canonicalize entity (channel, nick) identity names. (parse-isupport-multivalue-argument): New. Parse isupport string used in multi-value argument-values as used for CHANLIMIT, CHANMODES, IDCHAN and others.
  • protocol.lisp (connection:server-capabilities): New. This slot stores the assoc list of parameter keys and their values. (case-map-name): New. Returns the case-mapping used for a connection. (re-apply-case-mapping): New. Make sure all nicks and channels have been mapped using the same function. Also assures all hashes are based on the same mapping function. (add-default-hooks): Add irc-rpl_isupport-message to the default hooks list. (normalize-channel-name): Add connection parameter; use case-mapping active for the given connection. (make-channel): Add a connection to be passed in order to be able to do name-normalization. (make-user): Add connection parameter in order to be able to do name-normalization. (canonicalize-nickname): Use server-advertized nickname prefixes to determine how to canonicalize. (normalize-nickname): Use connections case-mapping to do normalization. (find-or-make-user): Pass connection in call to make-user. (find-channel, find-user, change-nickname): Update callers of normalize-nickname, normalize-channel-name and canonicalize-nickname
  • command.lisp (connect): Change instance creation order; creating a user requires a connection now.
  • event.lisp (default-hook [irc-rpl_isupport-message]): New. Implement default hook message for rpl_isupport message. Make sure that default values do get set. (default-hook [irc-rpl_list-message,

irc-join-message]): Update caller of make-channel.

(default-hook [irc-rpl_namreply-message]): Update caller of
canonicalize-nickname.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.9 KB
Line 
1;;;; $Id: command.lisp 76 2005-01-20 23:59:19Z ehuelsmann $
2;;;; $Source$
3
4;;;; See LICENSE for licensing information.
5
6(in-package :irc)
7
8(defgeneric pass (connection password))
9(defgeneric nick (connection new-nickname))
10(defgeneric user- (connection username mode &optional realname))
11(defgeneric oper (connection name password))
12(defgeneric mode (connection nickname mode))
13(defgeneric op (connection channel nickname))
14(defgeneric deop (connection channel nickname))
15(defgeneric voice (connection channel user))
16(defgeneric devoice (connection channel nickname))
17(defgeneric ban (connection channel mask))
18(defgeneric unban (connection channel mask))
19(defgeneric service (connection nickname distribution info))
20(defgeneric quit (connection &optional message))
21(defgeneric squit (connection server comment))
22(defgeneric join (connection channel))
23(defgeneric multi-join (connection channels))
24(defgeneric part (connection channel))
25(defgeneric part-all (connection))
26(defgeneric topic- (connection channel topic))
27(defgeneric names (connection channel &optional target))
28(defgeneric list- (connection &optional channel target))
29(defgeneric invite (connection user channel))
30(defgeneric kick (connection channel user &optional comment))
31(defgeneric privmsg (connection channel message))
32(defgeneric notice (connection target message))
33(defgeneric motd- (connection &optional target))
34(defgeneric lusers (connection &optional mask target))
35(defgeneric version (connection &optional target))
36(defgeneric stats (connection &optional query target))
37(defgeneric links (connection &optional remote-server server-mask))
38(defgeneric time- (connection &optional target))
39(defgeneric trace- (connection &optional target))
40(defgeneric admin (connection &optional target))
41(defgeneric info (connection &optional target))
42(defgeneric servlist (connection &optional mask type))
43(defgeneric squery (connection service-name text))
44(defgeneric who (connection &optional mask o))
45(defgeneric whois (connection mask &optional target))
46(defgeneric whowas (connection nickname &optional count target))
47(defgeneric kill (connection user &optional comment))
48(defgeneric ping (connection server))
49(defgeneric pong (connection server &optional server2))
50(defgeneric error- (connection message))
51(defgeneric away (connection message))
52(defgeneric rehash (connection))
53(defgeneric die (connection))
54(defgeneric restart- (connection))
55(defgeneric summon (connection nickname &optional target channel))
56(defgeneric users- (connection &optional target))
57(defgeneric wallops (connection message))
58(defgeneric userhost (connection nickname))
59(defgeneric ison (connection user))
60(defgeneric ctcp (connection target message))
61(defgeneric ctcp-chat-initiate (connection nickname))
62
63
64(defmethod pass ((connection connection) (password string))
65  "A \"PASS\" command is not required for a client connection to be
66registered, but it MUST precede the latter of the NICK/USER
67combination (for a user connection) or the SERVICE command (for a
68service connection). The RECOMMENDED order for a client to register is
69as follows:
70
71                           1. Pass message
72           2. Nick message                 2. Service message
73           3. User message
74
75Upon success, the client will receive an RPL_WELCOME (for users) or
76RPL_YOURESERVICE (for services) message indicating that the connection
77is now registered and known the to the entire IRC network.  The reply
78message MUST contain the full client identifier upon which it was
79registered."
80  (send-irc-message connection :pass nil password))
81
82(defmethod nick ((connection connection) (new-nickname string))
83  (send-irc-message connection :nick nil new-nickname))
84
85(defmethod user- ((connection connection) (username string)
86                  (mode integer) &optional (realname ""))
87  (send-irc-message connection :user realname username mode "*"))
88
89(defmethod oper ((connection connection) (name string) (password string))
90  (send-irc-message connection :oper nil name password))
91
92(defmethod mode ((connection connection) (nickname string) (mode string))
93  (send-irc-message connection :mode nil nickname mode))
94
95;; utility functions not part of the RFCs
96(defmethod op ((connection connection) (channel string) (nickname string))
97  (send-irc-message connection :mode nil channel "+o" nickname))
98
99(defmethod op ((connection connection) (channel channel) (user user))
100  (op connection (name channel) (nickname user)))
101
102(defmethod deop ((connection connection) (channel string) (nickname string))
103  (send-irc-message connection :mode nil channel "-o" nickname))
104
105(defmethod deop ((connection connection) (channel channel) (user user))
106  (deop connection (name channel) (nickname user)))
107
108(defmethod voice ((connection connection) (channel string) (nickname string))
109  (send-irc-message connection :mode nil channel "+v" nickname))
110
111(defmethod voice ((connection connection) (channel channel) (user user))
112  (voice connection (name channel) (nickname user)))
113
114(defmethod devoice ((connection connection) (channel string) (nickname string))
115  (send-irc-message connection :mode nil channel "-v" nickname))
116
117(defmethod devoice ((connection connection) (channel channel) (user user))
118  (devoice connection (name channel) (nickname user)))
119
120(defmethod ban ((connection connection) (channel string) (mask string))
121  (send-irc-message connection :mode nil channel "+b" mask))
122
123(defmethod ban ((connection connection) (channel channel) (mask string))
124  (ban connection (name channel) mask))
125
126;; unban or deban?
127(defmethod unban ((connection connection) (channel string) (mask string))
128  (send-irc-message connection :mode nil channel "-b" mask))
129
130(defmethod unban ((connection connection) (channel channel) (mask string))
131  (unban connection (name channel) mask))
132
133(defmethod service ((connection connection) (nickname string)
134                    (distribution string) (info string))
135  (send-irc-message connection :service info nickname "*" distribution 0 0 info))
136
137(defmethod quit ((connection connection) &optional (message *default-quit-message*))
138  (remove-all-channels connection)
139  (remove-all-users connection)
140  (send-irc-message connection :quit message)
141  #+(and sbcl (not sb-thread))
142  (sb-sys:invalidate-descriptor (sb-sys:fd-stream-fd
143                                        (server-stream connection)))
144  (close (server-stream connection)))
145
146(defmethod squit ((connection connection) (server string) (comment string))
147  (send-irc-message connection :squit comment server))
148
149(defmethod join ((connection connection) (channel string))
150  (send-irc-message connection :join nil channel))
151
152(defmethod join ((connection connection) (channel channel))
153  (join connection (name channel)))
154
155;; utility function not part of the RFC
156(defmethod multi-join ((connection connection) (channels list))
157  (dolist (channel channels)
158    (join connection channel)))
159
160(defmethod part ((connection connection) (channel string))
161  (send-irc-message connection :part nil channel))
162
163(defmethod part ((connection connection) (channel channel))
164  (part connection (name channel)))
165
166;; utility function not part of the RFC
167(defmethod part-all ((connection connection))
168  (dolist (channel (channels connection))
169    (part connection (name channel))))
170
171(defmethod topic- ((connection connection) (channel string) (topic string))
172  (send-irc-message connection :topic topic channel))
173
174(defmethod topic- ((connection connection) (channel channel) (topic string))
175  (topic- connection (name channel) topic))
176
177(defmethod names ((connection connection) (channel string)
178                  &optional (target ""))
179  (send-irc-message connection :names nil channel target))
180
181(defmethod names ((connection connection) (channel channel)
182                  &optional (target ""))
183  (names connection (name channel) target))
184
185(defmethod list- ((connection connection) &optional
186                  (channel "") (target ""))
187  (send-irc-message connection :list nil channel target))
188
189(defmethod invite ((connection connection) (nickname string) (channel string))
190  (send-irc-message connection :invite nil nickname channel))
191
192(defmethod invite ((connection connection) (user user) (channel channel))
193  (invite connection (nickname user) (name channel)))
194
195(defmethod kick ((connection connection) (channel string)
196                 (user string) &optional (comment ""))
197  (send-irc-message connection :kick comment channel user))
198
199(defmethod kick ((connection connection) (channel channel)
200                 (user user) &optional (comment ""))
201  (kick connection (name channel) (nickname user) comment))
202
203(defmethod privmsg ((connection connection) (target string) (message string))
204  (send-irc-message connection :privmsg message target))
205
206(defmethod privmsg ((connection connection) (user user) (message string))
207  (privmsg connection (nickname user) message))
208
209(defmethod privmsg ((connection connection) (channel channel) (message string))
210  (privmsg connection (name channel) message))
211
212(defmethod notice ((connection connection) (target string) (message string))
213  (send-irc-message connection :notice message target))
214
215(defmethod notice ((connection connection) (user user) (message string))
216  (notice connection (nickname user) message))
217
218(defmethod notice ((connection connection) (channel channel) (message string))
219  (notice connection (name channel) message))
220
221(defmethod motd- ((connection connection) &optional (target ""))
222  (send-irc-message connection :motd nil target))
223
224(defmethod lusers ((connection connection) &optional (mask "") (target ""))
225  (send-irc-message connection :lusers nil mask target))
226
227(defmethod version ((connection connection) &optional (target ""))
228  (send-irc-message connection :version nil target))
229
230(defmethod stats ((connection connection) &optional (query "") (target ""))
231  (send-irc-message connection :stats nil query target))
232                 
233(defmethod links ((connection connection) &optional (remote-server "")
234                  (server-mask ""))
235  (send-irc-message connection :links nil remote-server server-mask))
236
237(defmethod time- ((connection connection) &optional (target ""))
238  (send-irc-message connection :time nil target))
239
240(defun connect-to-server-socket (host port)
241  #+sbcl
242  (let ((s (make-instance 'sb-bsd-sockets:inet-socket
243                          :type :stream
244                          :protocol :tcp)))
245    (sb-bsd-sockets:socket-connect s (car (sb-bsd-sockets:host-ent-addresses
246                                           (sb-bsd-sockets:get-host-by-name host))) port)
247    s)
248  )
249
250(defun socket-stream (socket)
251  #+sbcl
252  (sb-bsd-sockets:socket-make-stream socket
253                                     :element-type 'character
254                                     :input t
255                                     :output t
256                                     :buffering :none)
257  #+openmcl
258  socket)
259
260(defun socket-connect (server port)
261  #+lispworks (comm:open-tcp-stream server port :errorp t)
262  #+cmu       (sys:make-fd-stream (ext:connect-to-inet-socket server port)
263                                  :input t
264                                  :output t
265                                  :element-type 'character)
266  #+allegro (socket:make-socket :remote-host server :remote-port port)
267  #+sbcl (socket-stream (connect-to-server-socket server port))
268  #+openmcl (ccl:make-socket :remote-host server :remote-port port)
269  #+armedbear (ext:get-socket-stream (ext:make-socket server port))
270  )
271 
272(defun connect (&key (nickname *default-nickname*)
273                     (username nil)
274                     (realname nil)
275                     (mode 0)
276                     (server *default-irc-server*)
277                     (port *default-irc-server-port*)
278                     (logging-stream t))
279  "Connect to server and return a connection object."
280  (let* ((stream (socket-connect server port))
281         (connection (make-connection :server-stream stream
282                                      :client-stream logging-stream
283                                      :server-name server))
284         (user (make-user connection
285                          :nickname nickname
286                          :username username
287                          :realname realname)))
288    (setf (user connection) user)
289    (nick connection nickname)
290    (user- connection (or username nickname) mode (or realname nickname))
291    (add-default-hooks connection)
292    connection))
293
294(defmethod trace- ((connection connection) &optional (target ""))
295  (send-irc-message connection :trace nil target))
296
297(defmethod admin ((connection connection) &optional (target ""))
298  (send-irc-message connection :admin nil target))
299
300(defmethod info ((connection connection) &optional (target ""))
301  (send-irc-message connection :info nil target))
302
303(defmethod servlist ((connection connection) &optional (mask "") (type ""))
304  (send-irc-message connection :servlist nil mask type))
305
306(defmethod squery ((connection connection) (service-name string) (text string))
307  (send-irc-message connection :squery text service-name))
308
309(defmethod who ((connection connection) &optional (mask "") (o ""))
310  (send-irc-message connection :who nil mask o))
311
312(defmethod whois ((connection connection) (mask string) &optional (target ""))
313  (send-irc-message connection :whois nil target mask))
314
315(defmethod whowas ((connection connection) (nickname string)
316                   &optional (count "") (target ""))
317  (send-irc-message connection :whowas nil nickname count target))
318
319(defmethod kill ((connection connection) (nickname string) &optional (comment ""))
320  (send-irc-message connection :kill comment nickname))
321
322(defmethod kill ((connection connection) (user user) &optional (comment ""))
323  (kill connection (nickname user) comment))
324
325(defmethod ping ((connection connection) (server string))
326  (send-irc-message connection :ping nil server))
327
328(defmethod pong ((connection connection) (server string) &optional (server2 ""))
329  (send-irc-message connection :pong nil server server2))
330
331(defmethod error- ((connection connection) (message string))
332  (send-irc-message connection :error message))
333
334(defmethod away ((connection connection) (message string))
335  (send-irc-message connection :away message))
336
337(defmethod rehash ((connection connection))
338  (send-irc-message connection :rehash))
339
340(defmethod die ((connection connection))
341  (send-irc-message connection :die))
342
343(defmethod restart- ((connection connection))
344  (send-irc-message connection :restart))
345
346(defmethod summon ((connection connection) (nickname string)
347                   &optional (target "") (channel ""))
348  (send-irc-message connection :summon nil nickname target channel))
349
350(defmethod users- ((connection connection) &optional (target ""))
351  (send-irc-message connection :users nil target))
352
353(defmethod wallops ((connection connection) (message string))
354  (send-irc-message connection :wallops message))
355
356(defmethod userhost ((connection connection) (nickname string))
357  (send-irc-message connection :userhost nil nickname))
358
359(defmethod userhost ((connection connection) (user user))
360  (userhost connection (nickname user)))
361
362(defmethod ison ((connection connection) (nickname string))
363  (send-irc-message connection :ison nil nickname))
364
365(defmethod ison ((connection connection) (user user))
366  (ison connection (nickname user)))
367
368;; utility functions not part of the RFC
369(defmethod ctcp ((connection connection) target message)
370  (send-irc-message connection :privmsg (make-ctcp-message message) target))
371
372(defmethod ctcp-chat-initiate ((connection connection) (nickname string))
373  #+sbcl
374  (let ((socket (sb-bsd-sockets:make-inet-socket :stream :tcp))
375        (port 44347))
376    (sb-bsd-sockets:socket-bind socket #(127 0 0 1) port) ; arbitrary port
377    (sb-bsd-sockets:socket-listen socket 1) ; accept one connection
378    (ctcp connection nickname
379          (format nil "DCC CHAT chat ~A ~A"
380                                        ; the use of hostname here is incorrect (it could be a firewall's IP)
381                  (host-byte-order (hostname (user connection))) port))
382    (make-dcc-connection :user (find-user connection nickname)
383                         :input-stream t
384                         :output-stream (sb-bsd-sockets:socket-make-stream socket :input t :output t :buffering :none)
385                         :socket socket))
386  #-sbcl (warn "ctcp-chat-initiate is not supported on this implementation.")
387  )
Note: See TracBrowser for help on using the repository browser.