From 01b801e747793bf708a8284e37f13469d2c9a960 Mon Sep 17 00:00:00 2001
From: Joe Robinson <joe@grabyo.com>
Date: Mon, 14 Aug 2017 14:40:32 +0100
Subject: [PATCH] Handle nick already been taken, add some output for
 connection and status messages

---
 IrcConnection.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 IrcHandler.py    | 29 +++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+)

diff --git a/IrcConnection.py b/IrcConnection.py
index 08240fe..22d7cd7 100644
--- a/IrcConnection.py
+++ b/IrcConnection.py
@@ -13,18 +13,22 @@ class ircConnectThread(QThread):
     quit_sig = pyqtSignal(str, str)
     kick_sig = pyqtSignal(str, str, str, str)
     user_mode_sig = pyqtSignal(str, str, str, str)
+    error_sig = pyqtSignal(str, str)
+    status_sig = pyqtSignal(str)
     def __init__(self, handler):
         QThread.__init__(self)
         self.reactor = irc.client.Reactor()
         self.server = self.reactor.server()
         self.handler = handler
 
+
     def __del__(self):
         self.wait()
 
     def run(self):
         try:
             self.c = self.server.connect("irc.blatech.net", 6667, self.handler.get_nick())
+            self.c.connection_complete = False
         except irc.client.ServerConnectionError:
             print(sys.exc_info()[1])
             raise SystemExit(1)
@@ -46,12 +50,35 @@ class ircConnectThread(QThread):
         self.c.add_global_handler("topicinfo", self.on_topic)
         self.c.add_global_handler("nick", self.on_nick)
         self.c.add_global_handler("motd", self.on_motd)
+        self.c.add_global_handler("motdstart", self.on_motd)
+        self.c.add_global_handler("nicknameinuse", self.on_nicknameinuse)
+        self.c.add_global_handler("welcome", self.on_connectmsg)
+        self.c.add_global_handler("yourhost", self.on_connectmsg)
+        self.c.add_global_handler("created", self.on_connectmsg)
+        self.c.add_global_handler("myinfo", self.on_connectmsg)
+        self.c.add_global_handler("featurelist", self.on_connectmsg)
+        self.c.add_global_handler("luserconns", self.on_connectmsg)
+        self.c.add_global_handler("luserclient", self.on_connectmsg)
+        self.c.add_global_handler("luserop", self.on_connectmsg)
+        self.c.add_global_handler("luserunknown", self.on_connectmsg)
+        self.c.add_global_handler("luserchannels", self.on_connectmsg)
+        self.c.add_global_handler("luserme", self.on_connectmsg)
         self.reactor.process_forever()
 
     def on_connect(self, connection, event):
+        print("connected")
+        self.c.connection_complete = True
         if irc.client.is_channel("#wtest"):
             # self.join_sig.emit("#wtest")
             return
+
+    def on_connectmsg(self, connection, event):
+        print(event)
+        status_msg = "* "
+        for status in event.arguments:
+            status_msg = status_msg + status + " "
+        self.status_sig.emit(status_msg)
+
     def on_pubmsg(self, connection, event):
         print(event)
         self.sig.emit(event.target, event.source.split("!")[0], event.arguments[0])
@@ -109,7 +136,19 @@ class ircConnectThread(QThread):
         print(event)
 
     def on_motd(self, connection, event):
+        self.status_sig.emit(event.arguments[0])
+        print(event)
+
+    def on_nicknameinuse(self, connection, event):
         print(event)
+        if (self.c.connection_complete):
+            self.error_sig.emit("Nick '" + event.arguments[0] + "' is already in use", "")
+            self.handler.set_nick(event.target)
+        else:
+            self.error_sig.emit("Nick '" + event.arguments[0] + "' is already in use, changing to " + connection.get_nickname() + "_", "")
+            self.handler.set_nick(connection.get_nickname() + "_")
+            connection.nick(connection.get_nickname() + "_")
+
 
     @pyqtSlot(str, str)
     def send_msg(self, channel, message):
@@ -119,6 +158,13 @@ class ircConnectThread(QThread):
             self.server.privmsg(channel, message)
             print(message)
 
+    @pyqtSlot(str)
+    def change_nick(self, new_nick):
+        self.handler.set_nick(new_nick)
+        self.c.nick(new_nick)
+        #TODO: handle errors such as invalid/passworded channel
+        return True
+
     @pyqtSlot(str)
     def join_channel(self, channel):
         print(channel)
diff --git a/IrcHandler.py b/IrcHandler.py
index 9fd8b39..8d0c47f 100644
--- a/IrcHandler.py
+++ b/IrcHandler.py
@@ -41,6 +41,9 @@ class IrcHandler(QObject):
     def set_nick(self, nick):
         self.nick = nick
 
+    def change_nick(self, new_nick):
+        self.irc.change_nick(new_nick)
+
     @pyqtSlot(str)
     def join_channel(self, channelStr):
         res = self.irc.join_channel(channelStr)
@@ -79,6 +82,9 @@ class IrcHandler(QObject):
                 else:
                     channel = current_channel
                 self.part_channel(channel)
+            elif (command == "nick"):
+                new_nick = params[1]
+                self.change_nick(new_nick)
         else:
             self.sig.emit(current_channel, text)
             self.window.update_chat(current_channel, "<b>&lt;" + self.nick + "&gt;</b> " + text)
@@ -91,6 +97,10 @@ class IrcHandler(QObject):
             channel = self.channels[channelStr]
             self.window.update_chat(channelStr, "<b>&lt;" + nick + "&gt;</b> " + msg)
 
+    @pyqtSlot(str)
+    def handle_status_msg(self, msg):
+        self.window.update_chat("status", msg)
+
     @pyqtSlot(str, str)
     def handle_nicks(self, channelStr, nicks):
         nick_listStr = nicks.split(" ")[0:-1]
@@ -208,6 +218,23 @@ class IrcHandler(QObject):
             channel.get_users()[target_user].set_mode(mode)
             chat_area.append(source_user + mode_chat_str + target_user)
 
+    def handle_error(self, error_msg, target):
+        #Output the error in the relevant channel if one is provided
+        if(target != ""):
+            channel_view = self.channels.get(target).get_view();
+        #Otherwise use the currently selected channel
+        else:
+            current_channel = self.window.channel_tabs.property('currentItem').property('text')
+            channel = self.channels.get(current_channel)
+            #Default to the status channel if there's an issue (probably because status is the currently selected channel)
+            if (channel == None):
+                target = "status"
+            else:
+                target = current_channel
+
+        self.window.update_chat(target, error_msg)
+
+
     def connect_to_irc(self, view):
         self.irc.sig.connect(self.handle_msg)
         self.irc.namreply_sig.connect(self.handle_nicks)
@@ -218,6 +245,8 @@ class IrcHandler(QObject):
         self.irc.kick_sig.connect(self.handle_kick)
         self.irc.topic_sig.connect(self.handle_topic)
         self.irc.user_mode_sig.connect(self.handle_user_mode)
+        self.irc.error_sig.connect(self.handle_error)
+        self.irc.status_sig.connect(self.handle_status_msg)
         # self.irc.join_sig.connect(self.join_channel)
         self.irc.start()
         self.sig.connect(self.irc.send_msg)
-- 
GitLab