erc-backend.el 79 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004
  1. ;;; erc-backend.el --- Backend network communication for ERC
  2. ;; Copyright (C) 2004-2012 Free Software Foundation, Inc.
  3. ;; Filename: erc-backend.el
  4. ;; Author: Lawrence Mitchell <wence@gmx.li>
  5. ;; Created: 2004-05-7
  6. ;; Keywords: IRC chat client internet
  7. ;; This file is part of GNU Emacs.
  8. ;; GNU Emacs is free software: you can redistribute it and/or modify
  9. ;; it under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation, either version 3 of the License, or
  11. ;; (at your option) any later version.
  12. ;; GNU Emacs is distributed in the hope that it will be useful,
  13. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. ;; GNU General Public License for more details.
  16. ;; You should have received a copy of the GNU General Public License
  17. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  18. ;;; Commentary:
  19. ;; This file defines backend network communication handlers for ERC.
  20. ;;
  21. ;; How things work:
  22. ;;
  23. ;; You define a new handler with `define-erc-response-handler'. This
  24. ;; defines a function, a corresponding hook variable, and populates a
  25. ;; global hash table `erc-server-responses' with a map from response
  26. ;; to hook variable. See the function documentation for more
  27. ;; information.
  28. ;;
  29. ;; Upon receiving a line from the server, `erc-parse-server-response'
  30. ;; is called on it.
  31. ;;
  32. ;; A line generally looks like:
  33. ;;
  34. ;; LINE := ':' SENDER ' ' COMMAND ' ' (COMMAND-ARGS ' ')* ':' CONTENTS
  35. ;; SENDER := Not ':' | ' '
  36. ;; COMMAND := Not ':' | ' '
  37. ;; COMMAND-ARGS := Not ':' | ' '
  38. ;;
  39. ;; This gets parsed and stuffed into an `erc-response' struct. You
  40. ;; can access the fields of the struct with:
  41. ;;
  42. ;; COMMAND --- `erc-response.command'
  43. ;; COMMAND-ARGS --- `erc-response.command-args'
  44. ;; CONTENTS --- `erc-response.contents'
  45. ;; SENDER --- `erc-response.sender'
  46. ;; LINE --- `erc-response.unparsed'
  47. ;;
  48. ;; WARNING, WARNING!!
  49. ;; It's probably not a good idea to destructively modify the list
  50. ;; of command-args in your handlers, since other functions down the
  51. ;; line may well need to access the arguments too.
  52. ;;
  53. ;; That is, unless you're /absolutely/ sure that your handler doesn't
  54. ;; invoke some other function that needs to use COMMAND-ARGS, don't do
  55. ;; something like
  56. ;;
  57. ;; (while (erc-response.command-args parsed)
  58. ;; (let ((a (pop (erc-response.command-args parsed))))
  59. ;; ...))
  60. ;;
  61. ;; The parsed response is handed over to
  62. ;; `erc-handle-parsed-server-response', which checks whether it should
  63. ;; carry out duplicate suppression, and then runs `erc-call-hooks'.
  64. ;; `erc-call-hooks' retrieves the relevant hook variable from
  65. ;; `erc-server-responses' and runs it.
  66. ;;
  67. ;; Most handlers then destructure the parsed response in some way
  68. ;; (depending on what the handler is, the arguments have different
  69. ;; meanings), and generally display something, usually using
  70. ;; `erc-display-message'.
  71. ;;; TODO:
  72. ;; o Generalize the display-line code so that we can use it to
  73. ;; display the stuff we send, as well as the stuff we receive.
  74. ;; Then, move all display-related code into another backend-like
  75. ;; file, erc-display.el, say.
  76. ;;
  77. ;; o Clean up the handlers using new display code (has to be written
  78. ;; first).
  79. ;;; History:
  80. ;; 2004/05/10 -- Handler bodies taken out of erc.el and ported to new
  81. ;; interface.
  82. ;; 2005-08-13 -- Moved sending commands from erc.el.
  83. ;;; Code:
  84. (require 'erc-compat)
  85. (eval-when-compile (require 'cl))
  86. (autoload 'erc-with-buffer "erc" nil nil 'macro)
  87. (autoload 'erc-log "erc" nil nil 'macro)
  88. ;;;; Variables and options
  89. (defvar erc-server-responses (make-hash-table :test #'equal)
  90. "Hashtable mapping server responses to their handler hooks.")
  91. (defstruct (erc-response (:conc-name erc-response.))
  92. (unparsed "" :type string)
  93. (sender "" :type string)
  94. (command "" :type string)
  95. (command-args '() :type list)
  96. (contents "" :type string))
  97. ;;; User data
  98. (defvar erc-server-current-nick nil
  99. "Nickname on the current server.
  100. Use `erc-current-nick' to access this.")
  101. (make-variable-buffer-local 'erc-server-current-nick)
  102. ;;; Server attributes
  103. (defvar erc-server-process nil
  104. "The process object of the corresponding server connection.")
  105. (make-variable-buffer-local 'erc-server-process)
  106. (defvar erc-session-server nil
  107. "The server name used to connect to for this session.")
  108. (make-variable-buffer-local 'erc-session-server)
  109. (defvar erc-session-connector nil
  110. "The function used to connect to this session (nil for the default).")
  111. (make-variable-buffer-local 'erc-session-connector)
  112. (defvar erc-session-port nil
  113. "The port used to connect to.")
  114. (make-variable-buffer-local 'erc-session-port)
  115. (defvar erc-server-announced-name nil
  116. "The name the server announced to use.")
  117. (make-variable-buffer-local 'erc-server-announced-name)
  118. (defvar erc-server-version nil
  119. "The name and version of the server's ircd.")
  120. (make-variable-buffer-local 'erc-server-version)
  121. (defvar erc-server-parameters nil
  122. "Alist listing the supported server parameters.
  123. This is only set if the server sends 005 messages saying what is
  124. supported on the server.
  125. Entries are of the form:
  126. (PARAMETER . VALUE)
  127. or
  128. (PARAMETER) if no value is provided.
  129. Some examples of possible parameters sent by servers:
  130. CHANMODES=b,k,l,imnpst - list of supported channel modes
  131. CHANNELLEN=50 - maximum length of channel names
  132. CHANTYPES=#&!+ - supported channel prefixes
  133. CHARMAPPING=rfc1459 - character mapping used for nickname and channels
  134. KICKLEN=160 - maximum allowed kick message length
  135. MAXBANS=30 - maximum number of bans per channel
  136. MAXCHANNELS=10 - maximum number of channels allowed to join
  137. NETWORK=EFnet - the network identifier
  138. NICKLEN=9 - maximum allowed length of nicknames
  139. PREFIX=(ov)@+ - list of channel modes and the user prefixes if user has mode
  140. RFC2812 - server supports RFC 2812 features
  141. SILENCE=10 - supports the SILENCE command, maximum allowed number of entries
  142. TOPICLEN=160 - maximum allowed topic length
  143. WALLCHOPS - supports sending messages to all operators in a channel")
  144. (make-variable-buffer-local 'erc-server-parameters)
  145. ;;; Server and connection state
  146. (defvar erc-server-ping-timer-alist nil
  147. "Mapping of server buffers to their specific ping timer.")
  148. (defvar erc-server-connected nil
  149. "Non-nil if the current buffer has been used by ERC to establish
  150. an IRC connection.
  151. If you wish to determine whether an IRC connection is currently
  152. active, use the `erc-server-process-alive' function instead.")
  153. (make-variable-buffer-local 'erc-server-connected)
  154. (defvar erc-server-reconnect-count 0
  155. "Number of times we have failed to reconnect to the current server.")
  156. (make-variable-buffer-local 'erc-server-reconnect-count)
  157. (defvar erc-server-quitting nil
  158. "Non-nil if the user requests a quit.")
  159. (make-variable-buffer-local 'erc-server-quitting)
  160. (defvar erc-server-reconnecting nil
  161. "Non-nil if the user requests an explicit reconnect, and the
  162. current IRC process is still alive.")
  163. (make-variable-buffer-local 'erc-server-reconnecting)
  164. (defvar erc-server-timed-out nil
  165. "Non-nil if the IRC server failed to respond to a ping.")
  166. (make-variable-buffer-local 'erc-server-timed-out)
  167. (defvar erc-server-banned nil
  168. "Non-nil if the user is denied access because of a server ban.")
  169. (make-variable-buffer-local 'erc-server-banned)
  170. (defvar erc-server-error-occurred nil
  171. "Non-nil if the user triggers some server error.")
  172. (make-variable-buffer-local 'erc-server-error-occurred)
  173. (defvar erc-server-lines-sent nil
  174. "Line counter.")
  175. (make-variable-buffer-local 'erc-server-lines-sent)
  176. (defvar erc-server-last-peers '(nil . nil)
  177. "Last peers used, both sender and receiver.
  178. Those are used for /MSG destination shortcuts.")
  179. (make-variable-buffer-local 'erc-server-last-peers)
  180. (defvar erc-server-last-sent-time nil
  181. "Time the message was sent.
  182. This is useful for flood protection.")
  183. (make-variable-buffer-local 'erc-server-last-sent-time)
  184. (defvar erc-server-last-ping-time nil
  185. "Time the last ping was sent.
  186. This is useful for flood protection.")
  187. (make-variable-buffer-local 'erc-server-last-ping-time)
  188. (defvar erc-server-last-received-time nil
  189. "Time the last message was received from the server.
  190. This is useful for detecting hung connections.")
  191. (make-variable-buffer-local 'erc-server-last-received-time)
  192. (defvar erc-server-lag nil
  193. "Calculated server lag time in seconds.
  194. This variable is only set in a server buffer.")
  195. (make-variable-buffer-local 'erc-server-lag)
  196. (defvar erc-server-filter-data nil
  197. "The data that arrived from the server
  198. but has not been processed yet.")
  199. (make-variable-buffer-local 'erc-server-filter-data)
  200. (defvar erc-server-duplicates (make-hash-table :test 'equal)
  201. "Internal variable used to track duplicate messages.")
  202. (make-variable-buffer-local 'erc-server-duplicates)
  203. ;; From Circe
  204. (defvar erc-server-processing-p nil
  205. "Non-nil when we're currently processing a message.
  206. When ERC receives a private message, it sets up a new buffer for
  207. this query. These in turn, though, do start flyspell. This
  208. involves starting an external process, in which case Emacs will
  209. wait - and when it waits, it does accept other stuff from, say,
  210. network exceptions. So, if someone sends you two messages
  211. quickly after each other, ispell is started for the first, but
  212. might take long enough for the second message to be processed
  213. first.")
  214. (make-variable-buffer-local 'erc-server-processing-p)
  215. (defvar erc-server-flood-last-message 0
  216. "When we sent the last message.
  217. See `erc-server-flood-margin' for an explanation of the flood
  218. protection algorithm.")
  219. (make-variable-buffer-local 'erc-server-flood-last-message)
  220. (defvar erc-server-flood-queue nil
  221. "The queue of messages waiting to be sent to the server.
  222. See `erc-server-flood-margin' for an explanation of the flood
  223. protection algorithm.")
  224. (make-variable-buffer-local 'erc-server-flood-queue)
  225. (defvar erc-server-flood-timer nil
  226. "The timer to resume sending.")
  227. (make-variable-buffer-local 'erc-server-flood-timer)
  228. ;;; IRC protocol and misc options
  229. (defgroup erc-server nil
  230. "Parameters for dealing with IRC servers."
  231. :group 'erc)
  232. (defcustom erc-server-auto-reconnect t
  233. "Non-nil means that ERC will attempt to reestablish broken connections.
  234. Reconnection will happen automatically for any unexpected disconnection."
  235. :group 'erc-server
  236. :type 'boolean)
  237. (defcustom erc-server-reconnect-attempts 2
  238. "The number of times that ERC will attempt to reestablish a
  239. broken connection, or t to always attempt to reconnect.
  240. This only has an effect if `erc-server-auto-reconnect' is non-nil."
  241. :group 'erc-server
  242. :type '(choice (const :tag "Always reconnect" t)
  243. integer))
  244. (defcustom erc-server-reconnect-timeout 1
  245. "The amount of time, in seconds, that ERC will wait between
  246. successive reconnect attempts.
  247. If a key is pressed while ERC is waiting, it will stop waiting."
  248. :group 'erc-server
  249. :type 'number)
  250. (defcustom erc-split-line-length 440
  251. "*The maximum length of a single message.
  252. If a message exceeds this size, it is broken into multiple ones.
  253. IRC allows for lines up to 512 bytes. Two of them are CR LF.
  254. And a typical message looks like this:
  255. :nicky!uhuser@host212223.dialin.fnordisp.net PRIVMSG #lazybastards :Hello!
  256. You can limit here the maximum length of the \"Hello!\" part.
  257. Good luck."
  258. :type 'integer
  259. :group 'erc-server)
  260. (defcustom erc-coding-system-precedence '(utf-8 undecided)
  261. "List of coding systems to be preferred when receiving a string from the server.
  262. This will only be consulted if the coding system in
  263. `erc-server-coding-system' is `undecided'."
  264. :group 'erc-server
  265. :version "24.1"
  266. :type '(repeat coding-system))
  267. (defcustom erc-server-coding-system (if (and (fboundp 'coding-system-p)
  268. (coding-system-p 'undecided)
  269. (coding-system-p 'utf-8))
  270. '(utf-8 . undecided)
  271. nil)
  272. "The default coding system for incoming and outgoing text.
  273. This is either a coding system, a cons, a function, or nil.
  274. If a cons, the encoding system for outgoing text is in the car
  275. and the decoding system for incoming text is in the cdr. The most
  276. interesting use for this is to put `undecided' in the cdr. This
  277. means that `erc-coding-system-precedence' will be consulted, and the
  278. first match there will be used.
  279. If a function, it is called with the argument `target' and should
  280. return a coding system or a cons as described above.
  281. If you need to send non-ASCII text to people not using a client that
  282. does decoding on its own, you must tell ERC what encoding to use.
  283. Emacs cannot guess it, since it does not know what the people on the
  284. other end of the line are using."
  285. :group 'erc-server
  286. :type '(choice (const :tag "None" nil)
  287. coding-system
  288. (cons (coding-system :tag "encoding" :value utf-8)
  289. (coding-system :tag "decoding" :value undecided))
  290. function))
  291. (defcustom erc-encoding-coding-alist nil
  292. "Alist of target regexp and coding-system pairs to use.
  293. This overrides `erc-server-coding-system' depending on the
  294. current target as returned by `erc-default-target'.
  295. Example: If you know that the channel #linux-ru uses the coding-system
  296. `cyrillic-koi8', then add '(\"#linux-ru\" . cyrillic-koi8) to the
  297. alist."
  298. :group 'erc-server
  299. :type '(repeat (cons (string :tag "Target")
  300. coding-system)))
  301. (defcustom erc-server-connect-function 'open-network-stream
  302. "Function used to initiate a connection.
  303. It should take same arguments as `open-network-stream' does."
  304. :group 'erc-server
  305. :type 'function)
  306. (defcustom erc-server-prevent-duplicates '("301")
  307. "*Either nil or a list of strings.
  308. Each string is a IRC message type, like PRIVMSG or NOTICE.
  309. All Message types in that list of subjected to duplicate prevention."
  310. :type '(choice (const nil) (list string))
  311. :group 'erc-server)
  312. (defcustom erc-server-duplicate-timeout 60
  313. "*The time allowed in seconds between duplicate messages.
  314. If two identical messages arrive within this value of one another, the second
  315. isn't displayed."
  316. :type 'integer
  317. :group 'erc-server)
  318. ;;; Flood-related
  319. ;; Most of this is courtesy of Jorgen Schaefer and Circe
  320. ;; (http://www.nongnu.org/circe)
  321. (defcustom erc-server-flood-margin 10
  322. "*A margin on how much excess data we send.
  323. The flood protection algorithm of ERC works like the one
  324. detailed in RFC 2813, section 5.8 \"Flood control of clients\".
  325. * If `erc-server-flood-last-message' is less than the current
  326. time, set it equal.
  327. * While `erc-server-flood-last-message' is less than
  328. `erc-server-flood-margin' seconds ahead of the current
  329. time, send a message, and increase
  330. `erc-server-flood-last-message' by
  331. `erc-server-flood-penalty' for each message."
  332. :type 'integer
  333. :group 'erc-server)
  334. (defcustom erc-server-flood-penalty 3
  335. "How much we penalize a message.
  336. See `erc-server-flood-margin' for an explanation of the flood
  337. protection algorithm."
  338. :type 'integer
  339. :group 'erc-server)
  340. ;; Ping handling
  341. (defcustom erc-server-send-ping-interval 30
  342. "*Interval of sending pings to the server, in seconds.
  343. If this is set to nil, pinging the server is disabled."
  344. :group 'erc-server
  345. :type '(choice (const :tag "Disabled" nil)
  346. (integer :tag "Seconds")))
  347. (defcustom erc-server-send-ping-timeout 120
  348. "*If the time between ping and response is greater than this, reconnect.
  349. The time is in seconds.
  350. This must be greater than or equal to the value for
  351. `erc-server-send-ping-interval'.
  352. If this is set to nil, never try to reconnect."
  353. :group 'erc-server
  354. :type '(choice (const :tag "Disabled" nil)
  355. (integer :tag "Seconds")))
  356. (defvar erc-server-ping-handler nil
  357. "This variable holds the periodic ping timer.")
  358. (make-variable-buffer-local 'erc-server-ping-handler)
  359. ;;;; Helper functions
  360. ;; From Circe
  361. (defun erc-split-line (longline)
  362. "Return a list of lines which are not too long for IRC.
  363. The length is specified in `erc-split-line-length'.
  364. Currently this is called by `erc-send-input'."
  365. (if (< (length longline)
  366. erc-split-line-length)
  367. (list longline)
  368. (with-temp-buffer
  369. (insert longline)
  370. (let ((fill-column erc-split-line-length))
  371. (fill-region (point-min) (point-max)
  372. nil t))
  373. (split-string (buffer-string) "\n"))))
  374. ;; Used by CTCP functions
  375. (defun erc-upcase-first-word (str)
  376. "Upcase the first word in STR."
  377. (with-temp-buffer
  378. (insert str)
  379. (goto-char (point-min))
  380. (upcase-word 1)
  381. (buffer-string)))
  382. (defun erc-server-setup-periodical-ping (buffer)
  383. "Set up a timer to periodically ping the current server.
  384. The current buffer is given by BUFFER."
  385. (with-current-buffer buffer
  386. (and erc-server-ping-handler (erc-cancel-timer erc-server-ping-handler))
  387. (when erc-server-send-ping-interval
  388. (setq erc-server-ping-handler (run-with-timer
  389. 4 erc-server-send-ping-interval
  390. #'erc-server-send-ping
  391. buffer))
  392. (setq erc-server-ping-timer-alist (cons (cons buffer
  393. erc-server-ping-handler)
  394. erc-server-ping-timer-alist)))))
  395. (defun erc-server-process-alive ()
  396. "Return non-nil when `erc-server-process' is open or running."
  397. (and erc-server-process
  398. (processp erc-server-process)
  399. (memq (process-status erc-server-process) '(run open))))
  400. ;;;; Connecting to a server
  401. (defun erc-server-connect (server port buffer)
  402. "Perform the connection and login using the specified SERVER and PORT.
  403. We will store server variables in the buffer given by BUFFER."
  404. (let ((msg (erc-format-message 'connect ?S server ?p port)))
  405. (message "%s" msg)
  406. (let ((process (funcall erc-server-connect-function
  407. (format "erc-%s-%s" server port)
  408. nil server port)))
  409. (unless (processp process)
  410. (error "Connection attempt failed"))
  411. (message "%s...done" msg)
  412. ;; Misc server variables
  413. (with-current-buffer buffer
  414. (setq erc-server-process process)
  415. (setq erc-server-quitting nil)
  416. (setq erc-server-reconnecting nil)
  417. (setq erc-server-timed-out nil)
  418. (setq erc-server-banned nil)
  419. (setq erc-server-error-occurred nil)
  420. (let ((time (erc-current-time)))
  421. (setq erc-server-last-sent-time time)
  422. (setq erc-server-last-ping-time time)
  423. (setq erc-server-last-received-time time))
  424. (setq erc-server-lines-sent 0)
  425. ;; last peers (sender and receiver)
  426. (setq erc-server-last-peers '(nil . nil)))
  427. ;; we do our own encoding and decoding
  428. (when (fboundp 'set-process-coding-system)
  429. (set-process-coding-system process 'raw-text))
  430. ;; process handlers
  431. (set-process-sentinel process 'erc-process-sentinel)
  432. (set-process-filter process 'erc-server-filter-function)
  433. (set-process-buffer process buffer)))
  434. (erc-log "\n\n\n********************************************\n")
  435. (message "%s" (erc-format-message
  436. 'login ?n
  437. (with-current-buffer buffer (erc-current-nick))))
  438. ;; wait with script loading until we receive a confirmation (first
  439. ;; MOTD line)
  440. (if (eq erc-server-connect-function 'open-network-stream-nowait)
  441. ;; it's a bit unclear otherwise that it's attempting to establish a
  442. ;; connection
  443. (erc-display-message nil nil buffer "Opening connection..\n")
  444. (erc-login)))
  445. (defun erc-server-reconnect ()
  446. "Reestablish the current IRC connection.
  447. Make sure you are in an ERC buffer when running this."
  448. (let ((buffer (erc-server-buffer)))
  449. (unless (buffer-live-p buffer)
  450. (if (eq major-mode 'erc-mode)
  451. (setq buffer (current-buffer))
  452. (error "Reconnect must be run from an ERC buffer")))
  453. (with-current-buffer buffer
  454. (erc-update-mode-line)
  455. (erc-set-active-buffer (current-buffer))
  456. (setq erc-server-last-sent-time 0)
  457. (setq erc-server-lines-sent 0)
  458. (let ((erc-server-connect-function (or erc-session-connector
  459. 'open-network-stream)))
  460. (erc-open erc-session-server erc-session-port erc-server-current-nick
  461. erc-session-user-full-name t erc-session-password)))))
  462. (defun erc-server-filter-function (process string)
  463. "The process filter for the ERC server."
  464. (with-current-buffer (process-buffer process)
  465. (setq erc-server-last-received-time (erc-current-time))
  466. ;; If you think this is written in a weird way - please refer to the
  467. ;; docstring of `erc-server-processing-p'
  468. (if erc-server-processing-p
  469. (setq erc-server-filter-data
  470. (if erc-server-filter-data
  471. (concat erc-server-filter-data string)
  472. string))
  473. ;; This will be true even if another process is spawned!
  474. (let ((erc-server-processing-p t))
  475. (setq erc-server-filter-data (if erc-server-filter-data
  476. (concat erc-server-filter-data
  477. string)
  478. string))
  479. (while (and erc-server-filter-data
  480. (string-match "[\n\r]+" erc-server-filter-data))
  481. (let ((line (substring erc-server-filter-data
  482. 0 (match-beginning 0))))
  483. (setq erc-server-filter-data
  484. (if (= (match-end 0)
  485. (length erc-server-filter-data))
  486. nil
  487. (substring erc-server-filter-data
  488. (match-end 0))))
  489. (erc-log-irc-protocol line nil)
  490. (erc-parse-server-response process line)))))))
  491. (defsubst erc-server-reconnect-p (event)
  492. "Return non-nil if ERC should attempt to reconnect automatically.
  493. EVENT is the message received from the closed connection process."
  494. (or erc-server-reconnecting
  495. (and erc-server-auto-reconnect
  496. (not erc-server-banned)
  497. (not erc-server-error-occurred)
  498. ;; make sure we don't infinitely try to reconnect, unless the
  499. ;; user wants that
  500. (or (eq erc-server-reconnect-attempts t)
  501. (and (integerp erc-server-reconnect-attempts)
  502. (< erc-server-reconnect-count
  503. erc-server-reconnect-attempts)))
  504. (or erc-server-timed-out
  505. (not (string-match "^deleted" event)))
  506. ;; open-network-stream-nowait error for connection refused
  507. (not (string-match "^failed with code 111" event)))))
  508. (defun erc-process-sentinel-2 (event buffer)
  509. "Called when `erc-process-sentinel-1' has detected an unexpected disconnect."
  510. (if (not (buffer-live-p buffer))
  511. (erc-update-mode-line)
  512. (with-current-buffer buffer
  513. (let ((reconnect-p (erc-server-reconnect-p event)))
  514. (erc-display-message nil 'error (current-buffer)
  515. (if reconnect-p 'disconnected
  516. 'disconnected-noreconnect))
  517. (if (not reconnect-p)
  518. ;; terminate, do not reconnect
  519. (progn
  520. (erc-display-message nil 'error (current-buffer)
  521. 'terminated ?e event)
  522. ;; Update mode line indicators
  523. (erc-update-mode-line)
  524. (set-buffer-modified-p nil))
  525. ;; reconnect
  526. (condition-case err
  527. (progn
  528. (setq erc-server-reconnecting nil)
  529. (erc-server-reconnect)
  530. (setq erc-server-reconnect-count 0))
  531. (error (when (buffer-live-p buffer)
  532. (set-buffer buffer)
  533. (if (integerp erc-server-reconnect-attempts)
  534. (setq erc-server-reconnect-count
  535. (1+ erc-server-reconnect-count))
  536. (message "%s ... %s"
  537. "Reconnecting until we succeed"
  538. "kill the ERC server buffer to stop"))
  539. (if (numberp erc-server-reconnect-timeout)
  540. (run-at-time erc-server-reconnect-timeout nil
  541. #'erc-process-sentinel-2
  542. event buffer)
  543. (error (concat "`erc-server-reconnect-timeout`"
  544. " must be a number")))))))))))
  545. (defun erc-process-sentinel-1 (event buffer)
  546. "Called when `erc-process-sentinel' has decided that we're disconnecting.
  547. Determine whether user has quit or whether erc has been terminated.
  548. Conditionally try to reconnect and take appropriate action."
  549. (with-current-buffer buffer
  550. (if erc-server-quitting
  551. ;; normal quit
  552. (progn
  553. (erc-display-message nil 'error (current-buffer) 'finished)
  554. ;; Update mode line indicators
  555. (erc-update-mode-line)
  556. ;; Kill server buffer if user wants it
  557. (set-buffer-modified-p nil)
  558. (when erc-kill-server-buffer-on-quit
  559. (kill-buffer (current-buffer))))
  560. ;; unexpected disconnect
  561. (erc-process-sentinel-2 event buffer))))
  562. (defun erc-process-sentinel (cproc event)
  563. "Sentinel function for ERC process."
  564. (let ((buf (process-buffer cproc)))
  565. (when (buffer-live-p buf)
  566. (with-current-buffer buf
  567. (erc-log (format
  568. "SENTINEL: proc: %S status: %S event: %S (quitting: %S)"
  569. cproc (process-status cproc) event erc-server-quitting))
  570. (if (string-match "^open" event)
  571. ;; newly opened connection (no wait)
  572. (erc-login)
  573. ;; assume event is 'failed
  574. (erc-with-all-buffers-of-server cproc nil
  575. (setq erc-server-connected nil))
  576. (when erc-server-ping-handler
  577. (progn (erc-cancel-timer erc-server-ping-handler)
  578. (setq erc-server-ping-handler nil)))
  579. (run-hook-with-args 'erc-disconnected-hook
  580. (erc-current-nick) (system-name) "")
  581. ;; Remove the prompt
  582. (goto-char (or (marker-position erc-input-marker) (point-max)))
  583. (forward-line 0)
  584. (erc-remove-text-properties-region (point) (point-max))
  585. (delete-region (point) (point-max))
  586. ;; Decide what to do with the buffer
  587. ;; Restart if disconnected
  588. (erc-process-sentinel-1 event buf))))))
  589. ;;;; Sending messages
  590. (defun erc-coding-system-for-target (target)
  591. "Return the coding system or cons cell appropriate for TARGET.
  592. This is determined via `erc-encoding-coding-alist' or
  593. `erc-server-coding-system'."
  594. (unless target (setq target (erc-default-target)))
  595. (or (when target
  596. (let ((case-fold-search t))
  597. (catch 'match
  598. (dolist (pat erc-encoding-coding-alist)
  599. (when (string-match (car pat) target)
  600. (throw 'match (cdr pat)))))))
  601. (and (functionp erc-server-coding-system)
  602. (funcall erc-server-coding-system target))
  603. erc-server-coding-system))
  604. (defun erc-decode-string-from-target (str target)
  605. "Decode STR as appropriate for TARGET.
  606. This is indicated by `erc-encoding-coding-alist', defaulting to the value of
  607. `erc-server-coding-system'."
  608. (unless (stringp str)
  609. (setq str ""))
  610. (let ((coding (erc-coding-system-for-target target)))
  611. (when (consp coding)
  612. (setq coding (cdr coding)))
  613. (when (eq coding 'undecided)
  614. (let ((codings (detect-coding-string str))
  615. (precedence erc-coding-system-precedence))
  616. (while (and precedence
  617. (not (memq (car precedence) codings)))
  618. (pop precedence))
  619. (when precedence
  620. (setq coding (car precedence)))))
  621. (erc-decode-coding-string str coding)))
  622. ;; proposed name, not used by anything yet
  623. (defun erc-send-line (text display-fn)
  624. "Send TEXT to the current server. Wrapping and flood control apply.
  625. Use DISPLAY-FN to show the results."
  626. (mapc (lambda (line)
  627. (erc-server-send line)
  628. (funcall display-fn))
  629. (erc-split-line text)))
  630. ;; From Circe, with modifications
  631. (defun erc-server-send (string &optional forcep target)
  632. "Send STRING to the current server.
  633. If FORCEP is non-nil, no flood protection is done - the string is
  634. sent directly. This might cause the messages to arrive in a wrong
  635. order.
  636. If TARGET is specified, look up encoding information for that
  637. channel in `erc-encoding-coding-alist' or
  638. `erc-server-coding-system'.
  639. See `erc-server-flood-margin' for an explanation of the flood
  640. protection algorithm."
  641. (erc-log (concat "erc-server-send: " string "(" (buffer-name) ")"))
  642. (setq erc-server-last-sent-time (erc-current-time))
  643. (let ((encoding (erc-coding-system-for-target target)))
  644. (when (consp encoding)
  645. (setq encoding (car encoding)))
  646. (if (erc-server-process-alive)
  647. (erc-with-server-buffer
  648. (let ((str (concat string "\r\n")))
  649. (if forcep
  650. (progn
  651. (setq erc-server-flood-last-message
  652. (+ erc-server-flood-penalty
  653. erc-server-flood-last-message))
  654. (erc-log-irc-protocol str 'outbound)
  655. (condition-case err
  656. (progn
  657. ;; Set encoding just before sending the string
  658. (when (fboundp 'set-process-coding-system)
  659. (set-process-coding-system erc-server-process
  660. 'raw-text encoding))
  661. (process-send-string erc-server-process str))
  662. ;; See `erc-server-send-queue' for full
  663. ;; explanation of why we need this condition-case
  664. (error nil)))
  665. (setq erc-server-flood-queue
  666. (append erc-server-flood-queue
  667. (list (cons str encoding))))
  668. (erc-server-send-queue (current-buffer))))
  669. t)
  670. (message "ERC: No process running")
  671. nil)))
  672. (defun erc-server-send-ping (buf)
  673. "Send a ping to the IRC server buffer in BUF.
  674. Additionally, detect whether the IRC process has hung."
  675. (if (buffer-live-p buf)
  676. (with-current-buffer buf
  677. (if (and erc-server-send-ping-timeout
  678. (>
  679. (erc-time-diff (erc-current-time)
  680. erc-server-last-received-time)
  681. erc-server-send-ping-timeout))
  682. (progn
  683. ;; if the process is hung, kill it
  684. (setq erc-server-timed-out t)
  685. (delete-process erc-server-process))
  686. (erc-server-send (format "PING %.0f" (erc-current-time)))))
  687. ;; remove timer if the server buffer has been killed
  688. (let ((timer (assq buf erc-server-ping-timer-alist)))
  689. (when timer
  690. (erc-cancel-timer (cdr timer))
  691. (setcdr timer nil)))))
  692. ;; From Circe
  693. (defun erc-server-send-queue (buffer)
  694. "Send messages in `erc-server-flood-queue'.
  695. See `erc-server-flood-margin' for an explanation of the flood
  696. protection algorithm."
  697. (with-current-buffer buffer
  698. (let ((now (erc-current-time)))
  699. (when erc-server-flood-timer
  700. (erc-cancel-timer erc-server-flood-timer)
  701. (setq erc-server-flood-timer nil))
  702. (when (< erc-server-flood-last-message
  703. now)
  704. (setq erc-server-flood-last-message now))
  705. (while (and erc-server-flood-queue
  706. (< erc-server-flood-last-message
  707. (+ now erc-server-flood-margin)))
  708. (let ((msg (caar erc-server-flood-queue))
  709. (encoding (cdar erc-server-flood-queue)))
  710. (setq erc-server-flood-queue (cdr erc-server-flood-queue)
  711. erc-server-flood-last-message
  712. (+ erc-server-flood-last-message
  713. erc-server-flood-penalty))
  714. (erc-log-irc-protocol msg 'outbound)
  715. (erc-log (concat "erc-server-send-queue: "
  716. msg "(" (buffer-name buffer) ")"))
  717. (when (erc-server-process-alive)
  718. (condition-case err
  719. ;; Set encoding just before sending the string
  720. (progn
  721. (when (fboundp 'set-process-coding-system)
  722. (set-process-coding-system erc-server-process
  723. 'raw-text encoding))
  724. (process-send-string erc-server-process msg))
  725. ;; Sometimes the send can occur while the process is
  726. ;; being killed, which results in a weird SIGPIPE error.
  727. ;; Catch this and ignore it.
  728. (error nil)))))
  729. (when erc-server-flood-queue
  730. (setq erc-server-flood-timer
  731. (run-at-time (+ 0.2 erc-server-flood-penalty)
  732. nil #'erc-server-send-queue buffer))))))
  733. (defun erc-message (message-command line &optional force)
  734. "Send LINE to the server as a privmsg or a notice.
  735. MESSAGE-COMMAND should be either \"PRIVMSG\" or \"NOTICE\".
  736. If the target is \",\", the last person you've got a message from will
  737. be used. If the target is \".\", the last person you've sent a message
  738. to will be used."
  739. (cond
  740. ((string-match "^\\s-*\\(\\S-+\\) ?\\(.*\\)" line)
  741. (let ((tgt (match-string 1 line))
  742. (s (match-string 2 line)))
  743. (erc-log (format "cmd: MSG(%s): [%s] %s" message-command tgt s))
  744. (cond
  745. ((string= tgt ",")
  746. (if (car erc-server-last-peers)
  747. (setq tgt (car erc-server-last-peers))
  748. (setq tgt nil)))
  749. ((string= tgt ".")
  750. (if (cdr erc-server-last-peers)
  751. (setq tgt (cdr erc-server-last-peers))
  752. (setq tgt nil))))
  753. (cond
  754. (tgt
  755. (setcdr erc-server-last-peers tgt)
  756. (erc-server-send (format "%s %s :%s" message-command tgt s)
  757. force))
  758. (t
  759. (erc-display-message nil 'error (current-buffer) 'no-target))))
  760. t)
  761. (t nil)))
  762. ;;; CTCP
  763. (defun erc-send-ctcp-message (tgt l &optional force)
  764. "Send CTCP message L to TGT.
  765. If TGT is nil the message is not sent.
  766. The command must contain neither a prefix nor a trailing `\\n'.
  767. See also `erc-server-send'."
  768. (let ((l (erc-upcase-first-word l)))
  769. (cond
  770. (tgt
  771. (erc-log (format "erc-send-CTCP-message: [%s] %s" tgt l))
  772. (erc-server-send (format "PRIVMSG %s :\C-a%s\C-a" tgt l)
  773. force)))))
  774. (defun erc-send-ctcp-notice (tgt l &optional force)
  775. "Send CTCP notice L to TGT.
  776. If TGT is nil the message is not sent.
  777. The command must contain neither a prefix nor a trailing `\\n'.
  778. See also `erc-server-send'."
  779. (let ((l (erc-upcase-first-word l)))
  780. (cond
  781. (tgt
  782. (erc-log (format "erc-send-CTCP-notice: [%s] %s" tgt l))
  783. (erc-server-send (format "NOTICE %s :\C-a%s\C-a" tgt l)
  784. force)))))
  785. ;;;; Handling responses
  786. (defun erc-parse-server-response (proc string)
  787. "Parse and act upon a complete line from an IRC server.
  788. PROC is the process (connection) from which STRING was received.
  789. PROCs `process-buffer' is `current-buffer' when this function is called."
  790. (unless (string= string "") ;; Ignore empty strings
  791. (save-match-data
  792. (let ((posn (if (eq (aref string 0) ?:)
  793. (string-match " " string)
  794. 0))
  795. (msg (make-erc-response :unparsed string)))
  796. (setf (erc-response.sender msg)
  797. (if (eq posn 0)
  798. erc-session-server
  799. (substring string 1 posn)))
  800. (setf (erc-response.command msg)
  801. (let* ((bposn (string-match "[^ \n]" string posn))
  802. (eposn (string-match " " string bposn)))
  803. (setq posn (and eposn
  804. (string-match "[^ \n]" string eposn)))
  805. (substring string bposn eposn)))
  806. (while (and posn
  807. (not (eq (aref string posn) ?:)))
  808. (push (let* ((bposn posn)
  809. (eposn (string-match " " string bposn)))
  810. (setq posn (and eposn
  811. (string-match "[^ \n]" string eposn)))
  812. (substring string bposn eposn))
  813. (erc-response.command-args msg)))
  814. (when posn
  815. (let ((str (substring string (1+ posn))))
  816. (push str (erc-response.command-args msg))))
  817. (setf (erc-response.contents msg)
  818. (first (erc-response.command-args msg)))
  819. (setf (erc-response.command-args msg)
  820. (nreverse (erc-response.command-args msg)))
  821. (erc-decode-parsed-server-response msg)
  822. (erc-handle-parsed-server-response proc msg)))))
  823. (defun erc-decode-parsed-server-response (parsed-response)
  824. "Decode a pre-parsed PARSED-RESPONSE before it can be handled.
  825. If there is a channel name in `erc-response.command-args', decode
  826. `erc-response' according to this channel name and
  827. `erc-encoding-coding-alist', or use `erc-server-coding-system'
  828. for decoding."
  829. (let ((args (erc-response.command-args parsed-response))
  830. (decode-target nil)
  831. (decoded-args ()))
  832. (dolist (arg args nil)
  833. (when (string-match "^[#&].*" arg)
  834. (setq decode-target arg)))
  835. (when (stringp decode-target)
  836. (setq decode-target (erc-decode-string-from-target decode-target nil)))
  837. (setf (erc-response.unparsed parsed-response)
  838. (erc-decode-string-from-target
  839. (erc-response.unparsed parsed-response)
  840. decode-target))
  841. (setf (erc-response.sender parsed-response)
  842. (erc-decode-string-from-target
  843. (erc-response.sender parsed-response)
  844. decode-target))
  845. (setf (erc-response.command parsed-response)
  846. (erc-decode-string-from-target
  847. (erc-response.command parsed-response)
  848. decode-target))
  849. (dolist (arg (nreverse args) nil)
  850. (push (erc-decode-string-from-target arg decode-target)
  851. decoded-args))
  852. (setf (erc-response.command-args parsed-response) decoded-args)
  853. (setf (erc-response.contents parsed-response)
  854. (erc-decode-string-from-target
  855. (erc-response.contents parsed-response)
  856. decode-target))))
  857. (defun erc-handle-parsed-server-response (process parsed-response)
  858. "Handle a pre-parsed PARSED-RESPONSE from PROCESS.
  859. Hands off to helper functions via `erc-call-hooks'."
  860. (if (member (erc-response.command parsed-response)
  861. erc-server-prevent-duplicates)
  862. (let ((m (erc-response.unparsed parsed-response)))
  863. ;; duplicate suppression
  864. (if (< (or (gethash m erc-server-duplicates) 0)
  865. (- (erc-current-time) erc-server-duplicate-timeout))
  866. (erc-call-hooks process parsed-response))
  867. (puthash m (erc-current-time) erc-server-duplicates))
  868. ;; Hand off to the relevant handler.
  869. (erc-call-hooks process parsed-response)))
  870. (defun erc-get-hook (command)
  871. "Return the hook variable associated with COMMAND.
  872. See also `erc-server-responses'."
  873. (gethash (format (if (numberp command) "%03i" "%s") command)
  874. erc-server-responses))
  875. (defun erc-call-hooks (process message)
  876. "Call hooks associated with MESSAGE in PROCESS.
  877. Finds hooks by looking in the `erc-server-responses' hashtable."
  878. (let ((hook (or (erc-get-hook (erc-response.command message))
  879. 'erc-default-server-functions)))
  880. (run-hook-with-args-until-success hook process message)
  881. (erc-with-server-buffer
  882. (run-hook-with-args 'erc-timer-hook (erc-current-time)))))
  883. (add-hook 'erc-default-server-functions 'erc-handle-unknown-server-response)
  884. (defun erc-handle-unknown-server-response (proc parsed)
  885. "Display unknown server response's message."
  886. (let ((line (concat (erc-response.sender parsed)
  887. " "
  888. (erc-response.command parsed)
  889. " "
  890. (mapconcat 'identity (erc-response.command-args parsed)
  891. " "))))
  892. (erc-display-message parsed 'notice proc line)))
  893. (put 'define-erc-response-handler 'edebug-form-spec
  894. '(&define :name erc-response-handler
  895. (name &rest name)
  896. &optional sexp sexp def-body))
  897. (defmacro* define-erc-response-handler ((name &rest aliases)
  898. &optional extra-fn-doc extra-var-doc
  899. &rest fn-body)
  900. "Define an ERC handler hook/function pair.
  901. NAME is the response name as sent by the server (see the IRC RFC for
  902. meanings).
  903. This creates:
  904. - a hook variable `erc-server-NAME-functions' initialized to `erc-server-NAME'.
  905. - a function `erc-server-NAME' with body FN-BODY.
  906. If ALIASES is non-nil, each alias in ALIASES is `defalias'ed to
  907. `erc-server-NAME'.
  908. Alias hook variables are created as `erc-server-ALIAS-functions' and
  909. initialized to the same default value as `erc-server-NAME-functions'.
  910. FN-BODY is the body of `erc-server-NAME' it may refer to the two
  911. function arguments PROC and PARSED.
  912. If EXTRA-FN-DOC is non-nil, it is inserted at the beginning of the
  913. defined function's docstring.
  914. If EXTRA-VAR-DOC is non-nil, it is inserted at the beginning of the
  915. defined variable's docstring.
  916. As an example:
  917. (define-erc-response-handler (311 WHOIS WI)
  918. \"Some non-generic function documentation.\"
  919. \"Some non-generic variable documentation.\"
  920. (do-stuff-with-whois proc parsed))
  921. Would expand to:
  922. (prog2
  923. (defvar erc-server-311-functions 'erc-server-311
  924. \"Some non-generic variable documentation.
  925. Hook called upon receiving a 311 server response.
  926. Each function is called with two arguments, the process associated
  927. with the response and the parsed response.
  928. See also `erc-server-311'.\")
  929. (defun erc-server-311 (proc parsed)
  930. \"Some non-generic function documentation.
  931. Handler for a 311 server response.
  932. PROC is the server process which returned the response.
  933. PARSED is the actual response as an `erc-response' struct.
  934. If you want to add responses don't modify this function, but rather
  935. add things to `erc-server-311-functions' instead.\"
  936. (do-stuff-with-whois proc parsed))
  937. (puthash \"311\" 'erc-server-311-functions erc-server-responses)
  938. (puthash \"WHOIS\" 'erc-server-WHOIS-functions erc-server-responses)
  939. (puthash \"WI\" 'erc-server-WI-functions erc-server-responses)
  940. (defalias 'erc-server-WHOIS 'erc-server-311)
  941. (defvar erc-server-WHOIS-functions 'erc-server-311
  942. \"Some non-generic variable documentation.
  943. Hook called upon receiving a WHOIS server response.
  944. Each function is called with two arguments, the process associated
  945. with the response and the parsed response. If the function returns
  946. non-nil, stop processing the hook. Otherwise, continue.
  947. See also `erc-server-311'.\")
  948. (defalias 'erc-server-WI 'erc-server-311)
  949. (defvar erc-server-WI-functions 'erc-server-311
  950. \"Some non-generic variable documentation.
  951. Hook called upon receiving a WI server response.
  952. Each function is called with two arguments, the process associated
  953. with the response and the parsed response. If the function returns
  954. non-nil, stop processing the hook. Otherwise, continue.
  955. See also `erc-server-311'.\"))
  956. \(fn (NAME &rest ALIASES) &optional EXTRA-FN-DOC EXTRA-VAR-DOC &rest FN-BODY)"
  957. (if (numberp name) (setq name (intern (format "%03i" name))))
  958. (setq aliases (mapcar (lambda (a)
  959. (if (numberp a)
  960. (format "%03i" a)
  961. a))
  962. aliases))
  963. (let* ((hook-name (intern (format "erc-server-%s-functions" name)))
  964. (fn-name (intern (format "erc-server-%s" name)))
  965. (hook-doc (format "%sHook called upon receiving a %%s server response.
  966. Each function is called with two arguments, the process associated
  967. with the response and the parsed response. If the function returns
  968. non-nil, stop processing the hook. Otherwise, continue.
  969. See also `%s'."
  970. (if extra-var-doc
  971. (concat extra-var-doc "\n\n")
  972. "")
  973. fn-name))
  974. (fn-doc (format "%sHandler for a %s server response.
  975. PROC is the server process which returned the response.
  976. PARSED is the actual response as an `erc-response' struct.
  977. If you want to add responses don't modify this function, but rather
  978. add things to `%s' instead."
  979. (if extra-fn-doc
  980. (concat extra-fn-doc "\n\n")
  981. "")
  982. name hook-name))
  983. (fn-alternates
  984. (loop for alias in aliases
  985. collect (intern (format "erc-server-%s" alias))))
  986. (var-alternates
  987. (loop for alias in aliases
  988. collect (intern (format "erc-server-%s-functions" alias)))))
  989. `(prog2
  990. ;; Normal hook variable.
  991. (defvar ,hook-name ',fn-name ,(format hook-doc name))
  992. ;; Handler function
  993. (defun ,fn-name (proc parsed)
  994. ,fn-doc
  995. ,@fn-body)
  996. ;; Make find-function and find-variable find them
  997. (put ',fn-name 'definition-name ',name)
  998. (put ',hook-name 'definition-name ',name)
  999. ;; Hashtable map of responses to hook variables
  1000. ,@(loop for response in (cons name aliases)
  1001. for var in (cons hook-name var-alternates)
  1002. collect `(puthash ,(format "%s" response) ',var
  1003. erc-server-responses))
  1004. ;; Alternates.
  1005. ;; Functions are defaliased, hook variables are defvared so we
  1006. ;; can add hooks to one alias, but not another.
  1007. ,@(loop for fn in fn-alternates
  1008. for var in var-alternates
  1009. for a in aliases
  1010. nconc (list `(defalias ',fn ',fn-name)
  1011. `(defvar ,var ',fn-name ,(format hook-doc a))
  1012. `(put ',var 'definition-name ',hook-name))))))
  1013. (define-erc-response-handler (ERROR)
  1014. "Handle an ERROR command from the server." nil
  1015. (setq erc-server-error-occurred t)
  1016. (erc-display-message
  1017. parsed 'error nil 'ERROR
  1018. ?s (erc-response.sender parsed) ?c (erc-response.contents parsed)))
  1019. (define-erc-response-handler (INVITE)
  1020. "Handle invitation messages."
  1021. nil
  1022. (let ((target (first (erc-response.command-args parsed)))
  1023. (chnl (erc-response.contents parsed)))
  1024. (multiple-value-bind (nick login host)
  1025. (values-list (erc-parse-user (erc-response.sender parsed)))
  1026. (setq erc-invitation chnl)
  1027. (when (string= target (erc-current-nick))
  1028. (erc-display-message
  1029. parsed 'notice 'active
  1030. 'INVITE ?n nick ?u login ?h host ?c chnl)))))
  1031. (define-erc-response-handler (JOIN)
  1032. "Handle join messages."
  1033. nil
  1034. (let ((chnl (erc-response.contents parsed))
  1035. (buffer nil))
  1036. (multiple-value-bind (nick login host)
  1037. (values-list (erc-parse-user (erc-response.sender parsed)))
  1038. ;; strip the stupid combined JOIN facility (IRC 2.9)
  1039. (if (string-match "^\\(.*\\)?\^g.*$" chnl)
  1040. (setq chnl (match-string 1 chnl)))
  1041. (save-excursion
  1042. (let* ((str (cond
  1043. ;; If I have joined a channel
  1044. ((erc-current-nick-p nick)
  1045. (setq buffer (erc-open erc-session-server erc-session-port
  1046. nick erc-session-user-full-name
  1047. nil nil
  1048. (list chnl) chnl
  1049. erc-server-process))
  1050. (when buffer
  1051. (set-buffer buffer)
  1052. (erc-add-default-channel chnl)
  1053. (erc-server-send (format "MODE %s" chnl)))
  1054. (erc-with-buffer (chnl proc)
  1055. (erc-channel-begin-receiving-names))
  1056. (erc-update-mode-line)
  1057. (run-hooks 'erc-join-hook)
  1058. (erc-make-notice
  1059. (erc-format-message 'JOIN-you ?c chnl)))
  1060. (t
  1061. (setq buffer (erc-get-buffer chnl proc))
  1062. (erc-make-notice
  1063. (erc-format-message
  1064. 'JOIN ?n nick ?u login ?h host ?c chnl))))))
  1065. (when buffer (set-buffer buffer))
  1066. (erc-update-channel-member chnl nick nick t nil nil host login)
  1067. ;; on join, we want to stay in the new channel buffer
  1068. ;;(set-buffer ob)
  1069. (erc-display-message parsed nil buffer str))))))
  1070. (define-erc-response-handler (KICK)
  1071. "Handle kick messages received from the server." nil
  1072. (let* ((ch (first (erc-response.command-args parsed)))
  1073. (tgt (second (erc-response.command-args parsed)))
  1074. (reason (erc-trim-string (erc-response.contents parsed)))
  1075. (buffer (erc-get-buffer ch proc)))
  1076. (multiple-value-bind (nick login host)
  1077. (values-list (erc-parse-user (erc-response.sender parsed)))
  1078. (erc-remove-channel-member buffer tgt)
  1079. (cond
  1080. ((string= tgt (erc-current-nick))
  1081. (erc-display-message
  1082. parsed 'notice buffer
  1083. 'KICK-you ?n nick ?u login ?h host ?c ch ?r reason)
  1084. (run-hook-with-args 'erc-kick-hook buffer)
  1085. (erc-with-buffer
  1086. (buffer)
  1087. (erc-remove-channel-users))
  1088. (erc-delete-default-channel ch buffer)
  1089. (erc-update-mode-line buffer))
  1090. ((string= nick (erc-current-nick))
  1091. (erc-display-message
  1092. parsed 'notice buffer
  1093. 'KICK-by-you ?k tgt ?c ch ?r reason))
  1094. (t (erc-display-message
  1095. parsed 'notice buffer
  1096. 'KICK ?k tgt ?n nick ?u login ?h host ?c ch ?r reason))))))
  1097. (define-erc-response-handler (MODE)
  1098. "Handle server mode changes." nil
  1099. (let ((tgt (first (erc-response.command-args parsed)))
  1100. (mode (mapconcat 'identity (cdr (erc-response.command-args parsed))
  1101. " ")))
  1102. (multiple-value-bind (nick login host)
  1103. (values-list (erc-parse-user (erc-response.sender parsed)))
  1104. (erc-log (format "MODE: %s -> %s: %s" nick tgt mode))
  1105. ;; dirty hack
  1106. (let ((buf (cond ((erc-channel-p tgt)
  1107. (erc-get-buffer tgt proc))
  1108. ((string= tgt (erc-current-nick)) nil)
  1109. ((erc-active-buffer) (erc-active-buffer))
  1110. (t (erc-get-buffer tgt)))))
  1111. (with-current-buffer (or buf
  1112. (current-buffer))
  1113. (erc-update-modes tgt mode nick host login))
  1114. (if (or (string= login "") (string= host ""))
  1115. (erc-display-message parsed 'notice buf
  1116. 'MODE-nick ?n nick
  1117. ?t tgt ?m mode)
  1118. (erc-display-message parsed 'notice buf
  1119. 'MODE ?n nick ?u login
  1120. ?h host ?t tgt ?m mode)))
  1121. (erc-banlist-update proc parsed))))
  1122. (define-erc-response-handler (NICK)
  1123. "Handle nick change messages." nil
  1124. (let ((nn (erc-response.contents parsed))
  1125. bufs)
  1126. (multiple-value-bind (nick login host)
  1127. (values-list (erc-parse-user (erc-response.sender parsed)))
  1128. (setq bufs (erc-buffer-list-with-nick nick proc))
  1129. (erc-log (format "NICK: %s -> %s" nick nn))
  1130. ;; if we had a query with this user, make sure future messages will be
  1131. ;; sent to the correct nick. also add to bufs, since the user will want
  1132. ;; to see the nick change in the query, and if it's a newly begun query,
  1133. ;; erc-channel-users won't contain it
  1134. (erc-buffer-filter
  1135. (lambda ()
  1136. (when (equal (erc-default-target) nick)
  1137. (setq erc-default-recipients
  1138. (cons nn (cdr erc-default-recipients)))
  1139. (rename-buffer nn)
  1140. (erc-update-mode-line)
  1141. (add-to-list 'bufs (current-buffer)))))
  1142. (erc-update-user-nick nick nn host nil nil login)
  1143. (cond
  1144. ((string= nick (erc-current-nick))
  1145. (add-to-list 'bufs (erc-server-buffer))
  1146. (erc-set-current-nick nn)
  1147. (erc-update-mode-line)
  1148. (setq erc-nick-change-attempt-count 0)
  1149. (setq erc-default-nicks (if (consp erc-nick) erc-nick (list erc-nick)))
  1150. (erc-display-message
  1151. parsed 'notice bufs
  1152. 'NICK-you ?n nick ?N nn)
  1153. (run-hook-with-args 'erc-nick-changed-functions nn nick))
  1154. (t
  1155. (erc-handle-user-status-change 'nick (list nick login host) (list nn))
  1156. (erc-display-message parsed 'notice bufs 'NICK ?n nick
  1157. ?u login ?h host ?N nn))))))
  1158. (define-erc-response-handler (PART)
  1159. "Handle part messages." nil
  1160. (let* ((chnl (first (erc-response.command-args parsed)))
  1161. (reason (erc-trim-string (erc-response.contents parsed)))
  1162. (buffer (erc-get-buffer chnl proc)))
  1163. (multiple-value-bind (nick login host)
  1164. (values-list (erc-parse-user (erc-response.sender parsed)))
  1165. (erc-remove-channel-member buffer nick)
  1166. (erc-display-message parsed 'notice buffer
  1167. 'PART ?n nick ?u login
  1168. ?h host ?c chnl ?r (or reason ""))
  1169. (when (string= nick (erc-current-nick))
  1170. (run-hook-with-args 'erc-part-hook buffer)
  1171. (erc-with-buffer
  1172. (buffer)
  1173. (erc-remove-channel-users))
  1174. (erc-delete-default-channel chnl buffer)
  1175. (erc-update-mode-line buffer)
  1176. (when erc-kill-buffer-on-part
  1177. (kill-buffer buffer))))))
  1178. (define-erc-response-handler (PING)
  1179. "Handle ping messages." nil
  1180. (let ((pinger (first (erc-response.command-args parsed))))
  1181. (erc-log (format "PING: %s" pinger))
  1182. ;; ping response to the server MUST be forced, or you can lose big
  1183. (erc-server-send (format "PONG :%s" pinger) t)
  1184. (when erc-verbose-server-ping
  1185. (erc-display-message
  1186. parsed 'error proc
  1187. 'PING ?s (erc-time-diff erc-server-last-ping-time (erc-current-time))))
  1188. (setq erc-server-last-ping-time (erc-current-time))))
  1189. (define-erc-response-handler (PONG)
  1190. "Handle pong messages." nil
  1191. (let ((time (string-to-number (erc-response.contents parsed))))
  1192. (when (> time 0)
  1193. (setq erc-server-lag (erc-time-diff time (erc-current-time)))
  1194. (when erc-verbose-server-ping
  1195. (erc-display-message
  1196. parsed 'notice proc 'PONG
  1197. ?h (first (erc-response.command-args parsed)) ?i erc-server-lag
  1198. ?s (if (/= erc-server-lag 1) "s" "")))
  1199. (erc-update-mode-line))))
  1200. (define-erc-response-handler (PRIVMSG NOTICE)
  1201. "Handle private messages, including messages in channels." nil
  1202. (let ((sender-spec (erc-response.sender parsed))
  1203. (cmd (erc-response.command parsed))
  1204. (tgt (car (erc-response.command-args parsed)))
  1205. (msg (erc-response.contents parsed)))
  1206. (if (or (erc-ignored-user-p sender-spec)
  1207. (erc-ignored-reply-p msg tgt proc))
  1208. (when erc-minibuffer-ignored
  1209. (message "Ignored %s from %s to %s" cmd sender-spec tgt))
  1210. (let* ((sndr (erc-parse-user sender-spec))
  1211. (nick (nth 0 sndr))
  1212. (login (nth 1 sndr))
  1213. (host (nth 2 sndr))
  1214. (msgp (string= cmd "PRIVMSG"))
  1215. (noticep (string= cmd "NOTICE"))
  1216. ;; S.B. downcase *both* tgt and current nick
  1217. (privp (erc-current-nick-p tgt))
  1218. s buffer
  1219. fnick)
  1220. (setf (erc-response.contents parsed) msg)
  1221. (setq buffer (erc-get-buffer (if privp nick tgt) proc))
  1222. (when buffer
  1223. (with-current-buffer buffer
  1224. ;; update the chat partner info. Add to the list if private
  1225. ;; message. We will accumulate private identities indefinitely
  1226. ;; at this point.
  1227. (erc-update-channel-member (if privp nick tgt) nick nick
  1228. privp nil nil host login nil nil t)
  1229. (let ((cdata (erc-get-channel-user nick)))
  1230. (setq fnick (funcall erc-format-nick-function
  1231. (car cdata) (cdr cdata))))))
  1232. (cond
  1233. ((erc-is-message-ctcp-p msg)
  1234. (setq s (if msgp
  1235. (erc-process-ctcp-query proc parsed nick login host)
  1236. (erc-process-ctcp-reply proc parsed nick login host
  1237. (match-string 1 msg)))))
  1238. (t
  1239. (setcar erc-server-last-peers nick)
  1240. (setq s (erc-format-privmessage
  1241. (or fnick nick) msg
  1242. ;; If buffer is a query buffer,
  1243. ;; format the nick as for a channel.
  1244. (and (not (and buffer
  1245. (erc-query-buffer-p buffer)
  1246. erc-format-query-as-channel-p))
  1247. privp)
  1248. msgp))))
  1249. (when s
  1250. (if (and noticep privp)
  1251. (progn
  1252. (run-hook-with-args 'erc-echo-notice-always-hook
  1253. s parsed buffer nick)
  1254. (run-hook-with-args-until-success
  1255. 'erc-echo-notice-hook s parsed buffer nick))
  1256. (erc-display-message parsed nil buffer s)))
  1257. (when (string= cmd "PRIVMSG")
  1258. (erc-auto-query proc parsed))))))
  1259. ;; FIXME: need clean way of specifying extra hooks in
  1260. ;; define-erc-response-handler.
  1261. (add-hook 'erc-server-PRIVMSG-functions 'erc-auto-query)
  1262. (define-erc-response-handler (QUIT)
  1263. "Another user has quit IRC." nil
  1264. (let ((reason (erc-response.contents parsed))
  1265. bufs)
  1266. (multiple-value-bind (nick login host)
  1267. (values-list (erc-parse-user (erc-response.sender parsed)))
  1268. (setq bufs (erc-buffer-list-with-nick nick proc))
  1269. (erc-remove-user nick)
  1270. (setq reason (erc-wash-quit-reason reason nick login host))
  1271. (erc-display-message parsed 'notice bufs
  1272. 'QUIT ?n nick ?u login
  1273. ?h host ?r reason))))
  1274. (define-erc-response-handler (TOPIC)
  1275. "The channel topic has changed." nil
  1276. (let* ((ch (first (erc-response.command-args parsed)))
  1277. (topic (erc-trim-string (erc-response.contents parsed)))
  1278. (time (format-time-string "%T %m/%d/%y" (current-time))))
  1279. (multiple-value-bind (nick login host)
  1280. (values-list (erc-parse-user (erc-response.sender parsed)))
  1281. (erc-update-channel-member ch nick nick nil nil nil host login)
  1282. (erc-update-channel-topic ch (format "%s\C-o (%s, %s)" topic nick time))
  1283. (erc-display-message parsed 'notice (erc-get-buffer ch proc)
  1284. 'TOPIC ?n nick ?u login ?h host
  1285. ?c ch ?T topic))))
  1286. (define-erc-response-handler (WALLOPS)
  1287. "Display a WALLOPS message." nil
  1288. (let ((message (erc-response.contents parsed)))
  1289. (multiple-value-bind (nick login host)
  1290. (values-list (erc-parse-user (erc-response.sender parsed)))
  1291. (erc-display-message
  1292. parsed 'notice nil
  1293. 'WALLOPS ?n nick ?m message))))
  1294. (define-erc-response-handler (001)
  1295. "Set `erc-server-current-nick' to reflect server settings and display the welcome message."
  1296. nil
  1297. (erc-set-current-nick (first (erc-response.command-args parsed)))
  1298. (erc-update-mode-line) ; needed here?
  1299. (setq erc-nick-change-attempt-count 0)
  1300. (setq erc-default-nicks (if (consp erc-nick) erc-nick (list erc-nick)))
  1301. (erc-display-message
  1302. parsed 'notice 'active (erc-response.contents parsed)))
  1303. (define-erc-response-handler (MOTD 002 003 371 372 374 375)
  1304. "Display the server's message of the day." nil
  1305. (erc-handle-login)
  1306. (erc-display-message
  1307. parsed 'notice (if erc-server-connected 'active proc)
  1308. (erc-response.contents parsed)))
  1309. (define-erc-response-handler (376 422)
  1310. "End of MOTD/MOTD is missing." nil
  1311. (erc-server-MOTD proc parsed)
  1312. (erc-connection-established proc parsed))
  1313. (define-erc-response-handler (004)
  1314. "Display the server's identification." nil
  1315. (multiple-value-bind (server-name server-version)
  1316. (values-list (cdr (erc-response.command-args parsed)))
  1317. (setq erc-server-version server-version)
  1318. (setq erc-server-announced-name server-name)
  1319. (erc-update-mode-line-buffer (process-buffer proc))
  1320. (erc-display-message
  1321. parsed 'notice proc
  1322. 's004 ?s server-name ?v server-version
  1323. ?U (fourth (erc-response.command-args parsed))
  1324. ?C (fifth (erc-response.command-args parsed)))))
  1325. (define-erc-response-handler (005)
  1326. "Set the variable `erc-server-parameters' and display the received message.
  1327. According to RFC 2812, suggests alternate servers on the network.
  1328. Many servers, however, use this code to show which parameters they have set,
  1329. for example, the network identifier, maximum allowed topic length, whether
  1330. certain commands are accepted and more. See documentation for
  1331. `erc-server-parameters' for more information on the parameters sent.
  1332. A server may send more than one 005 message."
  1333. nil
  1334. (let ((line (mapconcat 'identity
  1335. (setf (erc-response.command-args parsed)
  1336. (cdr (erc-response.command-args parsed)))
  1337. " ")))
  1338. (while (erc-response.command-args parsed)
  1339. (let ((section (pop (erc-response.command-args parsed))))
  1340. ;; fill erc-server-parameters
  1341. (when (string-match "^\\([A-Z]+\\)\=\\(.*\\)$\\|^\\([A-Z]+\\)$"
  1342. section)
  1343. (add-to-list 'erc-server-parameters
  1344. `(,(or (match-string 1 section)
  1345. (match-string 3 section))
  1346. .
  1347. ,(match-string 2 section))))))
  1348. (erc-display-message parsed 'notice proc line)))
  1349. (define-erc-response-handler (221)
  1350. "Display the current user modes." nil
  1351. (let* ((nick (first (erc-response.command-args parsed)))
  1352. (modes (mapconcat 'identity
  1353. (cdr (erc-response.command-args parsed)) " ")))
  1354. (erc-set-modes nick modes)
  1355. (erc-display-message parsed 'notice 'active 's221 ?n nick ?m modes)))
  1356. (define-erc-response-handler (252)
  1357. "Display the number of IRC operators online." nil
  1358. (erc-display-message parsed 'notice 'active 's252
  1359. ?i (second (erc-response.command-args parsed))))
  1360. (define-erc-response-handler (253)
  1361. "Display the number of unknown connections." nil
  1362. (erc-display-message parsed 'notice 'active 's253
  1363. ?i (second (erc-response.command-args parsed))))
  1364. (define-erc-response-handler (254)
  1365. "Display the number of channels formed." nil
  1366. (erc-display-message parsed 'notice 'active 's254
  1367. ?i (second (erc-response.command-args parsed))))
  1368. (define-erc-response-handler (250 251 255 256 257 258 259 265 266 377 378)
  1369. "Generic display of server messages as notices.
  1370. See `erc-display-server-message'." nil
  1371. (erc-display-server-message proc parsed))
  1372. (define-erc-response-handler (275)
  1373. "Display secure connection message." nil
  1374. (multiple-value-bind (nick user message)
  1375. (values-list (cdr (erc-response.command-args parsed)))
  1376. (erc-display-message
  1377. parsed 'notice 'active 's275
  1378. ?n nick
  1379. ?m (mapconcat 'identity (cddr (erc-response.command-args parsed))
  1380. " "))))
  1381. (define-erc-response-handler (290)
  1382. "Handle dancer-ircd CAPAB messages." nil nil)
  1383. (define-erc-response-handler (301)
  1384. "AWAY notice." nil
  1385. (erc-display-message parsed 'notice 'active 's301
  1386. ?n (second (erc-response.command-args parsed))
  1387. ?r (erc-response.contents parsed)))
  1388. (define-erc-response-handler (303)
  1389. "ISON reply" nil
  1390. (erc-display-message parsed 'notice 'active 's303
  1391. ?n (second (erc-response.command-args parsed))))
  1392. (define-erc-response-handler (305)
  1393. "Return from AWAYness." nil
  1394. (erc-process-away proc nil)
  1395. (erc-display-message parsed 'notice 'active
  1396. 's305 ?m (erc-response.contents parsed)))
  1397. (define-erc-response-handler (306)
  1398. "Set AWAYness." nil
  1399. (erc-process-away proc t)
  1400. (erc-display-message parsed 'notice 'active
  1401. 's306 ?m (erc-response.contents parsed)))
  1402. (define-erc-response-handler (307)
  1403. "Display nick-identified message." nil
  1404. (multiple-value-bind (nick user message)
  1405. (values-list (cdr (erc-response.command-args parsed)))
  1406. (erc-display-message
  1407. parsed 'notice 'active 's307
  1408. ?n nick
  1409. ?m (mapconcat 'identity (cddr (erc-response.command-args parsed))
  1410. " "))))
  1411. (define-erc-response-handler (311 314)
  1412. "WHOIS/WHOWAS notices." nil
  1413. (let ((fname (erc-response.contents parsed))
  1414. (catalog-entry (intern (format "s%s" (erc-response.command parsed)))))
  1415. (multiple-value-bind (nick user host)
  1416. (values-list (cdr (erc-response.command-args parsed)))
  1417. (erc-update-user-nick nick nick host nil fname user)
  1418. (erc-display-message
  1419. parsed 'notice 'active catalog-entry
  1420. ?n nick ?f fname ?u user ?h host))))
  1421. (define-erc-response-handler (312)
  1422. "Server name response in WHOIS." nil
  1423. (multiple-value-bind (nick server-host)
  1424. (values-list (cdr (erc-response.command-args parsed)))
  1425. (erc-display-message
  1426. parsed 'notice 'active 's312
  1427. ?n nick ?s server-host ?c (erc-response.contents parsed))))
  1428. (define-erc-response-handler (313)
  1429. "IRC Operator response in WHOIS." nil
  1430. (erc-display-message
  1431. parsed 'notice 'active 's313
  1432. ?n (second (erc-response.command-args parsed))))
  1433. (define-erc-response-handler (315 318 323 369)
  1434. ;; 315 - End of WHO
  1435. ;; 318 - End of WHOIS list
  1436. ;; 323 - End of channel LIST
  1437. ;; 369 - End of WHOWAS
  1438. "End of WHO/WHOIS/LIST/WHOWAS notices." nil
  1439. (ignore proc parsed))
  1440. (define-erc-response-handler (317)
  1441. "IDLE notice." nil
  1442. (multiple-value-bind (nick seconds-idle on-since time)
  1443. (values-list (cdr (erc-response.command-args parsed)))
  1444. (setq time (when on-since
  1445. (format-time-string "%T %Y/%m/%d"
  1446. (erc-string-to-emacs-time on-since))))
  1447. (erc-update-user-nick nick nick nil nil nil
  1448. (and time (format "on since %s" time)))
  1449. (if time
  1450. (erc-display-message
  1451. parsed 'notice 'active 's317-on-since
  1452. ?n nick ?i (erc-sec-to-time (string-to-number seconds-idle)) ?t time)
  1453. (erc-display-message
  1454. parsed 'notice 'active 's317
  1455. ?n nick ?i (erc-sec-to-time (string-to-number seconds-idle))))))
  1456. (define-erc-response-handler (319)
  1457. "Channel names in WHOIS response." nil
  1458. (erc-display-message
  1459. parsed 'notice 'active 's319
  1460. ?n (second (erc-response.command-args parsed))
  1461. ?c (erc-response.contents parsed)))
  1462. (define-erc-response-handler (320)
  1463. "Identified user in WHOIS." nil
  1464. (erc-display-message
  1465. parsed 'notice 'active 's320
  1466. ?n (second (erc-response.command-args parsed))))
  1467. (define-erc-response-handler (321)
  1468. "LIST header." nil
  1469. (setq erc-channel-list nil))
  1470. (defun erc-server-321-message (proc parsed)
  1471. "Display a message for the 321 event."
  1472. (erc-display-message parsed 'notice proc 's321)
  1473. nil)
  1474. (add-hook 'erc-server-321-functions 'erc-server-321-message t)
  1475. (define-erc-response-handler (322)
  1476. "LIST notice." nil
  1477. (let ((topic (erc-response.contents parsed)))
  1478. (multiple-value-bind (channel num-users)
  1479. (values-list (cdr (erc-response.command-args parsed)))
  1480. (add-to-list 'erc-channel-list (list channel))
  1481. (erc-update-channel-topic channel topic))))
  1482. (defun erc-server-322-message (proc parsed)
  1483. "Display a message for the 322 event."
  1484. (let ((topic (erc-response.contents parsed)))
  1485. (multiple-value-bind (channel num-users)
  1486. (values-list (cdr (erc-response.command-args parsed)))
  1487. (erc-display-message
  1488. parsed 'notice proc 's322
  1489. ?c channel ?u num-users ?t (or topic "")))))
  1490. (add-hook 'erc-server-322-functions 'erc-server-322-message t)
  1491. (define-erc-response-handler (324)
  1492. "Channel or nick modes." nil
  1493. (let ((channel (second (erc-response.command-args parsed)))
  1494. (modes (mapconcat 'identity (cddr (erc-response.command-args parsed))
  1495. " ")))
  1496. (erc-set-modes channel modes)
  1497. (erc-display-message
  1498. parsed 'notice (erc-get-buffer channel proc)
  1499. 's324 ?c channel ?m modes)))
  1500. (define-erc-response-handler (328)
  1501. "Channel URL (on freenode network)." nil
  1502. (let ((channel (second (erc-response.command-args parsed)))
  1503. (url (erc-response.contents parsed)))
  1504. (erc-display-message parsed 'notice (erc-get-buffer channel proc)
  1505. 's328 ?c channel ?u url)))
  1506. (define-erc-response-handler (329)
  1507. "Channel creation date." nil
  1508. (let ((channel (second (erc-response.command-args parsed)))
  1509. (time (erc-string-to-emacs-time
  1510. (third (erc-response.command-args parsed)))))
  1511. (erc-display-message
  1512. parsed 'notice (erc-get-buffer channel proc)
  1513. 's329 ?c channel ?t (format-time-string "%A %Y/%m/%d %X" time))))
  1514. (define-erc-response-handler (330)
  1515. "Nick is authed as (on Quakenet network)." nil
  1516. ;; FIXME: I don't know what the magic numbers mean. Mummy, make
  1517. ;; the magic numbers go away.
  1518. ;; No seriously, I have no clue about the format of this command,
  1519. ;; and don't sit on Quakenet, so can't test. Originally we had:
  1520. ;; nick == (aref parsed 3)
  1521. ;; authaccount == (aref parsed 4)
  1522. ;; authmsg == (aref parsed 5)
  1523. ;; The guesses below are, well, just that. -- Lawrence 2004/05/10
  1524. (let ((nick (second (erc-response.command-args parsed)))
  1525. (authaccount (third (erc-response.command-args parsed)))
  1526. (authmsg (erc-response.contents parsed)))
  1527. (erc-display-message parsed 'notice 'active 's330
  1528. ?n nick ?a authmsg ?i authaccount)))
  1529. (define-erc-response-handler (331)
  1530. "No topic set for channel." nil
  1531. (let ((channel (second (erc-response.command-args parsed)))
  1532. (topic (erc-response.contents parsed)))
  1533. (erc-display-message parsed 'notice (erc-get-buffer channel proc)
  1534. 's331 ?c channel)))
  1535. (define-erc-response-handler (332)
  1536. "TOPIC notice." nil
  1537. (let ((channel (second (erc-response.command-args parsed)))
  1538. (topic (erc-response.contents parsed)))
  1539. (erc-update-channel-topic channel topic)
  1540. (erc-display-message parsed 'notice (erc-get-buffer channel proc)
  1541. 's332 ?c channel ?T topic)))
  1542. (define-erc-response-handler (333)
  1543. "Who set the topic, and when." nil
  1544. (multiple-value-bind (channel nick time)
  1545. (values-list (cdr (erc-response.command-args parsed)))
  1546. (setq time (format-time-string "%T %Y/%m/%d"
  1547. (erc-string-to-emacs-time time)))
  1548. (erc-update-channel-topic channel
  1549. (format "\C-o (%s, %s)" nick time)
  1550. 'append)
  1551. (erc-display-message parsed 'notice (erc-get-buffer channel proc)
  1552. 's333 ?c channel ?n nick ?t time)))
  1553. (define-erc-response-handler (341)
  1554. "Let user know when an INVITE attempt has been sent successfully."
  1555. nil
  1556. (multiple-value-bind (nick channel)
  1557. (values-list (cdr (erc-response.command-args parsed)))
  1558. (erc-display-message parsed 'notice (erc-get-buffer channel proc)
  1559. 's341 ?n nick ?c channel)))
  1560. (define-erc-response-handler (352)
  1561. "WHO notice." nil
  1562. (multiple-value-bind (channel user host server nick away-flag)
  1563. (values-list (cdr (erc-response.command-args parsed)))
  1564. (let ((full-name (erc-response.contents parsed))
  1565. hopcount)
  1566. (when (string-match "\\(^[0-9]+ \\)\\(.*\\)$" full-name)
  1567. (setq hopcount (match-string 1 full-name))
  1568. (setq full-name (match-string 2 full-name)))
  1569. (erc-update-channel-member channel nick nick nil nil nil host
  1570. user full-name)
  1571. (erc-display-message parsed 'notice 'active 's352
  1572. ?c channel ?n nick ?a away-flag
  1573. ?u user ?h host ?f full-name))))
  1574. (define-erc-response-handler (353)
  1575. "NAMES notice." nil
  1576. (let ((channel (third (erc-response.command-args parsed)))
  1577. (users (erc-response.contents parsed)))
  1578. (erc-display-message parsed 'notice (or (erc-get-buffer channel proc)
  1579. 'active)
  1580. 's353 ?c channel ?u users)
  1581. (erc-with-buffer (channel proc)
  1582. (erc-channel-receive-names users))))
  1583. (define-erc-response-handler (366)
  1584. "End of NAMES." nil
  1585. (erc-with-buffer ((second (erc-response.command-args parsed)) proc)
  1586. (erc-channel-end-receiving-names)))
  1587. (define-erc-response-handler (367)
  1588. "Channel ban list entries." nil
  1589. (multiple-value-bind (channel banmask setter time)
  1590. (values-list (cdr (erc-response.command-args parsed)))
  1591. ;; setter and time are not standard
  1592. (if setter
  1593. (erc-display-message parsed 'notice 'active 's367-set-by
  1594. ?c channel
  1595. ?b banmask
  1596. ?s setter
  1597. ?t (or time ""))
  1598. (erc-display-message parsed 'notice 'active 's367
  1599. ?c channel
  1600. ?b banmask))))
  1601. (define-erc-response-handler (368)
  1602. "End of channel ban list." nil
  1603. (let ((channel (second (erc-response.command-args parsed))))
  1604. (erc-display-message parsed 'notice 'active 's368
  1605. ?c channel)))
  1606. (define-erc-response-handler (379)
  1607. "Forwarding to another channel." nil
  1608. ;; FIXME: Yet more magic numbers in original code, I'm guessing this
  1609. ;; command takes two arguments, and doesn't have any "contents". --
  1610. ;; Lawrence 2004/05/10
  1611. (multiple-value-bind (from to)
  1612. (values-list (cdr (erc-response.command-args parsed)))
  1613. (erc-display-message parsed 'notice 'active
  1614. 's379 ?c from ?f to)))
  1615. (define-erc-response-handler (391)
  1616. "Server's time string." nil
  1617. (erc-display-message
  1618. parsed 'notice 'active
  1619. 's391 ?s (second (erc-response.command-args parsed))
  1620. ?t (third (erc-response.command-args parsed))))
  1621. (define-erc-response-handler (401)
  1622. "No such nick/channel." nil
  1623. (let ((nick/channel (second (erc-response.command-args parsed))))
  1624. (when erc-whowas-on-nosuchnick
  1625. (erc-log (format "cmd: WHOWAS: %s" nick/channel))
  1626. (erc-server-send (format "WHOWAS %s 1" nick/channel)))
  1627. (erc-display-message parsed '(notice error) 'active
  1628. 's401 ?n nick/channel)))
  1629. (define-erc-response-handler (403)
  1630. "No such channel." nil
  1631. (erc-display-message parsed '(notice error) 'active
  1632. 's403 ?c (second (erc-response.command-args parsed))))
  1633. (define-erc-response-handler (404)
  1634. "Cannot send to channel." nil
  1635. (erc-display-message parsed '(notice error) 'active
  1636. 's404 ?c (second (erc-response.command-args parsed))))
  1637. (define-erc-response-handler (405)
  1638. "Can't join that many channels." nil
  1639. (erc-display-message parsed '(notice error) 'active
  1640. 's405 ?c (second (erc-response.command-args parsed))))
  1641. (define-erc-response-handler (406)
  1642. "No such nick." nil
  1643. (erc-display-message parsed '(notice error) 'active
  1644. 's406 ?n (second (erc-response.command-args parsed))))
  1645. (define-erc-response-handler (412)
  1646. "No text to send." nil
  1647. (erc-display-message parsed '(notice error) 'active 's412))
  1648. (define-erc-response-handler (421)
  1649. "Unknown command." nil
  1650. (erc-display-message parsed '(notice error) 'active 's421
  1651. ?c (second (erc-response.command-args parsed))))
  1652. (define-erc-response-handler (432)
  1653. "Bad nick." nil
  1654. (erc-display-message parsed '(notice error) 'active 's432
  1655. ?n (second (erc-response.command-args parsed))))
  1656. (define-erc-response-handler (433)
  1657. "Login-time \"nick in use\"." nil
  1658. (erc-nickname-in-use (second (erc-response.command-args parsed))
  1659. "already in use"))
  1660. (define-erc-response-handler (437)
  1661. "Nick temporarily unavailable (on IRCnet)." nil
  1662. (let ((nick/channel (second (erc-response.command-args parsed))))
  1663. (unless (erc-channel-p nick/channel)
  1664. (erc-nickname-in-use nick/channel "temporarily unavailable"))))
  1665. (define-erc-response-handler (442)
  1666. "Not on channel." nil
  1667. (erc-display-message parsed '(notice error) 'active 's442
  1668. ?c (second (erc-response.command-args parsed))))
  1669. (define-erc-response-handler (461)
  1670. "Not enough parameters for command." nil
  1671. (erc-display-message parsed '(notice error) 'active 's461
  1672. ?c (second (erc-response.command-args parsed))
  1673. ?m (erc-response.contents parsed)))
  1674. (define-erc-response-handler (465)
  1675. "You are banned from this server." nil
  1676. (setq erc-server-banned t)
  1677. ;; show the server's message, as a reason might be provided
  1678. (erc-display-error-notice
  1679. parsed
  1680. (erc-response.contents parsed)))
  1681. (define-erc-response-handler (474)
  1682. "Banned from channel errors." nil
  1683. (erc-display-message parsed '(notice error) nil
  1684. (intern (format "s%s"
  1685. (erc-response.command parsed)))
  1686. ?c (second (erc-response.command-args parsed))))
  1687. (define-erc-response-handler (475)
  1688. "Channel key needed." nil
  1689. (erc-display-message parsed '(notice error) nil 's475
  1690. ?c (second (erc-response.command-args parsed)))
  1691. (when erc-prompt-for-channel-key
  1692. (let ((channel (second (erc-response.command-args parsed)))
  1693. (key (read-from-minibuffer
  1694. (format "Channel %s is mode +k. Enter key (RET to cancel): "
  1695. (second (erc-response.command-args parsed))))))
  1696. (when (and key (> (length key) 0))
  1697. (erc-cmd-JOIN channel key)))))
  1698. (define-erc-response-handler (477)
  1699. "Channel doesn't support modes." nil
  1700. (let ((channel (second (erc-response.command-args parsed)))
  1701. (message (erc-response.contents parsed)))
  1702. (erc-display-message parsed 'notice (erc-get-buffer channel proc)
  1703. (format "%s: %s" channel message))))
  1704. (define-erc-response-handler (482)
  1705. "You need to be a channel operator to do that." nil
  1706. (let ((channel (second (erc-response.command-args parsed)))
  1707. (message (erc-response.contents parsed)))
  1708. (erc-display-message parsed '(error notice) 'active 's482
  1709. ?c channel ?m message)))
  1710. (define-erc-response-handler (671)
  1711. "Secure connection response in WHOIS." nil
  1712. (let ((nick (second (erc-response.command-args parsed)))
  1713. (securemsg (erc-response.contents parsed)))
  1714. (erc-display-message parsed 'notice 'active 's671
  1715. ?n nick ?a securemsg)))
  1716. (define-erc-response-handler (431 445 446 451 462 463 464 481 483 484 485
  1717. 491 501 502)
  1718. ;; 431 - No nickname given
  1719. ;; 445 - SUMMON has been disabled
  1720. ;; 446 - USERS has been disabled
  1721. ;; 451 - You have not registered
  1722. ;; 462 - Unauthorized command (already registered)
  1723. ;; 463 - Your host isn't among the privileged
  1724. ;; 464 - Password incorrect
  1725. ;; 481 - Need IRCop privileges
  1726. ;; 483 - You can't kill a server!
  1727. ;; 484 - Your connection is restricted!
  1728. ;; 485 - You're not the original channel operator
  1729. ;; 491 - No O-lines for your host
  1730. ;; 501 - Unknown MODE flag
  1731. ;; 502 - Cannot change mode for other users
  1732. "Generic display of server error messages.
  1733. See `erc-display-error-notice'." nil
  1734. (erc-display-error-notice
  1735. parsed
  1736. (intern (format "s%s" (erc-response.command parsed)))))
  1737. ;; FIXME: These are yet to be implemented, they're just stubs for now
  1738. ;; -- Lawrence 2004/05/12
  1739. ;; response numbers left here for reference
  1740. ;; (define-erc-response-handler (323 364 365 381 382 392 393 394 395
  1741. ;; 200 201 202 203 204 205 206 208 209 211 212 213
  1742. ;; 214 215 216 217 218 219 241 242 243 244 249 261
  1743. ;; 262 302 342 351 402 407 409 411 413 414 415
  1744. ;; 423 424 436 441 443 444 467 471 472 473 KILL)
  1745. ;; nil nil
  1746. ;; (ignore proc parsed))
  1747. (provide 'erc-backend)
  1748. ;;; erc-backend.el ends here
  1749. ;; Local Variables:
  1750. ;; indent-tabs-mode: nil
  1751. ;; End: