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:`||
|`:cool:`||
|`:smooth:`||
-|`:distraughtfirman`||
+|`:distraughtfirman:`||
|`:distraught:`||
|`:insolent:`||
|`:bemused:`||
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"