Error when failing to join memo, services notices, no toast icon fill by default

This commit is contained in:
Dpeta 2022-06-30 09:59:34 +02:00
parent 6ffcc59b91
commit 4e2035408c
8 changed files with 122 additions and 63 deletions

View file

@ -1,16 +1,15 @@
# TODO LIST : ) # TODO LIST : )
## ADD ## ADD
- Memoserv support. - ~~Memoserv support.~~
- Use memopermabanmsg function? - ~~Use memopermabanmsg function?~~ <--- Permabans just give a KICK server response, there's no way to check for this.
## FIX ## FIX
- Mask & target not being passed to ``_max_msg_len``. - Mask & target not being passed to ``_max_msg_len``.
- No error message when Pesterchum fails to join a channel. (For example, when the channel name length is over CHANNELLEN) - Is this even possible to keep updated reliably?
- ~~No error message when Pesterchum fails to join a channel. (For example, when the channel name length is over CHANNELLEN)~~
- Choose memo window doesn't get updated on theme change. - Choose memo window doesn't get updated on theme change.
- Right click menu's color doesn't get updated on theme change in memos. - Right click menu's color doesn't get updated on theme change in memos.
- Closed windows sometimes stay open.
- Should confirm if this is still an issue.
- help() causes console to crash...? - help() causes console to crash...?
- Console is hopelessly broken, it'd be easier to make a list of what commands *don't* cause it to crash. Does anyone use this? - Console is hopelessly broken, it'd be easier to make a list of what commands *don't* cause it to crash. Does anyone use this?

View file

@ -375,9 +375,8 @@ class PesterProfile(object):
else: else:
return "<c=%s>%s</c> banned <c=%s>%s</c> from responding to memo: <c=black>[%s]</c>." % \ return "<c=%s>%s</c> banned <c=%s>%s</c> from responding to memo: <c=black>[%s]</c>." % \
(opchum.colorhtml(), opinit, self.colorhtml(), initials, str(reason)) (opchum.colorhtml(), opinit, self.colorhtml(), initials, str(reason))
"""
# Currently unused, might be neat to use in the future?
# As far as I'm aware, there's no IRC reply for this, this seems impossible to check for in practice.
def memopermabanmsg(self, opchum, opgrammar, syscolor, timeGrammar): def memopermabanmsg(self, opchum, opgrammar, syscolor, timeGrammar):
initials = (timeGrammar.pcf initials = (timeGrammar.pcf
+ self.initials() + self.initials()
@ -387,7 +386,7 @@ class PesterProfile(object):
+ opgrammar.number) + opgrammar.number)
return "<c=%s>%s</c> permabanned <c=%s>%s</c> from the memo." % \ return "<c=%s>%s</c> permabanned <c=%s>%s</c> from the memo." % \
(opchum.colorhtml(), opinit, self.colorhtml(), initials) (opchum.colorhtml(), opinit, self.colorhtml(), initials)
"""
def memojoinmsg(self, syscolor, td, timeGrammar, verb): def memojoinmsg(self, syscolor, td, timeGrammar, verb):
#(temporal, pcf, when) = (timeGrammar.temporal, timeGrammar.pcf, timeGrammar.when) #(temporal, pcf, when) = (timeGrammar.temporal, timeGrammar.pcf, timeGrammar.when)
timetext = timeDifference(td) timetext = timeDifference(td)

11
irc.py
View file

