diff --git a/TODO.md b/TODO.md
index 264616d..1579217 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,16 +1,15 @@
# TODO LIST : )
## ADD
- - Memoserv support.
- - Use memopermabanmsg function?
+ - ~~Memoserv support.~~
+ - ~~Use memopermabanmsg function?~~ <--- Permabans just give a KICK server response, there's no way to check for this.
## FIX
- 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.
- 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...?
- 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?
diff --git a/dataobjs.py b/dataobjs.py
index cbf1ba2..c0c0460 100644
--- a/dataobjs.py
+++ b/dataobjs.py
@@ -375,9 +375,8 @@ class PesterProfile(object):
else:
return "%s banned %s from responding to memo: [%s]." % \
(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):
initials = (timeGrammar.pcf
+ self.initials()
@@ -387,7 +386,7 @@ class PesterProfile(object):
+ opgrammar.number)
return "%s permabanned %s from the memo." % \
(opchum.colorhtml(), opinit, self.colorhtml(), initials)
- """
+
def memojoinmsg(self, syscolor, td, timeGrammar, verb):
#(temporal, pcf, when) = (timeGrammar.temporal, timeGrammar.pcf, timeGrammar.when)
timetext = timeDifference(td)
diff --git a/irc.py b/irc.py
index c0bd00a..acdde3d 100644
--- a/irc.py
+++ b/irc.py
@@ -392,6 +392,7 @@ class PesterIRC(QtCore.QThread):
cannotSendToChan = QtCore.pyqtSignal('QString', 'QString')
tooManyPeeps = QtCore.pyqtSignal()
quirkDisable = QtCore.pyqtSignal('QString', 'QString', 'QString')
+ forbiddenchannel = QtCore.pyqtSignal('QString', 'QString')
class PesterHandler(DefaultCommandHandler):
def notice(self, nick, chan, msg):
@@ -777,7 +778,7 @@ class PesterHandler(DefaultCommandHandler):
if chandle in namelist:
lesschums.append(c)
self.getMood(*lesschums)
-
+
def liststart(self, server, handle, *info):
self.channel_list = []
info = list(info)
@@ -802,14 +803,18 @@ class PesterHandler(DefaultCommandHandler):
self.parent.inviteReceived.emit(handle, channel)
def inviteonlychan(self, server, handle, channel, msg):
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=""):
self.parent.modesUpdated.emit(channel, modes)
def cannotsendtochan(self, server, handle, channel, msg):
self.parent.cannotSendToChan.emit(channel, msg)
def toomanypeeps(self, *stuff):
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):
self.parent.mainwindow.lastping = int(time.time())
self.client.send('PONG', server)
diff --git a/memos.py b/memos.py
index 9c1df6a..f25b71f 100644
--- a/memos.py
+++ b/memos.py
@@ -1103,6 +1103,24 @@ class PesterMemo(PesterConvo):
msgbox.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Ok)
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):
chums = self.userlist.findItems(op, QtCore.Qt.MatchFlag.MatchExactly)
for c in chums:
@@ -1167,6 +1185,7 @@ class PesterMemo(PesterConvo):
@QtCore.pyqtSlot(QString, QString, QString)
def userPresentChange(self, handle, channel, update):
+ #print("handle: %s, channel: %s, update: %s" % (handle, channel, update))
h = str(handle)
c = str(channel)
update = str(update)
diff --git a/oyoyo/ircevents.py b/oyoyo/ircevents.py
index 1d479ad..947684b 100644
--- a/oyoyo/ircevents.py
+++ b/oyoyo/ircevents.py
@@ -180,6 +180,12 @@ numeric_events = {
"502": "usersdontmatch",
}
+# Unrealircd extras
+unrealircd_events = {
+ "448": "forbiddenchannel",
+}
+numeric_events.update(unrealircd_events)
+
# IRC metadata draft specification
# https://gist.github.com/k4bek4be/92c2937cefd49990fbebd001faf2b237
metadata_numeric_events = {
@@ -221,5 +227,7 @@ protocol_events = [
"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()))
diff --git a/pesterchum.py b/pesterchum.py
index 3aaa444..16cc02d 100644
--- a/pesterchum.py
+++ b/pesterchum.py
@@ -259,9 +259,11 @@ import pytwmn
# "grimAuxiliatrix", "gallowsCalibrator", "gardenGnostic", "ectoBiologist", \
# "twinArmageddons", "terminallyCapricious", "turntechGodhead", "tentacleTherapist"]
#canon_handles = ["",]# Unused, kept to prevent unexpected calls causing a crash.
+BOTNAMES = []
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(SERVICES)
# Save the main app. From here, we should be able to get everything else in
# order, for console use.
@@ -1825,6 +1827,7 @@ class PesterWindow(MovingWindow):
memoWindow = PesterMemo(channel, timestr, self, None)
# connect signals
self.inviteOnlyChan['QString'].connect(memoWindow.closeInviteOnly)
+ self.forbiddenChan['QString', 'QString'].connect(memoWindow.closeForbidden)
memoWindow.messageSent['QString', 'QString'].connect(self.sendMessage['QString', 'QString'])
memoWindow.windowClosed['QString'].connect(self.closeMemo)
self.namesUpdated['QString'].connect(memoWindow.namesUpdated)
@@ -2220,7 +2223,10 @@ class PesterWindow(MovingWindow):
try:
del self.memos[c]
except KeyError:
- del self.memos[c.lower()]
+ try:
+ del self.memos[c.lower()]
+ except KeyError:
+ pass
@QtCore.pyqtSlot()
def tabsClosed(self):
del self.tabconvo
@@ -2271,6 +2277,12 @@ class PesterWindow(MovingWindow):
if m:
t = self.tm.Toast("NickServ:", m)
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)
def deliverInvite(self, handle, channel):
msgbox = QtWidgets.QMessageBox()
@@ -2326,7 +2338,7 @@ class PesterWindow(MovingWindow):
def userPresentUpdate(self, handle, channel, update):
c = str(channel)
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":
l = n.split(":")
oldnick = l[0]
@@ -2359,6 +2371,9 @@ class PesterWindow(MovingWindow):
except KeyError:
pass
elif update == "join":
+ # SAJOIN-ed?
+ if (n == self.profile().handle) and (c not in self.memos):
+ self.newMemo(channel, "+0:00")
try:
i = self.namesdb[c].index(n)
except ValueError:
@@ -3200,7 +3215,12 @@ class PesterWindow(MovingWindow):
msg = QtWidgets.QMessageBox(self)
msg.setText("D: TOO MANY PEOPLE!!!")
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()
def quit(self):
@@ -3553,6 +3573,7 @@ class PesterWindow(MovingWindow):
channelNames = QtCore.pyqtSignal('QString')
inviteChum = QtCore.pyqtSignal('QString', 'QString')
inviteOnlyChan = QtCore.pyqtSignal('QString')
+ forbiddenChan = QtCore.pyqtSignal('QString', 'QString')
closeSignal = QtCore.pyqtSignal()
reconnectIRC = QtCore.pyqtSignal()
gainAttention = QtCore.pyqtSignal(QtWidgets.QWidget)
@@ -3768,7 +3789,9 @@ Click this message to never see this again.")
('tooManyPeeps()',
'tooManyPeeps()'),
('quirkDisable(QString, QString, QString)',
- 'quirkDisable(QString, QString, QString)')
+ 'quirkDisable(QString, QString, QString)'),
+ ('forbiddenchannel(QString)',
+ 'forbiddenchannel(QString)')
]
def ircQtConnections(self, irc, widget):
# IRC --> Main window
@@ -3813,6 +3836,7 @@ Click this message to never see this again.")
(irc.chanInviteOnly, widget.chanInviteOnly),
(irc.modesUpdated, widget.modesUpdated),
(irc.cannotSendToChan, widget.cannotSendToChan),
+ (irc.forbiddenchannel, widget.forbiddenchannel),
(irc.tooManyPeeps, widget.tooManyPeeps),
(irc.quirkDisable, widget.quirkDisable))
def connectWidgets(self, irc, widget):
diff --git a/profile.py b/profile.py
index c020813..d0ee6d9 100644
--- a/profile.py
+++ b/profile.py
@@ -55,41 +55,43 @@ class PesterLog(object):
html = log_time + convertTags(msg, "html")+"
"
msg = log_time +convertTags(msg, "text")
modes = {"bbcode": bbcodemsg, "html": html, "text": msg}
- if handle not in self.convos:
- log_time = datetime.now().strftime("%Y-%m-%d.%H.%M")
- self.convos[handle] = {}
- for (format, t) in modes.items():
- if not os.path.exists("%s/%s/%s/%s" % (self.logpath, self.handle, handle, format)):
- os.makedirs("%s/%s/%s/%s" % (self.logpath, self.handle, handle, format))
- try:
+ try:
+ if handle not in self.convos:
+ log_time = datetime.now().strftime("%Y-%m-%d.%H.%M")
+ self.convos[handle] = {}
+ for (format, t) in modes.items():
+ if not os.path.exists("%s/%s/%s/%s" % (self.logpath, self.handle, handle, format)):
+ 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')
- except (IOError, OSError) 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))
- errmsg.setWindowTitle(":(")
- errmsg.exec()
- PchumLog.debug("post-error msg")
+ self.convos[handle][format] = fp
- 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():
- 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):
if handle not in self.convos:
diff --git a/toast.py b/toast.py
index cdf1ecf..4b5a657 100644
--- a/toast.py
+++ b/toast.py
@@ -216,15 +216,14 @@ class PesterToast(QtWidgets.QWidget, DefaultToast):
self.content = msg
if icon:
self.icon = QtWidgets.QLabel("")
- self.icon.setPixmap(QtGui.QPixmap(icon).scaledToWidth(30))
- else:
- self.icon = QtWidgets.QLabel("")
- self.icon.setPixmap(QtGui.QPixmap(30, 30))
- self.icon.pixmap().fill(QtGui.QColor(0,0,0,0))
+ iconPixmap = QtGui.QPixmap(icon).scaledToWidth(30)
+ self.icon.setPixmap(iconPixmap)
+ #else:
+ # self.icon.setPixmap(QtGui.QPixmap(30, 30))
+ # self.icon.pixmap().fill(QtGui.QColor(0,0,0,0))
layout_0 = QtWidgets.QVBoxLayout()
layout_0.setContentsMargins(0, 0, 0, 0)
- layout_0.setContentsMargins(0, 0, 0, 0)
if self.icon:
layout_1 = QtWidgets.QGridLayout()
@@ -250,15 +249,19 @@ class PesterToast(QtWidgets.QWidget, DefaultToast):
self.msg.setStyleSheet(self.parent().theme["toasts/content/style"])
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():
- # This 100% doesn't work with multiple screens.
- p = screen.availableGeometry().bottomRight()
- o = screen.geometry().bottomRight()
- anim.setStartValue(p.y() - o.y())
- anim.setEndValue(100)
- anim.valueChanged[QtCore.QVariant].connect(self.updateBottomLeftAnimation)
+ screens = QtWidgets.QApplication.screens()
+ screen = screens[0] # Should be the main one right???
+ # This 100% doesn't work with multiple screens.
+ p = screen.availableGeometry().bottomRight()
+ o = screen.geometry().bottomRight()
+ anim.setStartValue(p.y() - o.y())
+ anim.setEndValue(100)
+ anim.valueChanged[QtCore.QVariant].connect(self.updateBottomLeftAnimation)
self.byebye = False