Network/IRC/IrcWidget.py

changeset 6514
f11a703e4664
parent 6181
2ae7e332b941
child 6587
a04952159050
diff -r e1fcd71fbda3 -r f11a703e4664 Network/IRC/IrcWidget.py
--- a/Network/IRC/IrcWidget.py	Fri Sep 28 20:07:25 2018 +0200
+++ b/Network/IRC/IrcWidget.py	Sat Sep 29 19:32:33 2018 +0200
@@ -16,7 +16,8 @@
 import re
 import logging
 
-from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QByteArray, QTimer
+from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QByteArray, QTimer, \
+    QDateTime
 from PyQt5.QtWidgets import QWidget, QToolButton, QLabel, QTabWidget
 from PyQt5.QtNetwork import QTcpSocket, QAbstractSocket
 try:
@@ -127,7 +128,7 @@
         self.networkWidget.initialize(self.__ircNetworkManager)
         self.networkWidget.connectNetwork.connect(self.__connectNetwork)
         self.networkWidget.editNetwork.connect(self.__editNetwork)
-        self.networkWidget.joinChannel.connect(self.__joinChannel)
+        self.networkWidget.joinChannel.connect(self.joinChannel)
         self.networkWidget.nickChanged.connect(self.__changeNick)
         self.networkWidget.sendData.connect(self.__send)
         self.networkWidget.away.connect(self.__away)
@@ -288,9 +289,9 @@
             for channel in self.__channelList:
                 channel.setPartMessage(partMsg)
     
-    def __joinChannel(self, name, key=""):
+    def joinChannel(self, name, key=""):
         """
-        Private slot to join a channel.
+        Public slot to join a channel.
         
         @param name name of the channel (string)
         @param key key of the channel (string)
@@ -310,9 +311,13 @@
         channel.initAutoWho()
         
         channel.sendData.connect(self.__send)
+        channel.sendCtcpRequest.connect(self.__sendCtcpRequest)
         channel.sendCtcpReply.connect(self.__sendCtcpReply)
         channel.channelClosed.connect(self.__closeChannel)
         channel.openPrivateChat.connect(self.__openPrivate)
+        channel.awayCommand.connect(self.networkWidget.handleAwayCommand)
+        channel.leaveChannels.connect(self.__leaveChannels)
+        channel.leaveAllChannels.connect(self.__leaveAllChannels)
         
         self.channelsWidget.addTab(channel, name)
         self.__channelList.append(channel)
@@ -371,8 +376,12 @@
         channel.addUsers([name, self.__nickName])
         
         channel.sendData.connect(self.__send)
+        channel.sendCtcpRequest.connect(self.__sendCtcpRequest)
         channel.sendCtcpReply.connect(self.__sendCtcpReply)
         channel.channelClosed.connect(self.__closeChannel)
+        channel.awayCommand.connect(self.networkWidget.handleAwayCommand)
+        channel.leaveChannels.connect(self.__leaveChannels)
+        channel.leaveAllChannels.connect(self.__leaveAllChannels)
         
         self.channelsWidget.addTab(channel, name)
         self.__channelList.append(channel)
@@ -386,6 +395,29 @@
         channel = self.channelsWidget.currentWidget()
         channel.requestLeave()
     
+    @pyqtSlot(list)
+    def __leaveChannels(self, channelNames):
+        """
+        Private slot to leave a list of channels and close their associated
+        tabs.
+        
+        @param channelNames list of channels to leave
+        @type list of str
+        """
+        for channelName in channelNames:
+            for channel in self.__channelList:
+                if channel.name() == channelName:
+                    channel.leaveChannel()
+    
+    @pyqtSlot()
+    def __leaveAllChannels(self):
+        """
+        Private slot to leave all channels and close their tabs.
+        """
+        while self.__channelList:
+            channel = self.__channelList[0]
+            channel.leaveChannel()
+    
     def __closeAllChannels(self):
         """
         Private method to close all channels.