@ -392,6 +392,7 @@ class PesterIRC(QtCore.QThread):
cannotSendToChan = QtCore.pyqtSignal('QString', 'QString') cannotSendToChan = QtCore.pyqtSignal('QString', 'QString')
tooManyPeeps = QtCore.pyqtSignal() tooManyPeeps = QtCore.pyqtSignal()
quirkDisable = QtCore.pyqtSignal('QString', 'QString', 'QString') quirkDisable = QtCore.pyqtSignal('QString', 'QString', 'QString')
forbiddenchannel = QtCore.pyqtSignal('QString', 'QString')
class PesterHandler(DefaultCommandHandler): class PesterHandler(DefaultCommandHandler):
def notice(self, nick, chan, msg): def notice(self, nick, chan, msg):
@ -777,7 +778,7 @@ class PesterHandler(DefaultCommandHandler):
if chandle in namelist: if chandle in namelist:
lesschums.append(c) lesschums.append(c)
self.getMood(*lesschums) self.getMood(*lesschums)
def liststart(self, server, handle, *info): def liststart(self, server, handle, *info):
self.channel_list = [] self.channel_list = []
info = list(info) info = list(info)
@ -802,14 +803,18 @@ class PesterHandler(DefaultCommandHandler):
self.parent.inviteReceived.emit(handle, channel) self.parent.inviteReceived.emit(handle, channel)
def inviteonlychan(self, server, handle, channel, msg): def inviteonlychan(self, server, handle, channel, msg):
self.parent.chanInviteOnly.emit(channel) self.parent.chanInviteOnly.emit(channel)
# This can cause a crash without mode_params, channelmodeis can have six arguments. # channelmodeis can have six arguments.
def channelmodeis(self, server, handle, channel, modes, mode_params=""): def channelmodeis(self, server, handle, channel, modes, mode_params=""):
self.parent.modesUpdated.emit(channel, modes) self.parent.modesUpdated.emit(channel, modes)
def cannotsendtochan(self, server, handle, channel, msg): def cannotsendtochan(self, server, handle, channel, msg):
self.parent.cannotSendToChan.emit(channel, msg) self.parent.cannotSendToChan.emit(channel, msg)
def toomanypeeps(self, *stuff): def toomanypeeps(self, *stuff):
self.parent.tooManyPeeps.emit() self.parent.tooManyPeeps.emit()
def forbiddenchannel(self, server, handle, channel, msg):
# Channel is forbidden.
self.parent.forbiddenchannel.emit(channel, msg)
self.parent.userPresentUpdate.emit(handle, channel, "left")
def ping(self, prefix, server): def ping(self, prefix, server):
self.parent.mainwindow.lastping = int(time.time()) self.parent.mainwindow.lastping = int(time.time())
self.client.send('PONG', server) self.client.send('PONG', server)

View file

@ -1103,6 +1103,24 @@ class PesterMemo(PesterConvo):
msgbox.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Ok) msgbox.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Ok)
msgbox.exec() msgbox.exec()
@QtCore.pyqtSlot(QString, QString)
def closeForbidden(self, channel, reason):
c = str(channel)
if c.lower() == self.channel.lower():
self.mainwindow.forbiddenChan['QString', 'QString'].disconnect(self.closeForbidden)
if self.parent():
PchumLog.info(self.channel)
i = self.parent().tabIndices[self.channel]
self.parent().tabClose(i)
else:
self.close()
msgbox = QtWidgets.QMessageBox()
msgbox.setStyleSheet("QMessageBox{" + self.mainwindow.theme["main/defaultwindow/style"] + "}")
msgbox.setText("%s: D: CANT JOIN MEMO!!!" % (c))
msgbox.setInformativeText(reason)
msgbox.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Ok)
msgbox.exec()
def quirkDisable(self, op, msg): def quirkDisable(self, op, msg):
chums = self.userlist.findItems(op, QtCore.Qt.MatchFlag.MatchExactly) chums = self.userlist.findItems(op, QtCore.Qt.MatchFlag.MatchExactly)
for c in chums: for c in chums:
@ -1167,6 +1185,7 @@ class PesterMemo(PesterConvo):
@QtCore.pyqtSlot(QString, QString, QString) @QtCore.pyqtSlot(QString, QString, QString)
def userPresentChange(self, handle, channel, update): def userPresentChange(self, handle, channel, update):
#print("handle: %s, channel: %s, update: %s" % (handle, channel, update))
h = str(handle) h = str(handle)
c = str(channel) c = str(channel)
update = str(update) update = str(update)

