Network/IRC/IrcWidget.py

changeset 6514
f11a703e4664
parent 6181
2ae7e332b941
child 6587
a04952159050
equal deleted inserted replaced
6513:e1fcd71fbda3 6514:f11a703e4664
14 pass 14 pass
15 15
16 import re 16 import re
17 import logging 17 import logging
18 18
19 from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QByteArray, QTimer 19 from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QByteArray, QTimer, \
20 QDateTime
20 from PyQt5.QtWidgets import QWidget, QToolButton, QLabel, QTabWidget 21 from PyQt5.QtWidgets import QWidget, QToolButton, QLabel, QTabWidget
21 from PyQt5.QtNetwork import QTcpSocket, QAbstractSocket 22 from PyQt5.QtNetwork import QTcpSocket, QAbstractSocket
22 try: 23 try:
23 from PyQt5.QtNetwork import QSslSocket, QSslConfiguration 24 from PyQt5.QtNetwork import QSslSocket, QSslConfiguration
24 from E5Network.E5SslErrorHandler import E5SslErrorHandler 25 from E5Network.E5SslErrorHandler import E5SslErrorHandler
125 # all initialized, do connections now 126 # all initialized, do connections now
126 self.__ircNetworkManager.dataChanged.connect(self.__networkDataChanged) 127 self.__ircNetworkManager.dataChanged.connect(self.__networkDataChanged)
127 self.networkWidget.initialize(self.__ircNetworkManager) 128 self.networkWidget.initialize(self.__ircNetworkManager)
128 self.networkWidget.connectNetwork.connect(self.__connectNetwork) 129 self.networkWidget.connectNetwork.connect(self.__connectNetwork)
129 self.networkWidget.editNetwork.connect(self.__editNetwork) 130 self.networkWidget.editNetwork.connect(self.__editNetwork)
130 self.networkWidget.joinChannel.connect(self.__joinChannel) 131 self.networkWidget.joinChannel.connect(self.joinChannel)
131 self.networkWidget.nickChanged.connect(self.__changeNick) 132 self.networkWidget.nickChanged.connect(self.__changeNick)
132 self.networkWidget.sendData.connect(self.__send) 133 self.networkWidget.sendData.connect(self.__send)
133 self.networkWidget.away.connect(self.__away) 134 self.networkWidget.away.connect(self.__away)
134 self.networkWidget.autoConnected.connect(self.autoConnected) 135 self.networkWidget.autoConnected.connect(self.autoConnected)
135 136
286 if identity: 287 if identity:
287 partMsg = identity.getPartMessage() 288 partMsg = identity.getPartMessage()
288 for channel in self.__channelList: 289 for channel in self.__channelList:
289 channel.setPartMessage(partMsg) 290 channel.setPartMessage(partMsg)
290 291
291 def __joinChannel(self, name, key=""): 292 def joinChannel(self, name, key=""):
292 """ 293 """
293 Private slot to join a channel. 294 Public slot to join a channel.
294 295
295 @param name name of the channel (string) 296 @param name name of the channel (string)
296 @param key key of the channel (string) 297 @param key key of the channel (string)
297 """ 298 """
298 # step 1: check, if this channel is already joined 299 # step 1: check, if this channel is already joined
308 channel.setPartMessage(identity.getPartMessage()) 309 channel.setPartMessage(identity.getPartMessage())
309 channel.setUserPrivilegePrefix(self.__userPrefix) 310 channel.setUserPrivilegePrefix(self.__userPrefix)
310 channel.initAutoWho() 311 channel.initAutoWho()
311 312
312 channel.sendData.connect(self.__send) 313 channel.sendData.connect(self.__send)
314 channel.sendCtcpRequest.connect(self.__sendCtcpRequest)
313 channel.sendCtcpReply.connect(self.__sendCtcpReply) 315 channel.sendCtcpReply.connect(self.__sendCtcpReply)
314 channel.channelClosed.connect(self.__closeChannel) 316 channel.channelClosed.connect(self.__closeChannel)
315 channel.openPrivateChat.connect(self.__openPrivate) 317 channel.openPrivateChat.connect(self.__openPrivate)
318 channel.awayCommand.connect(self.networkWidget.handleAwayCommand)
319 channel.leaveChannels.connect(self.__leaveChannels)
320 channel.leaveAllChannels.connect(self.__leaveAllChannels)
316 321
317 self.channelsWidget.addTab(channel, name) 322 self.channelsWidget.addTab(channel, name)
318 self.__channelList.append(channel) 323 self.__channelList.append(channel)
319 self.channelsWidget.setCurrentWidget(channel) 324 self.channelsWidget.setCurrentWidget(channel)
320 325
369 channel.setUserPrivilegePrefix(self.__userPrefix) 374 channel.setUserPrivilegePrefix(self.__userPrefix)
370 channel.setPrivate(True, name) 375 channel.setPrivate(True, name)
371 channel.addUsers([name, self.__nickName]) 376 channel.addUsers([name, self.__nickName])
372 377
373 channel.sendData.connect(self.__send) 378 channel.sendData.connect(self.__send)
379 channel.sendCtcpRequest.connect(self.__sendCtcpRequest)
374 channel.sendCtcpReply.connect(self.__sendCtcpReply) 380 channel.sendCtcpReply.connect(self.__sendCtcpReply)
375 channel.channelClosed.connect(self.__closeChannel) 381 channel.channelClosed.connect(self.__closeChannel)
382 channel.awayCommand.connect(self.networkWidget.handleAwayCommand)
383 channel.leaveChannels.connect(self.__leaveChannels)
384 channel.leaveAllChannels.connect(self.__leaveAllChannels)
376 385
377 self.channelsWidget.addTab(channel, name) 386 self.channelsWidget.addTab(channel, name)
378 self.__channelList.append(channel) 387 self.__channelList.append(channel)
379 self.channelsWidget.setCurrentWidget(channel) 388 self.channelsWidget.setCurrentWidget(channel)
380 389
383 """ 392 """
384 Private slot to leave a channel and close the associated tab. 393 Private slot to leave a channel and close the associated tab.
385 """ 394 """
386 channel = self.channelsWidget.currentWidget() 395 channel = self.channelsWidget.currentWidget()
387 channel.requestLeave() 396 channel.requestLeave()
397
398 @pyqtSlot(list)
399 def __leaveChannels(self, channelNames):
400 """
401 Private slot to leave a list of channels and close their associated
402 tabs.
403
404 @param channelNames list of channels to leave
405 @type list of str
406 """
407 for channelName in channelNames:
408 for channel in self.__channelList:
409 if channel.name() == channelName:
410 channel.leaveChannel()
411
412 @pyqtSlot()
413 def __leaveAllChannels(self):
414 """
415 Private slot to leave all channels and close their tabs.
416 """
417 while self.__channelList:
418 channel = self.__channelList[0]
419 channel.leaveChannel()
388 420
389 def __closeAllChannels(self): 421 def __closeAllChannels(self):
390 """ 422 """
391 Private method to close all channels. 423 Private method to close all channels.
392 """ 424 """
439 """ 471 """
440 if self.__socket: 472 if self.__socket:
441 self.__socket.write( 473 self.__socket.write(
442 QByteArray("{0}\r\n".format(data).encode("utf-8"))) 474 QByteArray("{0}\r\n".format(data).encode("utf-8")))
443 475
476 def __sendCtcpRequest(self, receiver, request, arguments):
477 """
478 Private slot to send a CTCP request.
479
480 @param receiver nick name of the receiver
481 @type str
482 @param request CTCP request to be sent
483 @type str
484 @param arguments arguments to be sent
485 @type str
486 """
487 request = request.upper()
488 if request == "PING":
489 arguments = "Eric IRC {0}".format(
490 QDateTime.currentMSecsSinceEpoch())
491
492 self.__send("PRIVMSG {0} :\x01{1} {2}\x01".format(
493 receiver, request, arguments))
494
444 def __sendCtcpReply(self, receiver, text): 495 def __sendCtcpReply(self, receiver, text):
445 """ 496 """
446 Private slot to send a CTCP reply. 497 Private slot to send a CTCP reply.
447 498
448 @param receiver nick name of the receiver (string) 499 @param receiver nick name of the receiver
449 @param text text to be sent (string) 500 @type str
501 @param text text to be sent
502 @type str
450 """ 503 """
451 self.__send("NOTICE {0} :\x01{1}\x01".format(receiver, text)) 504 self.__send("NOTICE {0} :\x01{1}\x01".format(receiver, text))
452 505
453 def __hostFound(self): 506 def __hostFound(self):
454 """ 507 """
549 "<br/>{0}").format(line)) 602 "<br/>{0}").format(line))
550 603
551 self.__updateUsersCount() 604 self.__updateUsersCount()
552 self.__buffer = "" 605 self.__buffer = ""
553 606
607 def __handleCtcpReply(self, match):
608 """
609 Private method to handle a server message containing a CTCP reply.
610
611 @param match reference to the match object
612 """
613 if "!" in match.group(1):
614 sender = match.group(1).split("!", 1)[0]
615
616 try:
617 ctcpCommand = match.group(3).split(":", 1)[1]
618 except IndexError:
619 ctcpCommand = match.group(3)
620 ctcpCommand = ctcpCommand[1:].split("\x01", 1)[0]
621 if " " in ctcpCommand:
622 ctcpReply, ctcpArg = ctcpCommand.split(" ", 1)
623 else:
624 ctcpReply, ctcpArg = ctcpCommand, ""
625 ctcpReply = ctcpReply.upper()
626
627 if ctcpReply == "PING" and ctcpArg.startswith("Eric IRC "):
628 # it is a response to a ping request
629 pingDateTime = int(ctcpArg.split()[-1])
630 latency = QDateTime.currentMSecsSinceEpoch() - pingDateTime
631 self.networkWidget.addServerMessage(
632 self.tr("CTCP"),
633 self.tr(
634 "Received CTCP-PING response from {0} with latency"
635 " of {1} ms.").format(sender, latency))
636 else:
637 self.networkWidget.addServerMessage(
638 self.tr("CTCP"),
639 self.tr(
640 "Received unknown CTCP-{0} response from {1}.")
641 .format(ctcpReply, sender))
642
554 def __handleNamedMessage(self, match): 643 def __handleNamedMessage(self, match):
555 """ 644 """
556 Private method to handle a server message containing a message name. 645 Private method to handle a server message containing a message name.
557 646
558 @param match reference to the match object 647 @param match reference to the match object
562 if name == "NOTICE": 651 if name == "NOTICE":
563 try: 652 try:
564 msg = match.group(3).split(":", 1)[1] 653 msg = match.group(3).split(":", 1)[1]
565 except IndexError: 654 except IndexError:
566 msg = match.group(3) 655 msg = match.group(3)
656
657 if msg.startswith("\x01"):
658 self.__handleCtcpReply(match)
659 return True
660
567 if "!" in match.group(1): 661 if "!" in match.group(1):
568 name = match.group(1).split("!", 1)[0] 662 name = match.group(1).split("!", 1)[0]
569 msg = "-{0}- {1}".format(name, msg) 663 msg = "-{0}- {1}".format(name, msg)
570 self.networkWidget.addServerMessage(self.tr("Notice"), msg) 664 self.networkWidget.addServerMessage(self.tr("Notice"), msg)
571 return True 665 return True
610 else: 704 else:
611 self.networkWidget.addMessage( 705 self.networkWidget.addMessage(
612 self.tr("User {0} is now known as {1}.").format( 706 self.tr("User {0} is now known as {1}.").format(
613 oldNick, newNick)) 707 oldNick, newNick))
614 return True 708 return True
709 elif name == "PONG":
710 nick = match.group(3).split(":", 1)[1]
711 self.networkWidget.addMessage(
712 self.tr("Received PONG from {0}").format(nick))
713 return True
615 elif name == "ERROR": 714 elif name == "ERROR":
616 self.networkWidget.addErrorMessage( 715 self.networkWidget.addErrorMessage(
617 self.tr("Server Error"), match.group(3).split(":", 1)[1]) 716 self.tr("Server Error"), match.group(3).split(":", 1)[1])
618 return True 717 return True
619 718
747 """ 846 """
748 for channel in self.networkWidget.getNetworkChannels(): 847 for channel in self.networkWidget.getNetworkChannels():
749 if channel.autoJoin(): 848 if channel.autoJoin():
750 name = channel.getName() 849 name = channel.getName()
751 key = channel.getKey() 850 key = channel.getKey()
752 self.__joinChannel(name, key) 851 self.joinChannel(name, key)
753 852
754 def __tcpError(self, error): 853 def __tcpError(self, error):
755 """ 854 """
756 Private slot to handle errors reported by the TCP socket. 855 Private slot to handle errors reported by the TCP socket.
757 856

eric ide

mercurial