@@ -441,12 +473,33 @@
             self.__socket.write(
                 QByteArray("{0}\r\n".format(data).encode("utf-8")))
     
+    def __sendCtcpRequest(self, receiver, request, arguments):
+        """
+        Private slot to send a CTCP request.
+        
+        @param receiver nick name of the receiver
+        @type str
+        @param request CTCP request to be sent
+        @type str
+        @param arguments arguments to be sent
+        @type str
+        """
+        request = request.upper()
+        if request == "PING":
+            arguments = "Eric IRC {0}".format(
+                QDateTime.currentMSecsSinceEpoch())
+            
+        self.__send("PRIVMSG {0} :\x01{1} {2}\x01".format(
+            receiver, request, arguments))
+    
     def __sendCtcpReply(self, receiver, text):
         """
         Private slot to send a CTCP reply.
         
-        @param receiver nick name of the receiver (string)
-        @param text text to be sent (string)
+        @param receiver nick name of the receiver
+        @type str
+        @param text text to be sent
+        @type str
         """
         self.__send("NOTICE {0} :\x01{1}\x01".format(receiver, text))
     
@@ -551,6 +604,42 @@
                 self.__updateUsersCount()
                 self.__buffer = ""
     
+    def __handleCtcpReply(self, match):
+        """
+        Private method to handle a server message containing a CTCP reply.
+        
+        @param match reference to the match object
+        """
+        if "!" in match.group(1):
+            sender = match.group(1).split("!", 1)[0]
+            
+            try:
+                ctcpCommand = match.group(3).split(":", 1)[1]
+            except IndexError:
+                ctcpCommand = match.group(3)
+            ctcpCommand = ctcpCommand[1:].split("\x01", 1)[0]
+            if " " in ctcpCommand:
+                ctcpReply, ctcpArg = ctcpCommand.split(" ", 1)
+            else:
+                ctcpReply, ctcpArg = ctcpCommand, ""
+            ctcpReply = ctcpReply.upper()
+            
+            if ctcpReply == "PING" and ctcpArg.startswith("Eric IRC "):
+                # it is a response to a ping request
+                pingDateTime = int(ctcpArg.split()[-1])
+                latency = QDateTime.currentMSecsSinceEpoch() - pingDateTime
+                self.networkWidget.addServerMessage(
+                    self.tr("CTCP"),
+                    self.tr(
+                        "Received CTCP-PING response from {0} with latency"
+                        " of {1} ms.").format(sender, latency))
+            else:
+                self.networkWidget.addServerMessage(
+                    self.tr("CTCP"),
+                    self.tr(
+                        "Received unknown CTCP-{0} response from {1}.")
+                    .format(ctcpReply, sender))
+    
     def __handleNamedMessage(self, match):
         """
         Private method to handle a server message containing a message name.
@@ -564,6 +653,11 @@
                 msg = match.group(3).split(":", 1)[1]
             except IndexError:
                 msg = match.group(3)
+            
+            if msg.startswith("\x01"):
+                self.__handleCtcpReply(match)
+                return True
+            
             if "!" in match.group(1):
                 name = match.group(1).split("!", 1)[0]
                 msg = "-{0}- {1}".format(name, msg)
@@ -612,6 +706,11 @@
                     self.tr("User {0} is now known as {1}.").format(
                         oldNick, newNick))
             return True
+        elif name == "PONG":
+            nick = match.group(3).split(":", 1)[1]
+            self.networkWidget.addMessage(
+                self.tr("Received PONG from {0}").format(nick))
+            return True
         elif name == "ERROR":
             self.networkWidget.addErrorMessage(
                 self.tr("Server Error"), match.group(3).split(":", 1)[1])
@@ -749,7 +848,7 @@
             if channel.autoJoin():
                 name = channel.getName()
                 key = channel.getKey()
-                self.__joinChannel(name, key)
+                self.joinChannel(name, key)
     
     def __tcpError(self, error):
         """

eric ide

mercurial