View file

@ -180,6 +180,12 @@ numeric_events = {
"502": "usersdontmatch", "502": "usersdontmatch",
} }
# Unrealircd extras
unrealircd_events = {
"448": "forbiddenchannel",
}
numeric_events.update(unrealircd_events)
# IRC metadata draft specification # IRC metadata draft specification
# https://gist.github.com/k4bek4be/92c2937cefd49990fbebd001faf2b237 # https://gist.github.com/k4bek4be/92c2937cefd49990fbebd001faf2b237
metadata_numeric_events = { metadata_numeric_events = {
@ -221,5 +227,7 @@ protocol_events = [
"tagmsg", # IRCv3 message tags extension "tagmsg", # IRCv3 message tags extension
] ]
all_events = generated_events + protocol_events + list(numeric_events.values()) all_events = (generated_events
+ protocol_events
+ list(numeric_events.values()))

View file

@ -259,9 +259,11 @@ import pytwmn
# "grimAuxiliatrix", "gallowsCalibrator", "gardenGnostic", "ectoBiologist", \ # "grimAuxiliatrix", "gallowsCalibrator", "gardenGnostic", "ectoBiologist", \
# "twinArmageddons", "terminallyCapricious", "turntechGodhead", "tentacleTherapist"] # "twinArmageddons", "terminallyCapricious", "turntechGodhead", "tentacleTherapist"]
#canon_handles = ["",]# Unused, kept to prevent unexpected calls causing a crash. #canon_handles = ["",]# Unused, kept to prevent unexpected calls causing a crash.
BOTNAMES = []
CUSTOMBOTS = ["CALSPRITE", RANDNICK.upper()] CUSTOMBOTS = ["CALSPRITE", RANDNICK.upper()]
BOTNAMES = ["NICKSERV", "CHANSERV", "MEMOSERV", "OPERSERV", "HELPSERV", "HOSTSERV", "BOTSERV"] SERVICES = ["NICKSERV", "CHANSERV", "MEMOSERV", "OPERSERV", "HELPSERV", "HOSTSERV", "BOTSERV"]
BOTNAMES.extend(CUSTOMBOTS) BOTNAMES.extend(CUSTOMBOTS)
BOTNAMES.extend(SERVICES)
# Save the main app. From here, we should be able to get everything else in # Save the main app. From here, we should be able to get everything else in
# order, for console use. # order, for console use.
@ -1825,6 +1827,7 @@ class PesterWindow(MovingWindow):
memoWindow = PesterMemo(channel, timestr, self, None) memoWindow = PesterMemo(channel, timestr, self, None)
# connect signals # connect signals
self.inviteOnlyChan['QString'].connect(memoWindow.closeInviteOnly) self.inviteOnlyChan['QString'].connect(memoWindow.closeInviteOnly)
self.forbiddenChan['QString', 'QString'].connect(memoWindow.closeForbidden)
memoWindow.messageSent['QString', 'QString'].connect(self.sendMessage['QString', 'QString']) memoWindow.messageSent['QString', 'QString'].connect(self.sendMessage['QString', 'QString'])
memoWindow.windowClosed['QString'].connect(self.closeMemo) memoWindow.windowClosed['QString'].connect(self.closeMemo)
self.namesUpdated['QString'].connect(memoWindow.namesUpdated) self.namesUpdated['QString'].connect(memoWindow.namesUpdated)
@ -2220,7 +2223,10 @@ class PesterWindow(MovingWindow):
try: try:
del self.memos[c] del self.memos[c]
except KeyError: except KeyError:
del self.memos[c.lower()] try:
del self.memos[c.lower()]
except KeyError:
pass
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def tabsClosed(self): def tabsClosed(self):
del self.tabconvo del self.tabconvo
@ -2271,6 +2277,12 @@ class PesterWindow(MovingWindow):
if m: if m:
t = self.tm.Toast("NickServ:", m) t = self.tm.Toast("NickServ:", m)
t.show() t.show()
elif ("PESTERCHUM:" not in m) and (h.upper() in SERVICES):
# Show toast for rest services notices
# "Your VHOST is actived", "You have one new memo", etc.
t = self.tm.Toast("%s:" % h, m)
t.show()
@QtCore.pyqtSlot(QString, QString) @QtCore.pyqtSlot(QString, QString)
def deliverInvite(self, handle, channel): def deliverInvite(self, handle, channel):
msgbox = QtWidgets.QMessageBox() msgbox = QtWidgets.QMessageBox()
@ -2326,7 +2338,7 @@ class PesterWindow(MovingWindow):
def userPresentUpdate(self, handle, channel, update): def userPresentUpdate(self, handle, channel, update):
c = str(channel) c = str(channel)
n = str(handle) n = str(handle)
#PchumLog.debug("c=%s\nn=%s\nupdate=%s\n" % (c, n, update)) print("c=%s\nn=%s\nupdate=%s\n" % (c, n, update))
if update == "nick": if update == "nick":
l = n.split(":") l = n.split(":")
oldnick = l[0] oldnick = l[0]
@ -2359,6 +2371,9 @@ class PesterWindow(MovingWindow):
except KeyError: except KeyError:
pass pass
elif update == "join": elif update == "join":
# SAJOIN-ed?
if (n == self.profile().handle) and (c not in self.memos):
self.newMemo(channel, "+0:00")
try: try:
i = self.namesdb[c].index(n) i = self.namesdb[c].index(n)
except ValueError: except ValueError:
@ -3200,7 +3215,12 @@ class PesterWindow(MovingWindow):
msg = QtWidgets.QMessageBox(self) msg = QtWidgets.QMessageBox(self)
msg.setText("D: TOO MANY PEOPLE!!!") msg.setText("D: TOO MANY PEOPLE!!!")
msg.setInformativeText("The server has hit max capacity. Please try again later.") msg.setInformativeText("The server has hit max capacity. Please try again later.")
msg.show() #msg.setStyleSheet("QMessageBox{" + self.theme["main/defaultwindow/style"] + "}")
msg.exec()
@QtCore.pyqtSlot(QString, QString)
def forbiddenchannel(self, channel, reason):
self.forbiddenChan.emit(channel, reason)
@QtCore.pyqtSlot() @QtCore.pyqtSlot()
def quit(self): def quit(self):
@ -3553,6 +3573,7 @@ class PesterWindow(MovingWindow):
channelNames = QtCore.pyqtSignal('QString') channelNames = QtCore.pyqtSignal('QString')
inviteChum = QtCore.pyqtSignal('QString', 'QString') inviteChum = QtCore.pyqtSignal('QString', 'QString')
inviteOnlyChan = QtCore.pyqtSignal('QString') inviteOnlyChan = QtCore.pyqtSignal('QString')
forbiddenChan = QtCore.pyqtSignal('QString', 'QString')
closeSignal = QtCore.pyqtSignal() closeSignal = QtCore.pyqtSignal()
reconnectIRC = QtCore.pyqtSignal() reconnectIRC = QtCore.pyqtSignal()
gainAttention = QtCore.pyqtSignal(QtWidgets.QWidget) gainAttention = QtCore.pyqtSignal(QtWidgets.QWidget)
@ -3768,7 +3789,9 @@ Click this message to never see this again.")
('tooManyPeeps()', ('tooManyPeeps()',
'tooManyPeeps()'), 'tooManyPeeps()'),
('quirkDisable(QString, QString, QString)', ('quirkDisable(QString, QString, QString)',
'quirkDisable(QString, QString, QString)') 'quirkDisable(QString, QString, QString)'),
('forbiddenchannel(QString)',
'forbiddenchannel(QString)')
] ]
def ircQtConnections(self, irc, widget): def ircQtConnections(self, irc, widget):
# IRC --> Main window # IRC --> Main window
@ -3813,6 +3836,7 @@ Click this message to never see this again.")
(irc.chanInviteOnly, widget.chanInviteOnly), (irc.chanInviteOnly, widget.chanInviteOnly),
(irc.modesUpdated, widget.modesUpdated), (irc.modesUpdated, widget.modesUpdated),
(irc.cannotSendToChan, widget.cannotSendToChan), (irc.cannotSendToChan, widget.cannotSendToChan),
(irc.forbiddenchannel, widget.forbiddenchannel),
(irc.tooManyPeeps, widget.tooManyPeeps), (irc.tooManyPeeps, widget.tooManyPeeps),
(irc.quirkDisable, widget.quirkDisable)) (irc.quirkDisable, widget.quirkDisable))
def connectWidgets(self, irc, widget): def connectWidgets(self, irc, widget):

