|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the IRC window. |
|
8 """ |
|
9 |
|
10 import re |
|
11 import logging |
|
12 |
|
13 from PyQt4.QtCore import pyqtSlot, Qt, QByteArray |
|
14 from PyQt4.QtGui import QWidget, QToolButton, QLabel |
|
15 from PyQt4.QtNetwork import QTcpSocket, QAbstractSocket |
|
16 |
|
17 from E5Gui import E5MessageBox |
|
18 |
|
19 from .Ui_IrcWidget import Ui_IrcWidget |
|
20 |
|
21 from .IrcNetworkManager import IrcNetworkManager |
|
22 from .IrcChannelWidget import IrcChannelWidget |
|
23 |
|
24 import Preferences |
|
25 import UI.PixmapCache |
|
26 |
|
27 |
|
28 class IrcWidget(QWidget, Ui_IrcWidget): |
|
29 """ |
|
30 Class implementing the IRC window. |
|
31 """ |
|
32 def __init__(self, parent=None): |
|
33 """ |
|
34 Constructor |
|
35 |
|
36 @param parent reference to the parent widget (QWidget) |
|
37 """ |
|
38 super().__init__(parent) |
|
39 self.setupUi(self) |
|
40 |
|
41 self.__ircNetworkManager = IrcNetworkManager(self) |
|
42 |
|
43 self.__leaveButton = QToolButton(self) |
|
44 self.__leaveButton.setIcon(UI.PixmapCache.getIcon("ircCloseChannel.png")) |
|
45 self.__leaveButton.setToolTip(self.trUtf8("Press to leave the current channel")) |
|
46 self.__leaveButton.clicked[()].connect(self.__leaveChannel) |
|
47 self.__leaveButton.setEnabled(False) |
|
48 self.channelsWidget.setCornerWidget(self.__leaveButton, Qt.BottomRightCorner) |
|
49 self.channelsWidget.setTabsClosable(False) |
|
50 |
|
51 self.networkWidget.initialize(self.__ircNetworkManager) |
|
52 self.networkWidget.connectNetwork.connect(self.__connectNetwork) |
|
53 self.networkWidget.editNetwork.connect(self.__editNetwork) |
|
54 self.networkWidget.joinChannel.connect(self.__joinChannel) |
|
55 self.networkWidget.nickChanged.connect(self.__changeNick) |
|
56 |
|
57 self.__channelList = [] |
|
58 self.__channelTypePrefixes = "" |
|
59 self.__userName = "" |
|
60 self.__nickIndex = -1 |
|
61 self.__nickName = "" |
|
62 self.__server = None |
|
63 self.__registering = False |
|
64 |
|
65 self.__buffer = "" |
|
66 self.__userPrefix = {} |
|
67 |
|
68 # create TCP socket |
|
69 self.__socket = QTcpSocket(self) |
|
70 self.__socket.hostFound.connect(self.__hostFound) |
|
71 self.__socket.connected.connect(self.__hostConnected) |
|
72 self.__socket.disconnected.connect(self.__hostDisconnected) |
|
73 self.__socket.readyRead.connect(self.__readyRead) |
|
74 self.__socket.error.connect(self.__tcpError) |
|
75 |
|
76 self.__patterns = [ |
|
77 # :foo.bar.net COMMAND some message |
|
78 (re.compile(r""":([^ ]+)\s+([A-Z]+)\s+(.+)"""), self.__handleNamedMessage), |
|
79 # :foo.bar.net 123 * :info |
|
80 (re.compile(r""":([^ ]+)\s+(\d{3})\s+(.+)"""), self.__handleNumericMessage), |
|
81 # PING :ping message |
|
82 (re.compile(r"""PING\s+:(.*)"""), self.__ping), |
|
83 ] |
|
84 self.__prefixRe = re.compile(r""".*\sPREFIX=\((.*)\)([^ ]+).*""") |
|
85 self.__chanTypesRe = re.compile(r""".*\sCHANTYPES=([^ ]+).*""") |
|
86 |
|
87 ircPic = UI.PixmapCache.getPixmap("irc128.png") |
|
88 self.__emptyLabel = QLabel() |
|
89 self.__emptyLabel.setPixmap(ircPic) |
|
90 self.__emptyLabel.setAlignment(Qt.AlignVCenter | Qt.AlignHCenter) |
|
91 self.channelsWidget.addTab(self.__emptyLabel, "") |
|
92 |
|
93 |
|
94 def shutdown(self): |
|
95 """ |
|
96 Public method to shut down the widget. |
|
97 |
|
98 @return flag indicating successful shutdown (boolean) |
|
99 """ |
|
100 if self.__server: |
|
101 ok = E5MessageBox.yesNo(self, |
|
102 self.trUtf8("Disconnect from Server"), |
|
103 self.trUtf8("""<p>Do you really want to disconnect from""" |
|
104 """ <b>{0}</b>?</p><p>All channels will be closed.</p>""")\ |
|
105 .format(self.__server.getServer())) |
|
106 if ok: |
|
107 self.__socket.blockSignals(True) |
|
108 |
|
109 self.__send("QUIT :" + self.trUtf8("IRC for eric IDE")) |
|
110 self.__socket.close() |
|
111 self.__socket.deleteLater() |
|
112 else: |
|
113 ok = True |
|
114 |
|
115 if ok: |
|
116 self.__ircNetworkManager.close() |
|
117 return ok |
|
118 |
|
119 def __connectNetwork(self, name, connect): |
|
120 """ |
|
121 Private slot to connect to or disconnect from the given network. |
|
122 |
|
123 @param name name of the network to connect to (string) |
|
124 @param connect flag indicating to connect (boolean) |
|
125 """ |
|
126 if connect: |
|
127 network = self.__ircNetworkManager.getNetwork(name) |
|
128 self.__server = self.__ircNetworkManager.getServer(network.getServerName()) |
|
129 self.__userName = network.getIdentityName() |
|
130 if self.__server: |
|
131 self.networkWidget.addServerMessage(self.trUtf8("Info"), |
|
132 self.trUtf8("Looking for server {0} (port {1})...").format( |
|
133 self.__server.getServer(), self.__server.getPort())) |
|
134 self.__socket.connectToHost(self.__server.getServer(), |
|
135 self.__server.getPort()) |
|
136 else: |
|
137 ok = E5MessageBox.yesNo(self, |
|
138 self.trUtf8("Disconnect from Server"), |
|
139 self.trUtf8("""<p>Do you really want to disconnect from""" |
|
140 """ <b>{0}</b>?</p><p>All channels will be closed.</p>""")\ |
|
141 .format(self.__server.getServer())) |
|
142 if ok: |
|
143 self.networkWidget.addServerMessage(self.trUtf8("Info"), |
|
144 self.trUtf8("Disconnecting from server {0}...").format( |
|
145 self.__server.getServer())) |
|
146 while self.__channelList: |
|
147 channel = self.__channelList.pop() |
|
148 self.channelsWidget.removeTab(self.channelsWidget.indexOf(channel)) |
|
149 channel.deleteLater() |
|
150 channel = None |
|
151 self.__send("QUIT :" + self.trUtf8("IRC for eric IDE")) |
|
152 self.__socket.close() |
|
153 |
|
154 def __editNetwork(self, name): |
|
155 """ |
|
156 Private slot to edit the network configuration. |
|
157 |
|
158 @param name name of the network to edit (string) |
|
159 """ |
|
160 # TODO: implement this |
|
161 |
|
162 def __joinChannel(self, name): |
|
163 """ |
|
164 Private slot to join a channel. |
|
165 |
|
166 @param name name of the channel (string) |
|
167 """ |
|
168 # step 1: check, if this channel is already joined |
|
169 for channel in self.__channelList: |
|
170 if channel.name() == name: |
|
171 return |
|
172 |
|
173 channel = IrcChannelWidget(self) |
|
174 channel.setName(name) |
|
175 channel.setUserName(self.__nickName) |
|
176 channel.setPartMessage(self.trUtf8("IRC for eric IDE")) |
|
177 channel.setUserPrivilegePrefix(self.__userPrefix) |
|
178 |
|
179 channel.sendData.connect(self.__send) |
|
180 channel.channelClosed.connect(self.__closeChannel) |
|
181 |
|
182 self.channelsWidget.addTab(channel, name) |
|
183 self.__channelList.append(channel) |
|
184 |
|
185 self.__send("JOIN " + name) |
|
186 self.__send("MODE " + name) |
|
187 |
|
188 emptyIndex = self.channelsWidget.indexOf(self.__emptyLabel) |
|
189 if emptyIndex > -1: |
|
190 self.channelsWidget.removeTab(emptyIndex) |
|
191 self.__leaveButton.setEnabled(True) |
|
192 self.channelsWidget.setTabsClosable(True) |
|
193 |
|
194 @pyqtSlot() |
|
195 def __leaveChannel(self): |
|
196 """ |
|
197 Private slot to leave a channel and close the associated tab. |
|
198 """ |
|
199 channel = self.channelsWidget.currentWidget() |
|
200 channel.requestLeave() |
|
201 |
|
202 def __closeChannel(self, name): |
|
203 """ |
|
204 Private slot handling the closing of a channel. |
|
205 |
|
206 @param name name of the closed channel (string) |
|
207 """ |
|
208 for channel in self.__channelList: |
|
209 if channel.name() == name: |
|
210 self.channelsWidget.removeTab(self.channelsWidget.indexOf(channel)) |
|
211 self.__channelList.remove(channel) |
|
212 channel.deleteLater() |
|
213 |
|
214 if self.channelsWidget.count() == 0: |
|
215 self.channelsWidget.addTab(self.__emptyLabel, "") |
|
216 self.__leaveButton.setEnabled(False) |
|
217 self.channelsWidget.setTabsClosable(False) |
|
218 |
|
219 @pyqtSlot(int) |
|
220 def on_channelsWidget_tabCloseRequested(self, index): |
|
221 """ |
|
222 Private slot to close a channel by pressing the close button of |
|
223 the channels widget. |
|
224 |
|
225 @param index index of the tab to be closed (integer) |
|
226 """ |
|
227 channel = self.channelsWidget.widget(index) |
|
228 channel.requestLeave() |
|
229 |
|
230 def __send(self, data): |
|
231 """ |
|
232 Private slot to send data to the IRC server. |
|
233 |
|
234 @param data data to be sent (string) |
|
235 """ |
|
236 self.__socket.write(QByteArray("{0}\r\n".format(data).encode("utf-8"))) |
|
237 |
|
238 def __hostFound(self): |
|
239 """ |
|
240 Private slot to indicate the host was found. |
|
241 """ |
|
242 self.networkWidget.addServerMessage(self.trUtf8("Info"), |
|
243 self.trUtf8("Server found,connecting...")) |
|
244 |
|
245 def __hostConnected(self): |
|
246 """ |
|
247 Private slot to log in to the server after the connection was established. |
|
248 """ |
|
249 self.networkWidget.addServerMessage(self.trUtf8("Info"), |
|
250 self.trUtf8("Connected,logging in...")) |
|
251 self.networkWidget.setConnected(True) |
|
252 |
|
253 self.__registering = True |
|
254 serverPassword = self.__server.getPassword() |
|
255 if serverPassword: |
|
256 self.__send("PASS " + serverPassword) |
|
257 nick = self.networkWidget.getNickname() |
|
258 if not nick: |
|
259 self.__nickIndex = 0 |
|
260 try: |
|
261 nick = self.__ircNetworkManager.getIdentity(self.__userName)\ |
|
262 .getNickNames()[self.__nickIndex] |
|
263 except IndexError: |
|
264 nick = "" |
|
265 if not nick: |
|
266 nick = self.__userName |
|
267 self.__nickName = nick |
|
268 self.networkWidget.setNickName(nick) |
|
269 self.__send("NICK " + nick) |
|
270 self.__send("USER " + self.__userName + " 0 * :eric IDE chat") |
|
271 |
|
272 def __hostDisconnected(self): |
|
273 """ |
|
274 Private slot to indicate the host was disconnected. |
|
275 """ |
|
276 self.networkWidget.addServerMessage(self.trUtf8("Info"), |
|
277 self.trUtf8("Server disconnected.")) |
|
278 self.networkWidget.setConnected(False) |
|
279 self.__server = None |
|
280 self.__nickName = "" |
|
281 self.__nickIndex = -1 |
|
282 self.__channelTypePrefixes = "" |
|
283 |
|
284 def __readyRead(self): |
|
285 """ |
|
286 Private slot to read data from the socket. |
|
287 """ |
|
288 self.__buffer += str(self.__socket.readAll(), |
|
289 Preferences.getSystem("IOEncoding"), |
|
290 'replace') |
|
291 if self.__buffer.endswith("\r\n"): |
|
292 for line in self.__buffer.splitlines(): |
|
293 line = line.strip() |
|
294 if line: |
|
295 logging.debug("<IRC> " + line) |
|
296 handled = False |
|
297 # step 1: give channels a chance to handle the message |
|
298 for channel in self.__channelList: |
|
299 handled = channel.handleMessage(line) |
|
300 if handled: |
|
301 break |
|
302 else: |
|
303 # step 2: try to process the message ourselves |
|
304 for patternRe, patternFunc in self.__patterns: |
|
305 match = patternRe.match(line) |
|
306 if match is not None: |
|
307 if patternFunc(match): |
|
308 break |
|
309 else: |
|
310 # Oops, the message wasn't handled |
|
311 self.networkWidget.addErrorMessage( |
|
312 self.trUtf8("Message Error"), |
|
313 self.trUtf8("Unknown message received from server:" |
|
314 "<br/>{0}").format(line)) |
|
315 |
|
316 self.__updateUsersCount() |
|
317 self.__buffer = "" |
|
318 |
|
319 def __handleNamedMessage(self, match): |
|
320 """ |
|
321 Private method to handle a server message containing a message name. |
|
322 |
|
323 @param reference to the match object |
|
324 @return flag indicating, if the message was handled (boolean) |
|
325 """ |
|
326 name = match.group(2) |
|
327 if name == "NOTICE": |
|
328 try: |
|
329 msg = match.group(3).split(":", 1)[1] |
|
330 except IndexError: |
|
331 msg = match.group(3) |
|
332 if "!" in match.group(1): |
|
333 name = match.group(1).split("!", 1)[0] |
|
334 msg = "-{0}- {1}".format(name, msg) |
|
335 self.networkWidget.addServerMessage(self.trUtf8("Notice"), msg) |
|
336 return True |
|
337 elif name == "MODE": |
|
338 self.__registering = False |
|
339 if ":" in match.group(3): |
|
340 # :detlev_ MODE detlev_ :+i |
|
341 name, modes = match.group(3).split(" :") |
|
342 sourceNick = match.group(1) |
|
343 if not self.__isChannelName(name): |
|
344 if name == self.__nickName: |
|
345 if sourceNick == self.__nickName: |
|
346 msg = self.trUtf8( |
|
347 "You have set your personal modes to <b>[{0}]</b>")\ |
|
348 .format(modes) |
|
349 else: |
|
350 msg = self.trUtf8( |
|
351 "{0} has changed your personal modes to <b>[{1}]</b>")\ |
|
352 .format(sourceNick, modes) |
|
353 self.networkWidget.addServerMessage( |
|
354 self.trUtf8("Mode"), msg, filterMsg=False) |
|
355 return True |
|
356 elif name == "PART": |
|
357 nick = match.group(1).split("!", 1)[0] |
|
358 if nick == self.__nickName: |
|
359 channel = match.group(3).split(None, 1)[0] |
|
360 self.networkWidget.addMessage( |
|
361 self.trUtf8("You have left channel {0}.").format(channel)) |
|
362 return True |
|
363 elif name == "NICK": |
|
364 # :foo_!n=foo@foohost.bar.net NICK :newnick |
|
365 oldNick = match.group(1).split("!", 1)[0] |
|
366 newNick = match.group(3).split(":", 1)[1] |
|
367 if oldNick == self.__nickName: |
|
368 self.networkWidget.addMessage( |
|
369 self.trUtf8("You are now known as {0}.").format(newNick)) |
|
370 self.__nickName = newNick |
|
371 self.networkWidget.setNickName(newNick) |
|
372 else: |
|
373 self.networkWidget.addMessage( |
|
374 self.trUtf8("User {0} is now known as {1}.").format( |
|
375 oldNick, newNick)) |
|
376 return True |
|
377 |
|
378 return False |
|
379 |
|
380 def __handleNumericMessage(self, match): |
|
381 """ |
|
382 Private method to handle a server message containing a numeric code. |
|
383 |
|
384 @param reference to the match object |
|
385 @return flag indicating, if the message was handled (boolean) |
|
386 """ |
|
387 code = int(match.group(2)) |
|
388 if code < 400: |
|
389 return self.__handleServerReply(code, match.group(1), match.group(3)) |
|
390 else: |
|
391 return self.__handleServerError(code, match.group(1), match.group(3)) |
|
392 |
|
393 def __handleServerError(self, code, server, message): |
|
394 """ |
|
395 Private slot to handle a server error reply. |
|
396 |
|
397 @param code numerical code sent by the server (integer) |
|
398 @param server name of the server (string) |
|
399 @param message message sent by the server (string) |
|
400 @return flag indicating, if the message was handled (boolean) |
|
401 """ |
|
402 if code == 433: |
|
403 if self.__registering: |
|
404 self.__handleNickInUseLogin() |
|
405 else: |
|
406 self.__handleNickInUse() |
|
407 else: |
|
408 self.networkWidget.addServerMessage(self.trUtf8("Error"), message) |
|
409 |
|
410 return True |
|
411 |
|
412 def __handleServerReply(self, code, server, message): |
|
413 """ |
|
414 Private slot to handle a server reply. |
|
415 |
|
416 @param code numerical code sent by the server (integer) |
|
417 @param server name of the server (string) |
|
418 @param message message sent by the server (string) |
|
419 @return flag indicating, if the message was handled (boolean) |
|
420 """ |
|
421 # determine message type |
|
422 if code in [1, 2, 3, 4]: |
|
423 msgType = self.trUtf8("Welcome") |
|
424 elif code == 5: |
|
425 msgType = self.trUtf8("Support") |
|
426 elif code in [250, 251, 252, 253, 254, 255, 265, 266]: |
|
427 msgType = self.trUtf8("User") |
|
428 elif code in [372, 375, 376]: |
|
429 msgType = self.trUtf8("MOTD") |
|
430 else: |
|
431 msgType = self.trUtf8("Info ({0})").format(code) |
|
432 |
|
433 # special treatment for some messages |
|
434 if code == 375: |
|
435 message = self.trUtf8("Message of the day") |
|
436 elif code == 376: |
|
437 message = self.trUtf8("End of message of the day") |
|
438 elif code == 4: |
|
439 parts = message.strip().split() |
|
440 message = self.trUtf8("Server {0} (Version {1}), User-Modes: {2}," |
|
441 " Channel-Modes: {3}").format(parts[1], parts[2], parts[3], parts[4]) |
|
442 elif code == 265: |
|
443 parts = message.strip().split() |
|
444 message = self.trUtf8("Current users on {0}: {1}, max. {2}").format( |
|
445 server, parts[1], parts[2]) |
|
446 elif code == 266: |
|
447 parts = message.strip().split() |
|
448 message = self.trUtf8("Current users on the network: {0}, max. {1}").format( |
|
449 parts[1], parts[2]) |
|
450 else: |
|
451 first, message = message.split(None, 1) |
|
452 if message.startswith(":"): |
|
453 message = message[1:] |
|
454 else: |
|
455 message = message.replace(":", "", 1) |
|
456 |
|
457 self.networkWidget.addServerMessage(msgType, message) |
|
458 |
|
459 if code == 1: |
|
460 # register with services after the welcome message |
|
461 self.__registerWithServices() |
|
462 elif code == 5: |
|
463 # extract the user privilege prefixes |
|
464 # ... PREFIX=(ov)@+ ... |
|
465 m = self.__prefixRe.match(message) |
|
466 if m: |
|
467 self.__setUserPrivilegePrefix(m.group(1), m.group(2)) |
|
468 # extract the channel type prefixes |
|
469 # ... CHANTYPES=# ... |
|
470 m = self.__chanTypesRe.match(message) |
|
471 if m: |
|
472 self.__setChannelTypePrefixes(m.group(1)) |
|
473 |
|
474 return True |
|
475 |
|
476 def __registerWithServices(self): |
|
477 """ |
|
478 Private method to register to services. |
|
479 """ |
|
480 identity = self.__ircNetworkManager.getIdentity(self.__userName) |
|
481 service = identity.getName() |
|
482 password = identity.getPassword() |
|
483 if service and password: |
|
484 self.__send("PRIVMSG " + service + " :identify " + password) |
|
485 |
|
486 def __tcpError(self, error): |
|
487 """ |
|
488 Private slot to handle errors reported by the TCP socket. |
|
489 |
|
490 @param error error code reported by the socket |
|
491 (QAbstractSocket.SocketError) |
|
492 """ |
|
493 if error == QAbstractSocket.RemoteHostClosedError: |
|
494 # ignore this one, it's a disconnect |
|
495 pass |
|
496 elif error == QAbstractSocket.HostNotFoundError: |
|
497 self.networkWidget.addErrorMessage(self.trUtf8("Socket Error"), |
|
498 self.trUtf8("The host was not found. Please check the host name" |
|
499 " and port settings.")) |
|
500 elif error == QAbstractSocket.ConnectionRefusedError: |
|
501 self.networkWidget.addErrorMessage(self.trUtf8("Socket Error"), |
|
502 self.trUtf8("The connection was refused by the peer. Please check the" |
|
503 " host name and port settings.")) |
|
504 else: |
|
505 self.networkWidget.addErrorMessage(self.trUtf8("Socket Error"), |
|
506 self.trUtf8("The following network error occurred:<br/>{0}").format( |
|
507 self.__socket.errorString())) |
|
508 |
|
509 def __setUserPrivilegePrefix(self, prefix1, prefix2): |
|
510 """ |
|
511 Private method to set the user privilege prefix. |
|
512 |
|
513 @param prefix1 first part of the prefix (string) |
|
514 @param prefix2 indictors the first part gets mapped to (string) |
|
515 """ |
|
516 # PREFIX=(ov)@+ |
|
517 # o = @ -> @ircbot , channel operator |
|
518 # v = + -> +userName , voice operator |
|
519 for i in range(len(prefix1)): |
|
520 self.__userPrefix["+" + prefix1[i]] = prefix2[i] |
|
521 self.__userPrefix["-" + prefix1[i]] = "" |
|
522 |
|
523 def __ping(self, match): |
|
524 """ |
|
525 Private method to handle a PING message. |
|
526 |
|
527 @param reference to the match object |
|
528 @return flag indicating, if the message was handled (boolean) |
|
529 """ |
|
530 self.__send("PONG " + match.group(1)) |
|
531 return True |
|
532 |
|
533 def __updateUsersCount(self): |
|
534 """ |
|
535 Private method to update the users count on the channel tabs. |
|
536 """ |
|
537 for channel in self.__channelList: |
|
538 index = self.channelsWidget.indexOf(channel) |
|
539 self.channelsWidget.setTabText(index, |
|
540 self.trUtf8("{0} ({1})", "channel name, users count").format( |
|
541 channel.name(), channel.getUsersCount())) |
|
542 |
|
543 def __handleNickInUseLogin(self): |
|
544 """ |
|
545 Private method to handle a 443 server error at login. |
|
546 """ |
|
547 self.__nickIndex += 1 |
|
548 try: |
|
549 nick = self.__ircNetworkManager.getIdentity(self.__userName)\ |
|
550 .getNickNames()[self.__nickIndex] |
|
551 self.__nickName = nick |
|
552 except IndexError: |
|
553 self.networkWidget.addServerMessage(self.trUtf8("Critical"), |
|
554 self.trUtf8("No nickname acceptable to the server configured" |
|
555 " for <b>{0}</b>. Disconnecting...").format(self.__userName)) |
|
556 self.__connectNetwork("", False) |
|
557 self.__nickName = "" |
|
558 self.__nickIndex = -1 |
|
559 return |
|
560 |
|
561 self.networkWidget.setNickName(nick) |
|
562 self.__send("NICK " + nick) |
|
563 |
|
564 def __handleNickInUse(self): |
|
565 """ |
|
566 Private method to handle a 443 server error. |
|
567 """ |
|
568 self.networkWidget.addServerMessage(self.trUtf8("Critical"), |
|
569 self.trUtf8("The given nickname is already in use.")) |
|
570 |
|
571 def __changeNick(self, nick): |
|
572 """ |
|
573 Private slot to use a new nick name. |
|
574 |
|
575 @param nick nick name to use (str) |
|
576 """ |
|
577 self.__send("NICK " + nick) |
|
578 |
|
579 def __setChannelTypePrefixes(self, prefixes): |
|
580 """ |
|
581 Private method to set the channel type prefixes. |
|
582 |
|
583 @param prefixes channel prefix characters (string) |
|
584 """ |
|
585 self.__channelTypePrefixes = prefixes |
|
586 |
|
587 def __isChannelName(self, name): |
|
588 """ |
|
589 Private method to check, if the given name is a channel name. |
|
590 |
|
591 @return flag indicating a channel name (boolean) |
|
592 """ |
|
593 if not name: |
|
594 return False |
|
595 |
|
596 if self.__channelTypePrefixes: |
|
597 return name[0] in self.__channelTypePrefixes |
|
598 else: |
|
599 return name[0] in "#&" |