diff --git a/CHANGELOG.md b/CHANGELOG.md index fb340ed..5acaf74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,17 @@ # Changelog (This document uses YYYY-MM-DD) +## [v2.4.4] - 2022-09-10 + +### Added + - Desync check, verify connection is alive when system time changes by multiple minutes. + +### Changed + - Made outgoing irc.py functions do an extra check if connection/cli exists. + +### Fixed + - The string for the distraughtfirman smilie being ":distraughtfirman" instead of ":distraughtfirman:". + ## [v2.4.3] - 2022-09-06 ### Added diff --git a/README.md b/README.md index e311faf..72d17dc 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,7 @@ Ideally, you'll want to create and activate a [virtual environment](https://docs |`:chummy:`|:chummy: pesterchum smilie/emote| |`:cool:`|:cool: pesterchum smilie/emote| |`:smooth:`|:smooth: pesterchum smilie/emote| -|`:distraughtfirman`|:distraughtfirman pesterchum smilie/emote| +|`:distraughtfirman:`|:distraughtfirman: pesterchum smilie/emote| |`:distraught:`|:distraught: pesterchum smilie/emote| |`:insolent:`|:insolent: pesterchum smilie/emote| |`:bemused:`|:bemused: pesterchum smilie/emote| diff --git a/irc.py b/irc.py index 0fad301..5553540 100644 --- a/irc.py +++ b/irc.py @@ -123,267 +123,287 @@ class PesterIRC(QtCore.QThread): @QtCore.pyqtSlot(PesterProfile) def getMood(self, *chums): - self.cli.command_handler.getMood(*chums) + if hasattr(self, 'cli'): + self.cli.command_handler.getMood(*chums) @QtCore.pyqtSlot(PesterList) def getMoods(self, chums): - self.cli.command_handler.getMood(*chums) + if hasattr(self, 'cli'): + self.cli.command_handler.getMood(*chums) @QtCore.pyqtSlot(QString, QString) def sendNotice(self, text, handle): - h = str(handle) - t = str(text) - try: - helpers.notice(self.cli, h, t) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + h = str(handle) + t = str(text) + try: + helpers.notice(self.cli, h, t) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot(QString, QString) def sendMessage(self, text, handle): - h = str(handle) - textl = [str(text)] - def splittext(l): - if len(l[0]) > 450: - space = l[0].rfind(" ", 0,430) - if space == -1: - space = 450 - elif l[0][space+1:space+5] == "": - space = space+4 - a = l[0][0:space+1] - b = l[0][space+1:] - if a.count(" a.count(""): - # oh god ctags will break!! D= - hanging = [] - usedends = [] - c = a.rfind("", c) - while d in usedends: - d = a.find("", d+1) - if d != -1: usedends.append(d) - else: - f = a.find(">", c)+1 - hanging.append(a[c:f]) - c = a.rfind(" 450: + space = l[0].rfind(" ", 0,430) + if space == -1: + space = 450 + elif l[0][space+1:space+5] == "": + space = space+4 + a = l[0][0:space+1] + b = l[0][space+1:] + if a.count(" a.count(""): + # oh god ctags will break!! D= + hanging = [] + usedends = [] + c = a.rfind("", c) + while d in usedends: + d = a.find("", d+1) + if d != -1: usedends.append(d) + else: + f = a.find(">", c)+1 + hanging.append(a[c:f]) + c = a.rfind("")): - a = a + "" - #start them up again in the second part - for c in hanging: - b = c + b - if len(b) > 0: - return [a] + splittext([b]) + # end all ctags in first part + for i in range(a.count("")): + a = a + "" + #start them up again in the second part + for c in hanging: + b = c + b + if len(b) > 0: + return [a] + splittext([b]) + else: + return [a] else: - return [a] - else: - return l - textl = splittext(textl) - try: - for t in textl: - helpers.msg(self.cli, h, t) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + return l + textl = splittext(textl) + try: + for t in textl: + helpers.msg(self.cli, h, t) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot(QString, QString,) def sendCTCP(self, handle, text): - #cmd = text.split(' ')[0] - #msg = text.replace(cmd + ' ', '') - #msg = msg.replace(cmd, '') - try: - helpers.ctcp(self.cli, handle, text) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + try: + helpers.ctcp(self.cli, handle, text) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot(QString, bool) def startConvo(self, handle, initiated): - h = str(handle) - try: - helpers.msg(self.cli, h, "COLOR >%s" % (self.mainwindow.profile().colorcmd())) - if initiated: - helpers.msg(self.cli, h, "PESTERCHUM:BEGIN") - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() - @QtCore.pyqtSlot(QString) - def endConvo(self, handle): - h = str(handle) - try: - helpers.msg(self.cli, h, "PESTERCHUM:CEASE") - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() - @QtCore.pyqtSlot() - def updateProfile(self): - me = self.mainwindow.profile() - handle = me.handle - try: - helpers.nick(self.cli, handle) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() - self.mainwindow.closeConversations(True) - self.mainwindow.doAutoIdentify() - self.mainwindow.autoJoinDone = False - self.mainwindow.doAutoJoins() - self.updateMood() - @QtCore.pyqtSlot() - def updateMood(self): - me = self.mainwindow.profile() - # Moods via metadata - try: - helpers.metadata(self.cli, '*', "set", "mood", str(me.mood.value())) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() - # Backwards compatibility - try: - helpers.msg(self.cli, "#pesterchum", "MOOD >%d" % (me.mood.value())) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() - @QtCore.pyqtSlot() - def updateColor(self): - #PchumLog.debug("irc updateColor (outgoing)") - #me = self.mainwindow.profile() - # Update color metadata field - try: - color = self.mainwindow.profile().color - helpers.metadata(self.cli, '*', "set", "color", str(color.name())) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() - # Send color messages - for h in list(self.mainwindow.convos.keys()): + if hasattr(self, 'cli'): + h = str(handle) try: helpers.msg(self.cli, h, "COLOR >%s" % (self.mainwindow.profile().colorcmd())) + if initiated: + helpers.msg(self.cli, h, "PESTERCHUM:BEGIN") except OSError as e: PchumLog.warning(e) self.setConnectionBroken() @QtCore.pyqtSlot(QString) + def endConvo(self, handle): + if hasattr(self, 'cli'): + h = str(handle) + try: + helpers.msg(self.cli, h, "PESTERCHUM:CEASE") + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() + @QtCore.pyqtSlot() + def updateProfile(self): + if hasattr(self, 'cli'): + me = self.mainwindow.profile() + handle = me.handle + try: + helpers.nick(self.cli, handle) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() + self.mainwindow.closeConversations(True) + self.mainwindow.doAutoIdentify() + self.mainwindow.autoJoinDone = False + self.mainwindow.doAutoJoins() + self.updateMood() + @QtCore.pyqtSlot() + def updateMood(self): + if hasattr(self, 'cli'): + me = self.mainwindow.profile() + # Moods via metadata + try: + helpers.metadata(self.cli, '*', "set", "mood", str(me.mood.value())) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() + # Backwards compatibility + try: + helpers.msg(self.cli, "#pesterchum", "MOOD >%d" % (me.mood.value())) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() + @QtCore.pyqtSlot() + def updateColor(self): + if hasattr(self, 'cli'): + #PchumLog.debug("irc updateColor (outgoing)") + #me = self.mainwindow.profile() + # Update color metadata field + try: + color = self.mainwindow.profile().color + helpers.metadata(self.cli, '*', "set", "color", str(color.name())) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() + # Send color messages + for h in list(self.mainwindow.convos.keys()): + try: + helpers.msg(self.cli, h, "COLOR >%s" % (self.mainwindow.profile().colorcmd())) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() + @QtCore.pyqtSlot(QString) def blockedChum(self, handle): - h = str(handle) - try: - helpers.msg(self.cli, h, "PESTERCHUM:BLOCK") - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + h = str(handle) + try: + helpers.msg(self.cli, h, "PESTERCHUM:BLOCK") + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot(QString) def unblockedChum(self, handle): - h = str(handle) - try: - helpers.msg(self.cli, h, "PESTERCHUM:UNBLOCK") - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + h = str(handle) + try: + helpers.msg(self.cli, h, "PESTERCHUM:UNBLOCK") + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot(QString) def requestNames(self, channel): - c = str(channel) - try: - helpers.names(self.cli, c) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + c = str(channel) + try: + helpers.names(self.cli, c) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot() def requestChannelList(self): - try: - helpers.channel_list(self.cli) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + try: + helpers.channel_list(self.cli) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot(QString) def joinChannel(self, channel): - c = str(channel) - try: - helpers.join(self.cli, c) - helpers.mode(self.cli, c, "", None) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + c = str(channel) + try: + helpers.join(self.cli, c) + helpers.mode(self.cli, c, "", None) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot(QString) def leftChannel(self, channel): - c = str(channel) - try: - helpers.part(self.cli, c) - self.cli.command_handler.joined = False - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + c = str(channel) + try: + helpers.part(self.cli, c) + self.cli.command_handler.joined = False + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot(QString, QString) def kickUser(self, handle, channel): - l = handle.split(":") - c = str(channel) - h = str(l[0]) - if len(l) > 1: - reason = str(l[1]) - if len(l) > 2: - for x in l[2:]: - reason += str(":") + str(x) - else: - reason = "" - try: - helpers.kick(self.cli, h, c, reason) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + l = handle.split(":") + c = str(channel) + h = str(l[0]) + if len(l) > 1: + reason = str(l[1]) + if len(l) > 2: + for x in l[2:]: + reason += str(":") + str(x) + else: + reason = "" + try: + helpers.kick(self.cli, h, c, reason) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot(QString, QString, QString) def setChannelMode(self, channel, mode, command): - c = str(channel) - m = str(mode) - cmd = str(command) - PchumLog.debug("c=%s\nm=%s\ncmd=%s" % (c,m,cmd)) - if cmd == "": - cmd = None - try: - helpers.mode(self.cli, c, m, cmd) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + c = str(channel) + m = str(mode) + cmd = str(command) + PchumLog.debug("c=%s\nm=%s\ncmd=%s" % (c,m,cmd)) + if cmd == "": + cmd = None + try: + helpers.mode(self.cli, c, m, cmd) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot(QString) def channelNames(self, channel): - c = str(channel) - try: - helpers.names(self.cli, c) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + c = str(channel) + try: + helpers.names(self.cli, c) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot(QString, QString) def inviteChum(self, handle, channel): - h = str(handle) - c = str(channel) - try: - helpers.invite(self.cli, h, c) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + h = str(handle) + c = str(channel) + try: + helpers.invite(self.cli, h, c) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot() def pingServer(self): - try: - if hasattr(self, 'cli'): - self.cli.send("PING :B33") - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + try: + if hasattr(self, 'cli'): + self.cli.send("PING :B33") + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot(bool) def setAway(self, away=True): - try: - if away: - self.cli.send("AWAY Idle") - else: - self.cli.send("AWAY") - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + try: + if away: + self.cli.send("AWAY Idle") + else: + self.cli.send("AWAY") + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot(QString, QString) def killSomeQuirks(self, channel, handle): - c = str(channel) - h = str(handle) - try: - helpers.ctcp(self.cli, c, "NOQUIRKS", h) - except OSError as e: - PchumLog.warning(e) - self.setConnectionBroken() + if hasattr(self, 'cli'): + c = str(channel) + h = str(handle) + try: + helpers.ctcp(self.cli, c, "NOQUIRKS", h) + except OSError as e: + PchumLog.warning(e) + self.setConnectionBroken() @QtCore.pyqtSlot() def disconnectIRC(self): diff --git a/menus.py b/menus.py index 58a7d28..193d2b2 100644 --- a/menus.py +++ b/menus.py @@ -1815,6 +1815,8 @@ class LoadingScreen(QtWidgets.QDialog): #self.setWindowModality(QtCore.Qt.WindowModality.NonModal) # useless #self.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose) # useless self.loadinglabel = QtWidgets.QLabel("CONN3CT1NG", self) + #self.loadinglabel.setTextFormat(QtCore.Qt.TextFormat.RichText) # Clickable html links + #self.loadinglabel.setWordWrap(True) # Unusable because of QT clipping bug (QTBUG-92381) self.cancel = QtWidgets.QPushButton("QU1T >:?", self) self.ok = QtWidgets.QPushButton("R3CONN3CT >:]", self) # Help reduce the number of accidental Pesterchum closures... :| diff --git a/parsetools.py b/parsetools.py index ab6ff79..7e613a1 100644 --- a/parsetools.py +++ b/parsetools.py @@ -958,7 +958,7 @@ smiledict = { ":chummy:": "pc_chummy.png", ":cool:": "pccool.png", ":smooth:": "pccool.png", - ":distraughtfirman": "pc_distraughtfirman.png", + ":distraughtfirman:": "pc_distraughtfirman.png", ":distraught:": "pc_distraught.png", ":insolent:": "pc_insolent.png", ":bemused:": "pc_bemused.png", diff --git a/pesterchum.py b/pesterchum.py old mode 100644 new mode 100755 index 75ced63..2e053a8 --- a/pesterchum.py +++ b/pesterchum.py @@ -1434,6 +1434,7 @@ class PesterWindow(MovingWindow): self.pingtimer = QtCore.QTimer() self.pingtimer.timeout.connect(self.checkPing) self.sincerecv = 0 # Time since last recv + self.lastCheckPing = None @QtCore.pyqtSlot(QString, QString) def updateMsg(self, ver, url): @@ -1465,7 +1466,20 @@ class PesterWindow(MovingWindow): this function is called every 15sec''' # Return without irc if hasattr(self.parent, 'irc') == False: + self.lastCheckPing = None + self.sincerecv = 0 return + + # Desync check, happens if pc comes out of sleep. + currentTime = time.time() + timeDif = abs(currentTime - self.lastCheckPing) + if timeDif > 180: # default UnrealIRCd ping timeout time. + # 180 is the default UnrealIRCd ping timeout time. + PchumLog.warning(("Possible desync, system time changed by %s " + "seconds since last check. abs(%s - %s)") + % (timeDif, currentTime, self.lastCheckPing)) + self.sincerecv = 85 # Allows one more ping attempt before disconnect. + self.lastCheckPing = time.time() # Presume connection is dead after 90 seconds of silence. if self.sincerecv >= 90: @@ -1481,15 +1495,17 @@ class PesterWindow(MovingWindow): self.setFocus() else: self.parent.irc.unresponsive = False - if self.loadingscreen: - self.loadingscreen.done(QtWidgets.QDialog.DialogCode.Accepted) - + if hasattr(self, 'loadingscreen'): + if self.loadingscreen != None: + PchumLog.warning("Server alive !! :O") + self.loadingscreen.done(QtWidgets.QDialog.DialogCode.Accepted) + self.loadingscreen = None # Send a ping if it's been 30 seconds since we've heard from the server. if self.sincerecv >= 30: self.pingServer.emit() - self.sincerecv += 15 # Only updating every 15s is better for performance. + self.sincerecv += 5 # Not updating too frequently is better for performance. def profile(self): return self.userprofile.chat @@ -2163,11 +2179,17 @@ class PesterWindow(MovingWindow): self.doAutoJoins() # Start client --> server pings - if hasattr(self, 'pingtimer') == False: - self.pingtimer.start(1000*15) # time in ms + if hasattr(self, 'pingtimer'): + self.pingtimer.start(1000*5) # time in ms else: - self.pingtimer.start(1000*15) + PchumLog.warning("No ping timer.") + # Desync check + if hasattr(self, 'lastCheckPing'): + self.lastCheckPing = time.time() + else: + PchumLog.warning("No ping timer.") + @QtCore.pyqtSlot() def blockSelectedChum(self): curChumListing = self.chumList.currentItem() diff --git a/quirks/gradient.py b/quirks/gradient.py index 08bd2f7..d585ac9 100644 --- a/quirks/gradient.py +++ b/quirks/gradient.py @@ -112,7 +112,7 @@ smiledict = { ":chummy:": "pc_chummy.png", ":cool:": "pccool.png", ":smooth:": "pccool.png", - ":distraughtfirman": "pc_distraughtfirman.png", + ":distraughtfirman:": "pc_distraughtfirman.png", ":distraught:": "pc_distraught.png", ":insolent:": "pc_insolent.png", ":bemused:": "pc_bemused.png", diff --git a/version.py b/version.py index 57745f8..76e1e2a 100644 --- a/version.py +++ b/version.py @@ -1,2 +1,2 @@ -_pcVersion = "Alt. v2.4.3" -buildVersion = "v2.4.3" +_pcVersion = "Alt. v2.4.4" +buildVersion = "v2.4.4"