View file

@ -55,41 +55,43 @@ class PesterLog(object):
html = log_time + convertTags(msg, "html")+"<br />" html = log_time + convertTags(msg, "html")+"<br />"
msg = log_time +convertTags(msg, "text") msg = log_time +convertTags(msg, "text")
modes = {"bbcode": bbcodemsg, "html": html, "text": msg} modes = {"bbcode": bbcodemsg, "html": html, "text": msg}
if handle not in self.convos: try:
log_time = datetime.now().strftime("%Y-%m-%d.%H.%M") if handle not in self.convos:
self.convos[handle] = {} log_time = datetime.now().strftime("%Y-%m-%d.%H.%M")
for (format, t) in modes.items(): self.convos[handle] = {}
if not os.path.exists("%s/%s/%s/%s" % (self.logpath, self.handle, handle, format)): for (format, t) in modes.items():
os.makedirs("%s/%s/%s/%s" % (self.logpath, self.handle, handle, format)) if not os.path.exists("%s/%s/%s/%s" % (self.logpath, self.handle, handle, format)):
try: os.makedirs("%s/%s/%s/%s" % (self.logpath, self.handle, handle, format))
fp = codecs.open("%s/%s/%s/%s/%s.%s.txt" % (self.logpath, self.handle, handle, format, handle, log_time), encoding='utf-8', mode='a') fp = codecs.open("%s/%s/%s/%s/%s.%s.txt" % (self.logpath, self.handle, handle, format, handle, log_time), encoding='utf-8', mode='a')
except (IOError, OSError) as e: self.convos[handle][format] = fp
# Catching this exception does not stop pchum from dying if we run out of file handles </3
PchumLog.critical(e)
errmsg = QtWidgets.QMessageBox()
errmsg.setIcon(QtWidgets.QMessageBox.Icon.Warning)
errmsg.setText("Warning: Pesterchum could not open the log file for %s!" % (handle))
errmsg.setInformativeText("Your log for %s will not be saved because something went wrong. We suggest restarting Pesterchum. Sorry :(" % (handle))
errmsg.setWindowTitle(":(")
errmsg.exec()
PchumLog.debug("post-error msg")
self.convos[handle][format] = fp
for (format, t) in modes.items():
f = self.convos[handle][format]
f.write(t+"\r\n")
# flush + fsync force a write,
# makes sure logs are saved in the case of a crash.
f.flush()
os.fsync(f.fileno())
# This way the file descriptors are closed and reopened for every message,
# which is sub-optimal and definitely a performance drain but,
# otherwise we still run into the ulimit on platforms like MacOS fairly easily.
if ostools.isOSX() == True:
for (format, t) in modes.items(): for (format, t) in modes.items():
self.finish(handle) f = self.convos[handle][format]
f.write(t+"\r\n")
# flush + fsync force a write,
# makes sure logs are saved in the case of a crash.
f.flush()
os.fsync(f.fileno())
# This way the file descriptors are closed and reopened for every message,
# which is sub-optimal and definitely a performance drain but,
# otherwise we still run into the ulimit on platforms like MacOS fairly easily.
#if ostools.isOSX() == True:
# for (format, t) in modes.items():
# self.finish(handle)
except (IOError, OSError, KeyError, IndexError, ValueError) as e:
# Catching this exception does not stop pchum from dying if we run out of file handles </3
PchumLog.critical(e)
errmsg = QtWidgets.QMessageBox()
errmsg.setIcon(QtWidgets.QMessageBox.Icon.Warning)
errmsg.setText("Warning: Pesterchum could not open the log file for %s!" % (handle))
errmsg.setInformativeText("Your log for %s will not be saved because something went wrong. We suggest restarting Pesterchum. Sorry :(" % (handle)
+ '\n'
+ str(e))
errmsg.setWindowTitle(":(")
errmsg.exec()
PchumLog.debug("post-error msg")
def finish(self, handle): def finish(self, handle):
if handle not in self.convos: if handle not in self.convos:

