diff --git a/TODO b/TODO index edb3708..e597fd2 100644 --- a/TODO +++ b/TODO @@ -1,17 +1,17 @@ Features: -* Tray doesn't disappear on windows after close -* memo sending from unknown color breaks -- over IRC -* smilies processed before quirks -* More complex quirks: random, spelling, by-sound +* More complex quirks: spelling, by-sound +* random quirk string enter must clear text box and focus input on add +* IRC message limit!!! +* on ban, redirect to memo chooser * ? time option??? -* convert hex tags ( or ) * help menu -- about and forum +* Tray doesn't disappear on windows after close +* memo sending from unknown color breaks -- over IRC?? -- release alpha * shared buddy lists - changes to the buddy list should refresh it? multiple clients share buddy list??? * chumList not scaling -- QListView + delegate? * spell check? -* convo backgrounds -- make them more like http://www.mspaintadventures.com/storyfiles/hs2/02546_2.gif * help button on quirks menu? -- release beta * flashing?? diff --git a/convo.py b/convo.py index 7a8364c..7a7431f 100644 --- a/convo.py +++ b/convo.py @@ -1,11 +1,12 @@ from string import Template import re +from copy import copy from datetime import datetime, timedelta from PyQt4 import QtGui, QtCore from dataobjs import PesterProfile, Mood, PesterHistory from generic import PesterIcon, RightClickList -from parsetools import convertTags +from parsetools import convertTags, lexMessage, mecmd, colorBegin, colorEnd class PesterTabWindow(QtGui.QFrame): def __init__(self, mainwindow, parent=None, convo="convo"): @@ -203,74 +204,72 @@ class PesterText(QtGui.QTextEdit): self.setStyleSheet("QTextEdit { %s } QScrollBar:vertical { %s } QScrollBar::handle:vertical { %s } QScrollBar::add-line:vertical { %s } QScrollBar::sub-line:vertical { %s } QScrollBar:up-arrow:vertical { %s } QScrollBar:down-arrow:vertical { %s }" % (theme["convo/textarea/style"], theme["convo/scrollbar/style"], theme["convo/scrollbar/handle"], theme["convo/scrollbar/downarrow"], theme["convo/scrollbar/uparrow"], theme["convo/scrollbar/uarrowstyle"], theme["convo/scrollbar/darrowstyle"] )) else: self.setStyleSheet("QTextEdit { %s }" % (theme["convo/textarea/style"])) - def addMessage(self, text, chum): - color = chum.colorhtml() + def addMessage(self, lexmsg, chum): + if len(lexmsg) == 0: + return + color = chum.colorcmd() systemColor = QtGui.QColor(self.parent().mainwindow.theme["convo/systemMsgColor"]) initials = chum.initials() - msg = unicode(text) parent = self.parent() window = parent.mainwindow me = window.profile() - quirks = window.userprofile.quirks if parent.applyquirks else None - if msg == "PESTERCHUM:BEGIN": + if lexmsg[0] == "PESTERCHUM:BEGIN": parent.setChumOpen(True) - msg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"]) - window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) - self.append(convertTags(msg)) - elif msg == "PESTERCHUM:CEASE": + pmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"]) + window.chatlog.log(chum.handle, pmsg) + self.append(convertTags(pmsg)) + elif lexmsg[0] == "PESTERCHUM:CEASE": parent.setChumOpen(False) - msg = chum.pestermsg(me, systemColor, window.theme["convo/text/ceasepester"]) - window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) - self.append(convertTags(msg)) - elif msg == "PESTERCHUM:BLOCK": - msg = chum.pestermsg(me, systemColor, window.theme['convo/text/blocked']) - window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) - self.append(convertTags(msg)) - elif msg == "PESTERCHUM:UNBLOCK": - msg = chum.pestermsg(me, systemColor, window.theme['convo/text/unblocked']) - window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) - self.append(convertTags(msg)) - elif msg == "PESTERCHUM:BLOCKED": - msg = chum.pestermsg(me, systemColor, window.theme['convo/text/blockedmsg']) - window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) - self.append(convertTags(msg)) - elif msg == "PESTERCHUM:IDLE": - msg = chum.idlemsg(systemColor, window.theme['convo/text/idle']) - window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) - self.append(convertTags(msg)) - elif msg[0:3] == "/me" or msg[0:13] == "PESTERCHUM:ME": - if quirks: - msg = quirks.apply(msg) - if msg[0:3] == "/me": - start = 3 - else: - start = 13 - space = msg.find(" ") - msg = chum.memsg(systemColor, msg[start:space], msg[space:]) + pmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/ceasepester"]) + window.chatlog.log(chum.handle, pmsg) + self.append(convertTags(pmsg)) + elif lexmsg[0] == "PESTERCHUM:BLOCK": + pmsg = chum.pestermsg(me, systemColor, window.theme['convo/text/blocked']) + window.chatlog.log(chum.handle, pmsg) + self.append(convertTags(pmsg)) + elif lexmsg[0] == "PESTERCHUM:UNBLOCK": + pmsg = chum.pestermsg(me, systemColor, window.theme['convo/text/unblocked']) + window.chatlog.log(chum.handle, pmsg) + self.append(convertTags(pmsg)) + elif lexmsg[0] == "PESTERCHUM:BLOCKED": + pmsg = chum.pestermsg(me, systemColor, window.theme['convo/text/blockedmsg']) + window.chatlog.log(chum.handle, pmsg) + self.append(convertTags(pmsg)) + elif lexmsg[0] == "PESTERCHUM:IDLE": + imsg = chum.idlemsg(systemColor, window.theme['convo/text/idle']) + window.chatlog.log(chum.handle, imsg) + self.append(convertTags(imsg)) + elif type(lexmsg[0]) is mecmd: + memsg = chum.memsg(systemColor, lexmsg) if chum is me: - window.chatlog.log(parent.chum.handle, convertTags(msg, "bbcode")) + window.chatlog.log(parent.chum.handle, memsg) else: - window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) - self.append(convertTags(msg)) + window.chatlog.log(chum.handle, memsg) + self.append(convertTags(memsg)) else: if not parent.chumopen and chum is not me: beginmsg = chum.pestermsg(me, systemColor, window.theme["convo/text/beganpester"]) parent.setChumOpen(True) - window.chatlog.log(chum.handle, convertTags(beginmsg, "bbcode")) + window.chatlog.log(chum.handle, beginmsg) self.append(convertTags(beginmsg)) - msg = "%s: %s" % (color, initials, msg) - self.append(convertTags(msg, quirkobj=quirks)) + lexmsg[0:0] = [colorBegin("" % (color), color), + "%s: " % (initials)] + lexmsg.append(colorEnd("")) + self.append(convertTags(lexmsg)) if chum is me: - window.chatlog.log(parent.chum.handle, convertTags(msg, "bbcode", quirkobj=quirks)) + window.chatlog.log(parent.chum.handle, lexmsg) else: - if window.idle: + if window.idleaction.isChecked(): idlethreshhold = 60 if (not hasattr(self, 'lastmsg')) or \ - datetime.now() - self.lastmsg > timedelta(0,60): + datetime.now() - self.lastmsg > timedelta(0,idlethreshhold): + idlemsg = me.idlemsg(systemColor, verb) + self.textArea.append(convertTags(idlemsg)) + window.chatlog.log(self.title(), idlemsg) parent.messageSent.emit("PESTERCHUM:IDLE", parent.title()) self.lastmsg = datetime.now() - window.chatlog.log(chum.handle, convertTags(msg, "bbcode")) + window.chatlog.log(chum.handle, lexmsg) def changeTheme(self, theme): self.initTheme(theme) sb = self.verticalScrollBar() @@ -303,6 +302,7 @@ class PesterInput(QtGui.QLineEdit): self.setStyleSheet(theme["convo/input/style"]) def focusInEvent(self, event): self.parent().clearNewMessage() + self.parent().textArea.textCursor().clearSelection() QtGui.QLineEdit.focusInEvent(self, event) def keyPressEvent(self, event): if event.key() == QtCore.Qt.Key_Up: @@ -388,7 +388,7 @@ class PesterConvo(QtGui.QFrame): msg = self.mainwindow.profile().pestermsg(self.chum, QtGui.QColor(self.mainwindow.theme["convo/systemMsgColor"]), self.mainwindow.theme["convo/text/beganpester"]) self.setChumOpen(True) self.textArea.append(convertTags(msg)) - self.mainwindow.chatlog.log(self.title(), convertTags(msg, "bbcode")) + self.mainwindow.chatlog.log(self.title(), msg) self.newmessage = False self.history = PesterHistory() @@ -403,12 +403,12 @@ class PesterConvo(QtGui.QFrame): self.mainwindow.ceasesound.play() msg = self.chum.pestermsg(self.mainwindow.profile(), syscolor, self.mainwindow.theme["convo/text/ceasepester"]) self.textArea.append(convertTags(msg)) - self.mainwindow.chatlog.log(self.title(), convertTags(msg, "bbcode")) + self.mainwindow.chatlog.log(self.title(), msg) self.chumopen = False elif old and old.name() != mood.name(): msg = self.chum.moodmsg(mood, syscolor, self.mainwindow.theme) self.textArea.append(convertTags(msg)) - self.mainwindow.chatlog.log(self.title(), convertTags(msg, "bbcode")) + self.mainwindow.chatlog.log(self.title(), msg) if self.parent(): self.parent().updateMood(self.title(), mood, unblocked) else: @@ -431,13 +431,17 @@ class PesterConvo(QtGui.QFrame): def updateColor(self, color): self.chum.color = color - def addMessage(self, text, me=True): + def addMessage(self, msg, me=True): + if type(msg) in [str, unicode]: + lexmsg = lexMessage(msg) + else: + lexmsg = msg if me: chum = self.mainwindow.profile() else: chum = self.chum self.notifyNewMessage() - self.textArea.addMessage(text, chum) + self.textArea.addMessage(lexmsg, chum) def notifyNewMessage(self): # first see if this conversation HASS the focus @@ -516,13 +520,16 @@ class PesterConvo(QtGui.QFrame): if text == "" or text[0:11] == "PESTERCHUM:": return self.history.add(text) - self.addMessage(text, True) + quirks = self.mainwindow.userprofile.quirks + lexmsg = lexMessage(text) + if type(lexmsg[0]) is not mecmd and self.applyquirks: + lexmsg = quirks.apply(lexmsg) + serverMsg = copy(lexmsg) + self.addMessage(lexmsg, True) # if ceased, rebegin if hasattr(self, 'chumopen') and not self.chumopen: self.mainwindow.newConvoStarted.emit(QtCore.QString(self.title()), True) - # convert color tags - quirkobj = self.mainwindow.userprofile.quirks if self.applyquirks else None - text = convertTags(text, "ctag", quirkobj) + text = convertTags(serverMsg, "ctag") self.messageSent.emit(text, self.title()) self.textInput.setText("") diff --git a/convo.pyc b/convo.pyc index 07ab907..9651083 100644 Binary files a/convo.pyc and b/convo.pyc differ diff --git a/dataobjs.py b/dataobjs.py index c51be52..263d324 100644 --- a/dataobjs.py +++ b/dataobjs.py @@ -1,9 +1,10 @@ from PyQt4 import QtGui, QtCore from datetime import * import re +import random from generic import PesterIcon -from parsetools import timeDifference +from parsetools import timeDifference, convertTags class Mood(object): moods = ["chummy", "rancorous", "offline", "pleasant", "distraught", @@ -37,15 +38,31 @@ class pesterQuirk(object): raise ValueError("Quirks must be given a dictionary") self.quirk = quirk self.type = self.quirk["type"] - def apply(self, string): + def apply(self, string, first=False, last=False): if self.type == "prefix": return self.quirk["value"] + string - if self.type == "suffix": + elif self.type == "suffix": return string + self.quirk["value"] - if self.type == "replace": + elif self.type == "replace": return string.replace(self.quirk["from"], self.quirk["to"]) - if self.type == "regexp": - return re.sub(self.quirk["from"], self.quirk["to"], string) + elif self.type == "regexp": + fr = self.quirk["from"] + if not first and len(fr) > 0 and fr[0] == "^": + return string + if not last and len(fr) > 0 and fr[len(fr)-1] == "$": + return string + return re.sub(fr, self.quirk["to"], string) + elif self.type == "random": + fr = self.quirk["from"] + if not first and len(fr) > 0 and fr[0] == "^": + return string + if not last and len(fr) > 0 and fr[len(fr)-1] == "$": + return string + def randomrep(mo): + choice = random.choice(self.quirk["randomlist"]) + return mo.expand(choice) + return re.sub(self.quirk["from"], randomrep, string) + def __str__(self): if self.type == "prefix": return "BEGIN WITH: %s" % (self.quirk["value"]) @@ -55,6 +72,8 @@ class pesterQuirk(object): return "REPLACE %s WITH %s" % (self.quirk["from"], self.quirk["to"]) elif self.type == "regexp": return "REGEXP: %s REPLACED WITH %s" % (self.quirk["from"], self.quirk["to"]) + elif self.type == "random": + return "REGEXP: %s RANDOMLY REPLACED WITH %s" % (self.quirk["from"], [str(r) for r in self.quirk["randomlist"]]) class pesterQuirks(object): def __init__(self, quirklist): @@ -66,25 +85,35 @@ class pesterQuirks(object): self.quirklist.append(q) def plainList(self): return [q.quirk for q in self.quirklist] - def apply(self, string): - # don't quirk /me commands - if string[0:3] == "/me": - space = string.find(" ") - cmd = string[0:space] - string = string[space:] - else: - cmd = "" - presuffix = [q for q in self.quirklist if - q.type=='prefix' or q.type=='suffix'] + def apply(self, lexed, first=False, last=False): + prefix = [q for q in self.quirklist if q.type=='prefix'] + suffix = [q for q in self.quirklist if q.type=='suffix'] replace = [q for q in self.quirklist if q.type=='replace' or q.type=='regexp'] - for r in replace: - string = r.apply(string) - if not cmd: - for ps in presuffix: - string = ps.apply(string) - string = cmd+string - return string + random = [q for q in self.quirklist if q.type=='random'] + + firstStr = True + newlist = [] + for (i, o) in enumerate(lexed): + if type(o) not in [str, unicode]: + newlist.append(o) + continue + lastStr = (i == len(lexed)-1) + string = o + for r in random: + string = r.apply(string, first=firstStr, last=lastStr) + for r in replace: + string = r.apply(string, first=firstStr, last=lastStr) + if firstStr: + for p in prefix: + string = p.apply(string) + if lastStr: + for s in suffix: + string = s.apply(string) + newlist.append(string) + firstStr = False + + return newlist def __iter__(self): for q in self.quirklist: @@ -127,7 +156,9 @@ class PesterProfile(object): def blocked(self, config): return self.handle in config.getBlocklist() - def memsg(self, syscolor, suffix, msg, time=None): + def memsg(self, syscolor, lexmsg, time=None): + suffix = lexmsg[0].suffix + msg = convertTags(lexmsg[1:], "text") uppersuffix = suffix.upper() if time is not None: handle = "%s %s" % (time.temporal, self.handle) diff --git a/dataobjs.pyc b/dataobjs.pyc index f807641..b9744fc 100644 Binary files a/dataobjs.pyc and b/dataobjs.pyc differ diff --git a/generic.pyc b/generic.pyc index 033bd9a..3b026d6 100644 Binary files a/generic.pyc and b/generic.pyc differ diff --git a/irc.pyc b/irc.pyc index 62a8eb1..e4a65a5 100644 Binary files a/irc.pyc and b/irc.pyc differ diff --git a/logs/chums.js b/logs/chums.js index ee55015..e55192a 100644 --- a/logs/chums.js +++ b/logs/chums.js @@ -1 +1 @@ -{"macruralAlchemist": {"color": "#700000", "handle": "macruralAlchemist", "mood": "offline"}, "lyricalKeraunoscopic": {"color": "#00c000", "handle": "lyricalKeraunoscopic", "mood": "offline"}, "fireSwallow": {"color": "#80bb9a", "handle": "fireSwallow", "mood": "offline"}, "aquaMarinist": {"color": "#00caca", "handle": "aquaMarinist", "mood": "offline"}, "centaursTesticle": {"color": "#000056", "handle": "centaursTesticle", "mood": "offline"}, "mechanicalSpectacle": {"color": "#0000ff", "handle": "mechanicalSpectacle", "mood": "offline"}, "carcinoGeneticist": {"color": "#999999", "handle": "carcinoGeneticist", "mood": "offline"}, "greyscalePacifist": {"color": "#7f7f7f", "handle": "greyscalePacifist", "mood": "offline"}, "aquaticMarinist": {"color": "#00caca", "handle": "aquaticMarinist", "mood": "offline"}, "iw": {"color": "#ff0000", "handle": "iw", "mood": "offline"}, "insipidTranscient": {"color": "#145064", "handle": "insipidTranscient", "mood": "offline"}, "caffeinatedAnalyst": {"color": "#aa0000", "handle": "caffeinatedAnalyst", "mood": "offline"}, "midnightSparrow": {"color": "#ff55ff", "handle": "midnightSparrow", "mood": "offline"}, "absoluteTranquility": {"color": "#000033", "handle": "absoluteTranquility", "mood": "offline"}, "nitroZealist": {"color": "#ff3737", "handle": "nitroZealist", "mood": "offline"}, "quintessentialArbalest": {"color": "#999999", "handle": "quintessentialArbalest", "mood": "offline"}, "noSense": {"color": "#1d0059", "handle": "noSense", "mood": "offline"}, "agogPorphyry": {"color": "#522d80", "handle": "agogPorphyry", "mood": "offline"}, "grimAuxiliatrix": {"color": "#008141", "handle": "grimAuxiliatrix", "mood": "offline"}, "androidTechnician": {"color": "#0000ff", "handle": "androidTechnician", "mood": "offline"}, "ardentAbettor": {"color": "#c8b670", "handle": "ardentAbettor", "mood": "offline"}, "aceIsm": {"color": "#ffcc66", "handle": "aceIsm", "mood": "offline"}, "apocalypseArisen": {"color": "#a10000", "handle": "apocalypseArisen", "mood": "offline"}, "radicalApologist": {"color": "#ffaa00", "handle": "radicalApologist", "mood": "offline"}, "microMachines": {"color": "#aa00ff", "handle": "microMachines", "mood": "offline"}, "uroborosUnbound": {"color": "#00416a", "handle": "uroborosUnbound", "mood": "offline"}, "arachnidsGrip": {"color": "#005682", "handle": "arachnidsGrip", "mood": "offline"}, "caligulasAquarium": {"color": "#6a006a", "handle": "caligulasAquarium", "mood": "offline"}, "percipientPedestrian": {"color": "#00ffff", "handle": "percipientPedestrian", "mood": "offline"}, "tentacleTherapist": {"color": "#cc66ff", "handle": "tentacleTherapist", "mood": "offline"}, "sucroseSaboteur": {"color": "#00e700", "handle": "sucroseSaboteur", "mood": "offline"}, "illuminatedWax": {"color": "#000000", "handle": "illuminatedWax", "mood": "offline"}, "moirailBunp": {"color": "#6a3d0f", "handle": "moirailBunp", "mood": "offline"}, "madLurker": {"color": "#000000", "handle": "madLurker", "mood": "offline"}, "testOut": {"color": "#c760cc", "handle": "testOut", "mood": "offline"}, "pesterClient3022": {"color": "#336600", "handle": "pesterClient3022", "mood": "offline"}, "hellerificJefferson": {"color": "#3300ff", "handle": "hellerificJefferson", "mood": "offline"}, "DocScratch": {"color": "#ffffff", "handle": "DocScratch", "mood": "offline"}, "recalcitrantDisaster": {"color": "#8b0068", "handle": "recalcitrantDisaster", "mood": "offline"}, "superGhost": {"color": "#800564", "handle": "superGhost", "mood": "offline"}, "arsenicCatnip": {"color": "#006400", "handle": "arsenicCatnip", "mood": "offline"}, "kaleidoscopicMind": {"color": "#ff6666", "handle": "kaleidoscopicMind", "mood": "offline"}, "zealousScarecrow": {"color": "#00c882", "handle": "zealousScarecrow", "mood": "offline"}, "captainCaveman": {"color": "#7c414e", "handle": "captainCaveman", "mood": "offline"}, "gamblingGenocider": {"color": "#00ff00", "handle": "gamblingGenocider", "mood": "offline"}, "cuttlefishCuller": {"color": "#77003c", "handle": "cuttlefishCuller", "mood": "offline"}, "wovenWay": {"color": "#000000", "handle": "wovenWay", "mood": "offline"}, "masterG": {"color": "#77003c", "handle": "masterG", "mood": "offline"}, "elegantDiversion": {"color": "#14b40a", "handle": "elegantDiversion", "mood": "offline"}, "plasmaModerator": {"color": "#5685cc", "handle": "plasmaModerator", "mood": "offline"}, "carcinoGenetecist": {"color": "#7f7f7f", "handle": "carcinoGenetecist", "mood": "offline"}, "marineAquist": {"color": "#00caca", "handle": "marineAquist", "mood": "offline"}, "remoteBloodbath": {"color": "#c70000", "handle": "remoteBloodbath", "mood": "offline"}, "oilslickOrchid": {"color": "#743f7e", "handle": "oilslickOrchid", "mood": "offline"}, "acapellaWaterfall": {"color": "#000099", "handle": "acapellaWaterfall", "mood": "offline"}, "gallowsCalibrator": {"color": "#008282", "handle": "gallowsCalibrator", "mood": "offline"}, "rageInducer": {"color": "#00ffff", "handle": "rageInducer", "mood": "offline"}, "anguillaNuntia": {"color": "#ff007f", "handle": "anguillaNuntia", "mood": "offline"}, "greenZephyr": {"color": "#00ca40", "handle": "greenZephyr", "mood": "offline"}, "lawdEngrish": {"color": "#00ff00", "handle": "lawdEngrish", "mood": "offline"}, "pretentiousFantasia": {"color": "#ff66cf", "handle": "pretentiousFantasia", "mood": "offline"}, "counterRealist": {"color": "#10d985", "handle": "counterRealist", "mood": "offline"}, "maxiumumFatness": {"color": "#3366ff", "handle": "maxiumumFatness", "mood": "offline"}, "schlagzeugGator": {"color": "#61821f", "handle": "schlagzeugGator", "mood": "offline"}, "metaliAggressive": {"color": "#9289d5", "handle": "metaliAggressive", "mood": "offline"}, "pesterClient394": {"color": "#ff3737", "handle": "pesterClient394", "mood": "offline"}, "magmaExploiter": {"color": "#d90000", "handle": "magmaExploiter", "mood": "offline"}, "gardenGnostic": {"color": "#00ff00", "handle": "gardenGnostic", "mood": "offline"}, "unknownTraveler": {"color": "#006666", "handle": "unknownTraveler", "mood": "offline"}, "utilitarianTurnabout": {"color": "#dd0000", "handle": "utilitarianTurnabout", "mood": "offline"}, "adiosToreador": {"color": "#aa5500", "handle": "adiosToreador", "mood": "offline"}} \ No newline at end of file +{"macruralAlchemist": {"color": "#700000", "handle": "macruralAlchemist", "mood": "offline"}, "lyricalKeraunoscopic": {"color": "#00c000", "handle": "lyricalKeraunoscopic", "mood": "offline"}, "fireSwallow": {"color": "#80bb9a", "handle": "fireSwallow", "mood": "offline"}, "aquaMarinist": {"color": "#00caca", "handle": "aquaMarinist", "mood": "offline"}, "centaursTesticle": {"color": "#000056", "handle": "centaursTesticle", "mood": "offline"}, "mechanicalSpectacle": {"color": "#0000ff", "handle": "mechanicalSpectacle", "mood": "offline"}, "carcinoGeneticist": {"color": "#999999", "handle": "carcinoGeneticist", "mood": "offline"}, "greyscalePacifist": {"color": "#7f7f7f", "handle": "greyscalePacifist", "mood": "offline"}, "aquaticMarinist": {"color": "#00caca", "handle": "aquaticMarinist", "mood": "offline"}, "iw": {"color": "#ff0000", "handle": "iw", "mood": "offline"}, "insipidTranscient": {"color": "#145064", "handle": "insipidTranscient", "mood": "offline"}, "caffeinatedAnalyst": {"color": "#aa0000", "handle": "caffeinatedAnalyst", "mood": "offline"}, "pesterClient394": {"color": "#ff3737", "handle": "pesterClient394", "mood": "offline"}, "absoluteTranquility": {"color": "#000033", "handle": "absoluteTranquility", "mood": "offline"}, "nitroZealist": {"color": "#ff3737", "handle": "nitroZealist", "mood": "offline"}, "quintessentialArbalest": {"color": "#999999", "handle": "quintessentialArbalest", "mood": "offline"}, "noSense": {"color": "#1d0059", "handle": "noSense", "mood": "offline"}, "agogPorphyry": {"color": "#522d80", "handle": "agogPorphyry", "mood": "offline"}, "grimAuxiliatrix": {"color": "#008141", "handle": "grimAuxiliatrix", "mood": "offline"}, "terminallyCapricious": {"color": "#2b0057", "handle": "terminallyCapricious", "mood": "offline"}, "androidTechnician": {"color": "#0000ff", "handle": "androidTechnician", "mood": "offline"}, "ardentAbettor": {"color": "#c8b670", "handle": "ardentAbettor", "mood": "offline"}, "aceIsm": {"color": "#ffcc66", "handle": "aceIsm", "mood": "offline"}, "apocalypseArisen": {"color": "#a10000", "handle": "apocalypseArisen", "mood": "offline"}, "radicalApologist": {"color": "#ffaa00", "handle": "radicalApologist", "mood": "offline"}, "microMachines": {"color": "#aa00ff", "handle": "microMachines", "mood": "offline"}, "uroborosUnbound": {"color": "#00416a", "handle": "uroborosUnbound", "mood": "offline"}, "arachnidsGrip": {"color": "#005682", "handle": "arachnidsGrip", "mood": "offline"}, "caligulasAquarium": {"color": "#6a006a", "handle": "caligulasAquarium", "mood": "offline"}, "percipientPedestrian": {"color": "#00ffff", "handle": "percipientPedestrian", "mood": "offline"}, "tentacleTherapist": {"color": "#cc66ff", "handle": "tentacleTherapist", "mood": "offline"}, "sucroseSaboteur": {"color": "#00e700", "handle": "sucroseSaboteur", "mood": "offline"}, "illuminatedWax": {"color": "#000000", "handle": "illuminatedWax", "mood": "offline"}, "moirailBunp": {"color": "#6a3d0f", "handle": "moirailBunp", "mood": "offline"}, "madLurker": {"color": "#000000", "handle": "madLurker", "mood": "offline"}, "testOut": {"color": "#c760cc", "handle": "testOut", "mood": "offline"}, "pesterClient3022": {"color": "#336600", "handle": "pesterClient3022", "mood": "offline"}, "hellerificJefferson": {"color": "#3300ff", "handle": "hellerificJefferson", "mood": "offline"}, "DocScratch": {"color": "#ffffff", "handle": "DocScratch", "mood": "offline"}, "recalcitrantDisaster": {"color": "#8b0068", "handle": "recalcitrantDisaster", "mood": "offline"}, "superGhost": {"color": "#800564", "handle": "superGhost", "mood": "offline"}, "arsenicCatnip": {"color": "#006400", "handle": "arsenicCatnip", "mood": "offline"}, "kaleidoscopicMind": {"color": "#ff6666", "handle": "kaleidoscopicMind", "mood": "offline"}, "zealousScarecrow": {"color": "#00c882", "handle": "zealousScarecrow", "mood": "offline"}, "captainCaveman": {"color": "#7c414e", "handle": "captainCaveman", "mood": "offline"}, "gamblingGenocider": {"color": "#00ff00", "handle": "gamblingGenocider", "mood": "offline"}, "cuttlefishCuller": {"color": "#77003c", "handle": "cuttlefishCuller", "mood": "offline"}, "wovenWay": {"color": "#000000", "handle": "wovenWay", "mood": "offline"}, "masterG": {"color": "#77003c", "handle": "masterG", "mood": "offline"}, "elegantDiversion": {"color": "#14b40a", "handle": "elegantDiversion", "mood": "offline"}, "plasmaModerator": {"color": "#5685cc", "handle": "plasmaModerator", "mood": "offline"}, "carcinoGenetecist": {"color": "#7f7f7f", "handle": "carcinoGenetecist", "mood": "offline"}, "marineAquist": {"color": "#00caca", "handle": "marineAquist", "mood": "offline"}, "remoteBloodbath": {"color": "#c70000", "handle": "remoteBloodbath", "mood": "offline"}, "oilslickOrchid": {"color": "#743f7e", "handle": "oilslickOrchid", "mood": "offline"}, "acapellaWaterfall": {"color": "#000099", "handle": "acapellaWaterfall", "mood": "offline"}, "gallowsCalibrator": {"color": "#008282", "handle": "gallowsCalibrator", "mood": "offline"}, "rageInducer": {"color": "#00ffff", "handle": "rageInducer", "mood": "offline"}, "anguillaNuntia": {"color": "#ff007f", "handle": "anguillaNuntia", "mood": "offline"}, "greenZephyr": {"color": "#00ca40", "handle": "greenZephyr", "mood": "offline"}, "lawdEngrish": {"color": "#00ff00", "handle": "lawdEngrish", "mood": "offline"}, "pretentiousFantasia": {"color": "#ff66cf", "handle": "pretentiousFantasia", "mood": "offline"}, "counterRealist": {"color": "#10d985", "handle": "counterRealist", "mood": "offline"}, "maxiumumFatness": {"color": "#3366ff", "handle": "maxiumumFatness", "mood": "offline"}, "schlagzeugGator": {"color": "#61821f", "handle": "schlagzeugGator", "mood": "offline"}, "metaliAggressive": {"color": "#9289d5", "handle": "metaliAggressive", "mood": "offline"}, "midnightSparrow": {"color": "#ff55ff", "handle": "midnightSparrow", "mood": "offline"}, "magmaExploiter": {"color": "#d90000", "handle": "magmaExploiter", "mood": "offline"}, "gardenGnostic": {"color": "#00ff00", "handle": "gardenGnostic", "mood": "offline"}, "unknownTraveler": {"color": "#006666", "handle": "unknownTraveler", "mood": "offline"}, "utilitarianTurnabout": {"color": "#dd0000", "handle": "utilitarianTurnabout", "mood": "offline"}, "adiosToreador": {"color": "#aa5500", "handle": "adiosToreador", "mood": "offline"}} \ No newline at end of file diff --git a/memos.py b/memos.py index 10b7786..ec8bb6b 100644 --- a/memos.py +++ b/memos.py @@ -1,12 +1,14 @@ from string import Template import re +from copy import copy from PyQt4 import QtGui, QtCore from datetime import time, timedelta, datetime from dataobjs import PesterProfile, Mood, PesterHistory from generic import PesterIcon, RightClickList from convo import PesterConvo, PesterInput, PesterText, PesterTabWindow -from parsetools import convertTags, addTimeInitial, timeProtocol +from parsetools import convertTags, addTimeInitial, timeProtocol, \ + lexMessage, colorBegin, colorEnd, mecmd def delta2txt(d, format="pc"): if format == "pc": @@ -223,18 +225,20 @@ class MemoText(PesterText): else: self.setStyleSheet("QTextEdit { %s }" % theme["memos/textarea/style"]) - def addMessage(self, text, chum): + def addMessage(self, msg, chum): + if type(msg) in [str, unicode]: + lexmsg = lexMessage(msg) + else: + lexmsg = msg parent = self.parent() window = parent.mainwindow me = window.profile() - quirks = window.userprofile.quirks if parent.applyquirks else None - msg = unicode(text) chumdb = window.chumdb if chum is not me: # SO MUCH WH1T3SP4C3 >:] - mobj = _ctag_begin.match(text) # get color from tag - if mobj: + if type(lexmsg[0]) is colorBegin: # get color tag + colortag = lexmsg[0] try: - color = QtGui.QColor(*[int(c) for c in mobj.group(1).split(",")]) + color = QtGui.QColor(*[int(c) for c in colortag.color.split(",")]) except ValueError: color = QtGui.QColor("black") else: @@ -257,7 +261,7 @@ class MemoText(PesterText): # new chum! time current newtime = timedelta(0) time = TimeTracker(newtime) - parent.times[chum.handle] = time + parent.times[handle] = time else: time = parent.time @@ -265,26 +269,16 @@ class MemoText(PesterText): grammar = time.getGrammar() joinmsg = chum.memojoinmsg(systemColor, time.getTime(), grammar, window.theme["convo/text/joinmemo"]) self.append(convertTags(joinmsg)) - parent.mainwindow.chatlog.log(parent.channel, convertTags(msg, "bbcode")) + parent.mainwindow.chatlog.log(parent.channel, joinmsg) time.openCurrentTime() - if msg[0:3] == "/me" or msg[0:13] == "PESTERCHUM:ME": - if quirks: - msg = quirks.apply(msg) - if msg[0:3] == "/me": - start = 3 - else: - start = 13 - space = msg.find(" ") - memsg = chum.memsg(systemColor, msg[start:space], msg[space:], time=time.getGrammar()) - window.chatlog.log(parent.channel, convertTags(msg, "bbcode")) + if type(lexmsg[0]) is mecmd: + memsg = chum.memsg(systemColor, lexmsg, time=time.getGrammar()) + window.chatlog.log(parent.channel, memsg) self.append(convertTags(memsg)) else: - if chum is not me: - msg = addTimeInitial(msg, parent.times[chum.handle].getGrammar()) - self.append(convertTags(msg, quirksobj=quirks)) - window.chatlog.log(parent.channel, convertTags(msg, "bbcode", quirks)) - + self.append(convertTags(lexmsg)) + window.chatlog.log(parent.channel, lexmsg) def changeTheme(self, theme): self.initTheme(theme) @@ -398,7 +392,7 @@ class PesterMemo(PesterConvo): msg = p.memoopenmsg(systemColor, self.time.getTime(), timeGrammar, self.mainwindow.theme["convo/text/openmemo"], self.channel) self.time.openCurrentTime() self.textArea.append(convertTags(msg)) - self.mainwindow.chatlog.log(self.channel, convertTags(msg, "bbcode")) + self.mainwindow.chatlog.log(self.channel, msg) self.op = False self.newmessage = False @@ -537,7 +531,7 @@ class PesterMemo(PesterConvo): self.times[handle].removeTime(close) msg = chum.memoclosemsg(systemColor, grammar, window.theme["convo/text/closememo"]) self.textArea.append(convertTags(msg)) - self.mainwindow.chatlog.log(self.channel, convertTags(msg, "bbcode")) + self.mainwindow.chatlog.log(self.channel, msg) elif timed not in self.times[handle]: self.times[handle].addTime(timed) else: @@ -556,20 +550,26 @@ class PesterMemo(PesterConvo): if self.time.getTime() == None: self.sendtime() grammar = self.time.getGrammar() - if text[0:3] != "/me": + quirks = self.mainwindow.userprofile.quirks + lexmsg = lexMessage(text) + if type(lexmsg[0]) is not mecmd: + if self.applyquirks: + lexmsg = quirks.apply(lexmsg) initials = self.mainwindow.profile().initials() colorcmd = self.mainwindow.profile().colorcmd() - clientText = "%s%s%s: %s" % (colorcmd, grammar.pcf, initials, grammar.number, text) + clientMsg = [colorBegin("" % (colorcmd), colorcmd), + "%s%s%s: " % (grammar.pcf, initials, grammar.number)] + lexmsg + [colorEnd("")] # account for TC's parsing error - serverText = "%s: %s " % (colorcmd, initials, text) + serverMsg = [colorBegin("" % (colorcmd), colorcmd), + "%s: " % (initials)] + lexmsg + [colorEnd(""), " "] else: - clientText = text - serverText = clientText - self.addMessage(clientText, True) - # convert color tags - quirks = self.mainwindow.userprofile.quirks if self.applyquirks else None - serverText = convertTags(unicode(serverText), "ctag", quirks) + clientMsg = copy(lexmsg) + serverMsg = copy(lexmsg) + + self.addMessage(clientMsg, True) + serverText = convertTags(serverMsg, "ctag") self.messageSent.emit(serverText, self.title()) + self.textInput.setText("") @QtCore.pyqtSlot() def namesUpdated(self): @@ -611,7 +611,7 @@ class PesterMemo(PesterConvo): grammar = t.getGrammar() msg = chum.memoclosemsg(systemColor, grammar, self.mainwindow.theme["convo/text/closememo"]) self.textArea.append(convertTags(msg)) - self.mainwindow.chatlog.log(self.channel, convertTags(msg, "bbcode")) + self.mainwindow.chatlog.log(self.channel, msg) self.times[h].removeTime(t.getTime()) if update == "nick": self.addUser(newnick) @@ -639,7 +639,7 @@ class PesterMemo(PesterConvo): opgrammar = TimeGrammar("CURRENT", "C", "RIGHT NOW") msg = chum.memobanmsg(opchum, opgrammar, systemColor, grammar) self.textArea.append(convertTags(msg)) - self.mainwindow.chatlog.log(self.channel, convertTags(msg, "bbcode")) + self.mainwindow.chatlog.log(self.channel, msg) ttracker.removeTime(ttracker.getTime()) if chum is self.mainwindow.profile(): @@ -658,7 +658,7 @@ class PesterMemo(PesterConvo): self.time.openCurrentTime() msg = me.memoopenmsg(systemColor, self.time.getTime(), self.time.getGrammar(), self.mainwindow.theme["convo/text/openmemo"], self.channel) self.textArea.append(convertTags(msg)) - self.mainwindow.chatlog.log(self.channel, convertTags(msg, "bbcode")) + self.mainwindow.chatlog.log(self.channel, msg) elif ret == QtGui.QMessageBox.Cancel: if self.parent(): i = self.parent().tabIndices[self.channel] @@ -725,7 +725,7 @@ class PesterMemo(PesterConvo): systemColor = QtGui.QColor(self.mainwindow.theme["memos/systemMsgColor"]) msg = me.memoclosemsg(systemColor, grammar, self.mainwindow.theme["convo/text/closememo"]) self.textArea.append(convertTags(msg)) - self.mainwindow.chatlog.log(self.channel, convertTags(msg, "bbcode")) + self.mainwindow.chatlog.log(self.channel, msg) newtime = self.time.getTime() if newtime is None: @@ -738,12 +738,13 @@ class PesterMemo(PesterConvo): time = self.time.prevTime() self.time.setCurrent(time) self.resetSlider(time) + self.textInput.setFocus() @QtCore.pyqtSlot() def nexttime(self): time = self.time.nextTime() self.time.setCurrent(time) self.resetSlider(time) - + self.textInput.setFocus() def closeEvent(self, event): self.mainwindow.waitingMessages.messageAnswered(self.channel) self.windowClosed.emit(self.title()) diff --git a/memos.pyc b/memos.pyc index 749749e..3061b67 100644 Binary files a/memos.pyc and b/memos.pyc differ diff --git a/menus.py b/menus.py index f0acdd1..15794fd 100644 --- a/menus.py +++ b/menus.py @@ -30,7 +30,7 @@ class PesterQuirkList(QtGui.QListWidget): for q in mainwindow.userprofile.quirks: item = PesterQuirkItem(q, self) self.addItem(item) - self.sortItems() + #self.sortItems() @QtCore.pyqtSlot() def removeCurrent(self): @@ -38,6 +38,77 @@ class PesterQuirkList(QtGui.QListWidget): if i >= 0: self.takeItem(i) +class RandomQuirkDialog(MultiTextDialog): + def __init__(self, parent): + QtGui.QDialog.__init__(self, parent) + self.setWindowTitle("RANDOM QUIRK") + self.inputs = {} + layout_1 = QtGui.QHBoxLayout() + regexpl = QtGui.QLabel("REGEXP:", self) + self.regexp = QtGui.QLineEdit(self) + layout_1.addWidget(regexpl) + layout_1.addWidget(self.regexp) + replacewithl = QtGui.QLabel("REPLACE WITH:", self) + + layout_2 = QtGui.QVBoxLayout() + layout_3 = QtGui.QHBoxLayout() + self.replacelist = QtGui.QListWidget(self) + self.replaceinput = QtGui.QLineEdit(self) + addbutton = QtGui.QPushButton("ADD", self) + self.connect(addbutton, QtCore.SIGNAL('clicked()'), + self, QtCore.SLOT('addRandomString()')) + removebutton = QtGui.QPushButton("REMOVE", self) + self.connect(removebutton, QtCore.SIGNAL('clicked()'), + self, QtCore.SLOT('removeRandomString()')) + layout_3.addWidget(addbutton) + layout_3.addWidget(removebutton) + layout_2.addWidget(self.replacelist) + layout_2.addWidget(self.replaceinput) + layout_2.addLayout(layout_3) + layout_1.addLayout(layout_2) + + self.ok = QtGui.QPushButton("OK", self) + self.ok.setDefault(True) + self.connect(self.ok, QtCore.SIGNAL('clicked()'), + self, QtCore.SLOT('accept()')) + self.cancel = QtGui.QPushButton("CANCEL", self) + self.connect(self.cancel, QtCore.SIGNAL('clicked()'), + self, QtCore.SLOT('reject()')) + layout_ok = QtGui.QHBoxLayout() + layout_ok.addWidget(self.cancel) + layout_ok.addWidget(self.ok) + + layout_0 = QtGui.QVBoxLayout() + layout_0.addLayout(layout_1) + layout_0.addLayout(layout_ok) + + self.setLayout(layout_0) + + def getText(self): + r = self.exec_() + if r == QtGui.QDialog.Accepted: + randomlist = [unicode(self.replacelist.item(i).text()) + for i in range(0,self.replacelist.count())] + retval = {"from": unicode(self.regexp.text()), + "randomlist": randomlist } + return retval + else: + return None + + + @QtCore.pyqtSlot() + def addRandomString(self): + text = unicode(self.replaceinput.text()) + item = QtGui.QListWidgetItem(text, self.replacelist) + self.replaceinput.setText("") + @QtCore.pyqtSlot() + def removeRandomString(self): + if not self.replacelist.currentItem(): + return + else: + self.replacelist.takeItem(self.currentRow()) + self.replaceinput.setFocus() + class PesterChooseQuirks(QtGui.QDialog): def __init__(self, config, theme, parent): QtGui.QDialog.__init__(self, parent) @@ -62,11 +133,17 @@ class PesterChooseQuirks(QtGui.QDialog): self.addRegexpReplaceButton = QtGui.QPushButton("REGEXP REPLACE", self) self.connect(self.addRegexpReplaceButton, QtCore.SIGNAL('clicked()'), self, QtCore.SLOT('addRegexpDialog()')) + self.addRandomReplaceButton = QtGui.QPushButton("RANDOM REPLACE", self) + self.connect(self.addRandomReplaceButton, QtCore.SIGNAL('clicked()'), + self, QtCore.SLOT('addRandomDialog()')) + layout_1 = QtGui.QHBoxLayout() layout_1.addWidget(self.addPrefixButton) layout_1.addWidget(self.addSuffixButton) layout_1.addWidget(self.addSimpleReplaceButton) - layout_1.addWidget(self.addRegexpReplaceButton) + layout_2 = QtGui.QHBoxLayout() + layout_2.addWidget(self.addRegexpReplaceButton) + layout_2.addWidget(self.addRandomReplaceButton) self.removeSelectedButton = QtGui.QPushButton("REMOVE", self) self.connect(self.removeSelectedButton, QtCore.SIGNAL('clicked()'), @@ -86,6 +163,7 @@ class PesterChooseQuirks(QtGui.QDialog): layout_0 = QtGui.QVBoxLayout() layout_0.addWidget(self.quirkList) layout_0.addLayout(layout_1) + layout_0.addLayout(layout_2) layout_0.addWidget(self.removeSelectedButton) layout_0.addLayout(layout_ok) self.setLayout(layout_0) @@ -94,7 +172,6 @@ class PesterChooseQuirks(QtGui.QDialog): return [self.quirkList.item(i).quirk for i in range(0,self.quirkList.count())] - @QtCore.pyqtSlot() def addPrefixDialog(self): pdict = MultiTextDialog("ENTER PREFIX", self, {"label": "Value:", "inputname": "value"}).getText() @@ -102,7 +179,7 @@ class PesterChooseQuirks(QtGui.QDialog): prefix = pesterQuirk(pdict) pitem = PesterQuirkItem(prefix, self.quirkList) self.quirkList.addItem(pitem) - self.quirkList.sortItems() + #self.quirkList.sortItems() @QtCore.pyqtSlot() def addSuffixDialog(self): vdict = MultiTextDialog("ENTER SUFFIX", self, {"label": "Value:", "inputname": "value"}).getText() @@ -110,7 +187,7 @@ class PesterChooseQuirks(QtGui.QDialog): quirk = pesterQuirk(vdict) item = PesterQuirkItem(quirk, self.quirkList) self.quirkList.addItem(item) - self.quirkList.sortItems() + #self.quirkList.sortItems() @QtCore.pyqtSlot() def addSimpleReplaceDialog(self): vdict = MultiTextDialog("REPLACE", self, {"label": "Replace:", "inputname": "from"}, {"label": "With:", "inputname": "to"}).getText() @@ -118,7 +195,7 @@ class PesterChooseQuirks(QtGui.QDialog): quirk = pesterQuirk(vdict) item = PesterQuirkItem(quirk, self.quirkList) self.quirkList.addItem(item) - self.quirkList.sortItems() + #self.quirkList.sortItems() @QtCore.pyqtSlot() def addRegexpDialog(self): vdict = MultiTextDialog("REGEXP REPLACE", self, {"label": "Regexp:", "inputname": "from"}, {"label": "Replace With:", "inputname": "to"}).getText() @@ -135,7 +212,23 @@ class PesterChooseQuirks(QtGui.QDialog): quirk = pesterQuirk(vdict) item = PesterQuirkItem(quirk, self.quirkList) self.quirkList.addItem(item) - self.quirkList.sortItems() + #self.quirkList.sortItems() + @QtCore.pyqtSlot() + def addRandomDialog(self): + vdict = RandomQuirkDialog(self).getText() + vdict["type"] = "random" + try: + re.compile(vdict["from"]) + except re.error, e: + quirkWarning = QtGui.QMessageBox(self) + quirkWarning.setText("Not a valid regular expression!") + quirkWarning.setInformativeText("H3R3S WHY DUMP4SS: %s" % (e)) + quirkWarning.exec_() + return + quirk = pesterQuirk(vdict) + item = PesterQuirkItem(quirk, self.quirkList) + self.quirkList.addItem(item) + #self.quirkList.sortItems() class PesterChooseTheme(QtGui.QDialog): def __init__(self, config, theme, parent): diff --git a/menus.pyc b/menus.pyc index a4bfd9e..657ace7 100644 Binary files a/menus.pyc and b/menus.pyc differ diff --git a/oyoyo/__init__.pyc b/oyoyo/__init__.pyc index be26c04..28e3e80 100644 Binary files a/oyoyo/__init__.pyc and b/oyoyo/__init__.pyc differ diff --git a/oyoyo/client.pyc b/oyoyo/client.pyc index 5ba5325..9115adc 100644 Binary files a/oyoyo/client.pyc and b/oyoyo/client.pyc differ diff --git a/oyoyo/cmdhandler.pyc b/oyoyo/cmdhandler.pyc index e9def19..d97b3d1 100644 Binary files a/oyoyo/cmdhandler.pyc and b/oyoyo/cmdhandler.pyc differ diff --git a/oyoyo/helpers.pyc b/oyoyo/helpers.pyc index e5c82c4..e5b17da 100644 Binary files a/oyoyo/helpers.pyc and b/oyoyo/helpers.pyc differ diff --git a/oyoyo/ircevents.pyc b/oyoyo/ircevents.pyc index 1f1ccd6..c83999f 100644 Binary files a/oyoyo/ircevents.pyc and b/oyoyo/ircevents.pyc differ diff --git a/oyoyo/parse.pyc b/oyoyo/parse.pyc index e67f2ea..9095b24 100644 Binary files a/oyoyo/parse.pyc and b/oyoyo/parse.pyc differ diff --git a/parsetools.py b/parsetools.py index cb703f9..cc9f8b9 100644 --- a/parsetools.py +++ b/parsetools.py @@ -4,10 +4,13 @@ from datetime import timedelta from PyQt4 import QtGui _ctag_begin = re.compile(r'(?i)') +_gtag_begin = re.compile(r'(?i)') _ctag_end = re.compile(r'(?i)') _ctag_rgb = re.compile(r'\d+,\d+,\d+') _urlre = re.compile(r"(?i)http://[^\s]+") -_memore = re.compile(r" (#[A-Za-z0-9_]+)") +_memore = re.compile(r"(\s|^)(#[A-Za-z0-9_]+)") +_imgre = re.compile(r"""(?i)""") +_mecmdre = re.compile(r"^/me(\S*)") def lexer(string, objlist): """objlist is a list: [(objecttype, re),...] list is in order of preference""" @@ -38,6 +41,8 @@ class colorBegin(object): self.color = color def convert(self, format): color = self.color + if format == "text": + return "" if _ctag_rgb.match(color) is not None: if format=='ctag': return "" % (color) @@ -64,6 +69,8 @@ class colorEnd(object): return "" elif format == "bbcode": return "[/color]" + elif format == "text": + return "" else: return self.string class hyperlink(object): @@ -76,6 +83,30 @@ class hyperlink(object): return "[url]%s[/url]" % (self.string) else: return self.string +class imagelink(object): + def __init__(self, string, img): + self.string = string + self.img = img + def convert(self, format): + if format == "html": + return self.string + elif format == "bbcode": + if self.img[0:7] == "http://": + return "[img]%s[/img]" % (img) + else: + return "" + else: + return "" +class memolex(object): + def __init__(self, string, space, channel): + self.string = string + self.space = space + self.channel = channel + def convert(self, format): + if format == "html": + return "%s%s" % (self.space, self.channel, self.channel) + else: + return self.string class smiley(object): def __init__(self, string): self.string = string @@ -84,15 +115,22 @@ class smiley(object): return "" % (smiledict[self.string]) else: return self.string +class mecmd(object): + def __init__(self, string, suffix): + self.string = string + self.suffix = suffix + def convert(self, format): + return self.string -def convertTags(string, format="html", quirkobj=None): - if format not in ["html", "bbcode", "ctag"]: - raise ValueError("Color format not recognized") - lexlist = [(colorBegin, _ctag_begin), (colorEnd, _ctag_end), - (hyperlink, _urlre), (hyperlink, _memore), +def lexMessage(string): + lexlist = [(mecmd, _mecmdre), + (colorBegin, _ctag_begin), (colorBegin, _gtag_begin), + (colorEnd, _ctag_end), (imagelink, _imgre), + (hyperlink, _urlre), (memolex, _memore), (smiley, _smilere)] - lexed = lexer(string, lexlist) + lexed = lexer(unicode(string), lexlist) + balanced = [] beginc = 0 endc = 0 @@ -111,25 +149,35 @@ def convertTags(string, format="html", quirkobj=None): if beginc > endc: for i in range(0, beginc-endc): balanced.append(colorEnd("")) + if type(balanced[len(balanced)-1]) not in [str, unicode]: + balanced.append("") + return balanced +def convertTags(lexed, format="html"): + if format not in ["html", "bbcode", "ctag", "text"]: + raise ValueError("Color format not recognized") + + if type(lexed) in [str, unicode]: + lexed = lexMessage(lexed) escaped = "" - for o in balanced: + firststr = True + for (i, o) in enumerate(lexed): if type(o) in [str, unicode]: - if quirkobj: - o = quirkobj.apply(o) if format == "html": escaped += o.replace("&", "&").replace(">", ">").replace("<","<") else: escaped += o else: escaped += o.convert(format) + return escaped def addTimeInitial(string, grammar): endofi = string.find(":") endoftag = string.find(">") - if endoftag < 0 or endoftag > 16 or endofi > 17: + # support Doc Scratch mode + if (endoftag < 0 or endoftag > 16) or (endofi < 0 or endofi > 17): return string return string[0:endoftag+1]+grammar.pcf+string[endoftag+1:endofi]+grammar.number+string[endofi:] diff --git a/parsetools.pyc b/parsetools.pyc index 7b8e8b9..7323615 100644 Binary files a/parsetools.pyc and b/parsetools.pyc differ diff --git a/pesterchum.js b/pesterchum.js index 7f21063..ff954a3 100644 --- a/pesterchum.js +++ b/pesterchum.js @@ -1 +1 @@ -{"tabs": false, "soundon": true, "chums": ["unknownTraveler", "tentacleTherapist", "vaginalEngineer", "mechanicalSpectacle", "carcinoGeneticist", "schlagzeugGator", "gamblingGenocider", "gardenGnostic", "superGhost", "centaursTesticle", "arachnidsGrip", "grimAuxiliatrix", "remoteBloodbath", "nitroZealist", "greenZephyr", "arsenicCatnip", "adiosToreador", "cuttlefishCuller", "rageInducer", "gallowsCalibrator", "caligulasAquarium", "terminallyCapricious", "illuminatedWax", "aquaMarinist", "maxiumumFatness", "elegantDiversion", "moirailBunp", "uroborosUnbound", "androidTechnician", "midnightSparrow", "apocalypseArisen", "anguillaNuntia", "oilslickOrchid", "confusedTransient", "pretentiousFantasia", "aquaticMarinist", "lyricalKeraunoscopic", "counterRealist", "ectoBiologist"], "defaultprofile": "ghostDunk", "block": []} \ No newline at end of file +{"tabs": true, "soundon": true, "chums": ["unknownTraveler", "tentacleTherapist", "vaginalEngineer", "mechanicalSpectacle", "carcinoGeneticist", "schlagzeugGator", "gamblingGenocider", "gardenGnostic", "superGhost", "centaursTesticle", "arachnidsGrip", "grimAuxiliatrix", "remoteBloodbath", "nitroZealist", "greenZephyr", "arsenicCatnip", "adiosToreador", "cuttlefishCuller", "rageInducer", "gallowsCalibrator", "caligulasAquarium", "terminallyCapricious", "illuminatedWax", "aquaMarinist", "elegantDiversion", "moirailBunp", "uroborosUnbound", "androidTechnician", "midnightSparrow", "apocalypseArisen", "anguillaNuntia", "oilslickOrchid", "confusedTransient", "pretentiousFantasia", "aquaticMarinist", "lyricalKeraunoscopic", "counterRealist", "ectoBiologist", "percipientPedestrian", "asceticClinician"], "defaultprofile": "ghostDunk", "block": []} \ No newline at end of file diff --git a/pesterchum.py b/pesterchum.py index 5d87bed..b5edad3 100644 --- a/pesterchum.py +++ b/pesterchum.py @@ -19,8 +19,8 @@ from menus import PesterChooseQuirks, PesterChooseTheme, \ from dataobjs import PesterProfile, Mood, pesterQuirk, pesterQuirks from generic import PesterIcon, RightClickList, MultiTextDialog, PesterList from convo import PesterTabWindow, PesterText, PesterInput, PesterConvo -from parsetools import convertTags -from memos import PesterMemo, MemoTabWindow +from parsetools import convertTags, addTimeInitial +from memos import PesterMemo, MemoTabWindow, TimeTracker from irc import PesterIRC class waitingMessageHolder(object): @@ -59,27 +59,35 @@ class PesterLog(object): self.handle = handle self.convos = {} def log(self, handle, msg): + bbcodemsg = convertTags(msg, "bbcode") + html = convertTags(msg, "html") + msg = convertTags(msg, "text") + modes = {"bbcode": bbcodemsg, "html": html, "text": msg} if not self.convos.has_key(handle): - if not os.path.exists("logs/%s" % (self.handle)): - os.mkdir("logs/%s" % (self.handle)) - time = datetime.now().strftime("%Y-%m-%d.%H.%M.txt") - if not os.path.exists("logs/%s/%s" % (self.handle, handle)): - os.mkdir("logs/%s/%s" % (self.handle, handle)) - fp = codecs.open("logs/%s/%s/%s.%s" % (self.handle, handle, handle, time), encoding='utf-8', mode='a') - self.convos[handle] = fp - if platform.system() == "Windows": - self.convos[handle].write(msg+"\r\n") - else: - self.convos[handle].write(msg+"\n") - self.convos[handle].flush() + time = datetime.now().strftime("%Y-%m-%d.%H.%M") + self.convos[handle] = {} + for (format, t) in modes.iteritems(): + if not os.path.exists("logs/%s/%s/%s" % (self.handle, handle, format)): + os.makedirs("logs/%s/%s/%s" % (self.handle, handle, format)) + fp = codecs.open("logs/%s/%s/%s/%s.%s.txt" % (self.handle, handle, format, handle, time), encoding='utf-8', mode='a') + self.convos[handle][format] = fp + for (format, t) in modes.iteritems(): + f = self.convos[handle][format] + if platform.system() == "Windows": + f.write(t+"\r\n") + else: + f.write(t+"\r\n") + f.flush() def finish(self, handle): if not self.convos.has_key(handle): return - self.convos[handle].close() + for f in self.convos[handle].values(): + f.close() del self.convos[handle] def close(self): for h in self.convos.keys(): - self.convos[h].close() + for f in self.convos[h].values(): + f.close() class PesterProfileDB(dict): def __init__(self): @@ -668,6 +676,10 @@ class PesterWindow(MovingWindow): self.importaction = QtGui.QAction(self.theme["main/menus/client/import"], self) self.connect(self.importaction, QtCore.SIGNAL('triggered()'), self, QtCore.SLOT('importExternalConfig()')) + self.idleaction = QtGui.QAction(self.theme["main/menus/client/idle"], self) + self.idleaction.setCheckable(True) + self.connect(self.idleaction, QtCore.SIGNAL('toggled(bool)'), + self, QtCore.SLOT('toggleIdle(bool)')) self.menu = QtGui.QMenuBar(self) @@ -676,6 +688,7 @@ class PesterWindow(MovingWindow): filemenu.addAction(opts) filemenu.addAction(memoaction) filemenu.addAction(userlistaction) + filemenu.addAction(self.idleaction) filemenu.addAction(self.importaction) filemenu.addAction(exitaction) @@ -769,7 +782,7 @@ class PesterWindow(MovingWindow): self.waitingMessages = waitingMessageHolder(self) - self.idle = False + self.autoidle = False self.idlethreshold = 600 self.idletimer = QtCore.QTimer(self) self.idleposition = QtGui.QCursor.pos() @@ -843,6 +856,14 @@ class PesterWindow(MovingWindow): # silently ignore in case we forgot to /part return memo = self.memos[chan] + msg = unicode(msg) + if not memo.times.has_key(handle): + # new chum! time current + newtime = timedelta(0) + time = TimeTracker(newtime) + memo.times[handle] = time + if msg[0:3] != "/me" and msg[0:13] != "PESTERCHUM:ME": + msg = addTimeInitial(msg, memo.times[handle].getGrammar()) memo.addMessage(msg, handle) self.alarm.play() @@ -963,6 +984,7 @@ class PesterWindow(MovingWindow): self.userlistaction.setText(theme["main/menus/client/userlist"]) self.memoaction.setText(theme["main/menus/client/memos"]) self.importaction.setText(theme["main/menus/client/import"]) + self.idleaction.setText(theme["main/menus/client/idle"]) self.filemenu.setTitle(theme["main/menus/client/_name"]) self.changetheme.setText(theme["main/menus/profile/theme"]) self.changequirks.setText(theme["main/menus/profile/quirks"]) @@ -1116,7 +1138,7 @@ class PesterWindow(MovingWindow): chum = self.convos[h].chum chumopen = self.convos[h].chumopen if chumopen: - self.chatlog.log(chum.handle, convertTags(self.profile().pestermsg(chum, QtGui.QColor(self.theme["convo/systemMsgColor"]), self.theme["convo/text/ceasepester"]), "bbcode")) + self.chatlog.log(chum.handle, self.profile().pestermsg(chum, QtGui.QColor(self.theme["convo/systemMsgColor"]), self.theme["convo/text/ceasepester"])) self.convoClosed.emit(handle) self.chatlog.finish(h) del self.convos[h] @@ -1242,7 +1264,7 @@ class PesterWindow(MovingWindow): convo = self.convos[h] msg = self.profile().pestermsg(convo.chum, QtGui.QColor(self.theme["convo/systemMsgColor"]), self.theme["convo/text/blocked"]) convo.textArea.append(convertTags(msg)) - self.chatlog.log(convo.chum.handle, convertTags(msg, "bbcode")) + self.chatlog.log(convo.chum.handle, msg) convo.updateBlocked() self.chumList.removeChum(h) if hasattr(self, 'trollslum') and self.trollslum: @@ -1259,7 +1281,7 @@ class PesterWindow(MovingWindow): convo = self.convos[h] msg = self.profile().pestermsg(convo.chum, QtGui.QColor(self.theme["convo/systemMsgColor"]), self.theme["convo/text/unblocked"]) convo.textArea.append(convertTags(msg)) - self.chatlog.log(convo.chum.handle, convertTags(msg, "bbcode")) + self.chatlog.log(convo.chum.handle, msg) convo.updateMood(convo.chum.mood, unblocked=True) chum = PesterProfile(h, chumdb=self.chumdb) if hasattr(self, 'trollslum') and self.trollslum: @@ -1271,18 +1293,16 @@ class PesterWindow(MovingWindow): @QtCore.pyqtSlot(bool) def toggleIdle(self, idle): - if self.idle and not idle: - self.idle = False - elif idle and not self.idle: - self.idle = True + if idle: sysColor = QtGui.QColor(self.theme["convo/systemMsgColor"]) verb = self.theme["convo/text/idle"] for (h, convo) in self.convos.iteritems(): msg = self.profile().idlemsg(sysColor, verb) convo.textArea.append(convertTags(msg)) - self.chatlog.log(h, convertTags(msg, "bbcode")) + self.chatlog.log(h, msg) self.sendMessage.emit("PESTERCHUM:IDLE", h) - + else: + self.idletime = 0 @QtCore.pyqtSlot() def checkIdle(self): newpos = QtGui.QCursor.pos() @@ -1291,9 +1311,14 @@ class PesterWindow(MovingWindow): else: self.idletime = 0 if self.idletime >= self.idlethreshold: - self.toggleIdle(True) + if not self.idleaction.isChecked(): + self.idleaction.toggle() + self.autoidle = True else: - self.toggleIdle(False) + if self.autoidle: + if self.idleaction.isChecked(): + self.idleaction.toggle() + self.autoidle = False self.idleposition = newpos @QtCore.pyqtSlot() def importExternalConfig(self): @@ -1801,10 +1826,9 @@ class MainProgram(QtCore.QObject): self.widget.loadingscreen = LoadingScreen(self.widget) self.connect(self.widget.loadingscreen, QtCore.SIGNAL('rejected()'), self.widget, QtCore.SLOT('close()')) - self.widget.loadingscreen = None - #status = self.widget.loadingscreen.exec_() - #if status == QtGui.QDialog.Rejected: - # sys.exit(0) + status = self.widget.loadingscreen.exec_() + if status == QtGui.QDialog.Rejected: + sys.exit(0) os._exit(self.app.exec_()) pesterchum = MainProgram() diff --git a/profiles/ghostDunk.js b/profiles/ghostDunk.js index ea311d0..338c689 100644 --- a/profiles/ghostDunk.js +++ b/profiles/ghostDunk.js @@ -1 +1 @@ -{"color": "#ff00ff", "theme": "pesterchum", "quirks": [{"to": "7", "from": "t", "type": "replace"}], "handle": "ghostDunk"} \ No newline at end of file +{"color": "#ff00ff", "theme": "pesterchum", "quirks": [], "handle": "ghostDunk"} \ No newline at end of file