View file

@ -216,15 +216,14 @@ class PesterToast(QtWidgets.QWidget, DefaultToast):
self.content = msg self.content = msg
if icon: if icon:
self.icon = QtWidgets.QLabel("") self.icon = QtWidgets.QLabel("")
self.icon.setPixmap(QtGui.QPixmap(icon).scaledToWidth(30)) iconPixmap = QtGui.QPixmap(icon).scaledToWidth(30)
else: self.icon.setPixmap(iconPixmap)
self.icon = QtWidgets.QLabel("") #else:
self.icon.setPixmap(QtGui.QPixmap(30, 30)) # self.icon.setPixmap(QtGui.QPixmap(30, 30))
self.icon.pixmap().fill(QtGui.QColor(0,0,0,0)) # self.icon.pixmap().fill(QtGui.QColor(0,0,0,0))
layout_0 = QtWidgets.QVBoxLayout() layout_0 = QtWidgets.QVBoxLayout()
layout_0.setContentsMargins(0, 0, 0, 0) layout_0.setContentsMargins(0, 0, 0, 0)
layout_0.setContentsMargins(0, 0, 0, 0)
if self.icon: if self.icon:
layout_1 = QtWidgets.QGridLayout() layout_1 = QtWidgets.QGridLayout()
@ -250,15 +249,19 @@ class PesterToast(QtWidgets.QWidget, DefaultToast):
self.msg.setStyleSheet(self.parent().theme["toasts/content/style"]) self.msg.setStyleSheet(self.parent().theme["toasts/content/style"])
self.layout().setSpacing(0) self.layout().setSpacing(0)
self.msg.setText(PesterToast.wrapText(self.msg.font(), str(self.msg.text()), self.parent().theme["toasts/width"], self.parent().theme["toasts/content/style"])) self.msg.setText(PesterToast.wrapText(self.msg.font(),
str(self.msg.text()),
self.parent().theme["toasts/width"],
self.parent().theme["toasts/content/style"]))
for screen in QtWidgets.QApplication.screens(): screens = QtWidgets.QApplication.screens()
# This 100% doesn't work with multiple screens. screen = screens[0] # Should be the main one right???
p = screen.availableGeometry().bottomRight() # This 100% doesn't work with multiple screens.
o = screen.geometry().bottomRight() p = screen.availableGeometry().bottomRight()
anim.setStartValue(p.y() - o.y()) o = screen.geometry().bottomRight()
anim.setEndValue(100) anim.setStartValue(p.y() - o.y())
anim.valueChanged[QtCore.QVariant].connect(self.updateBottomLeftAnimation) anim.setEndValue(100)
anim.valueChanged[QtCore.QVariant].connect(self.updateBottomLeftAnimation)
self.byebye = False self.byebye = False