Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Classify pesterquirk #186

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 0 additions & 244 deletions dataobjs.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import re
import random
import itertools
import logging
from datetime import datetime

Expand All @@ -15,249 +13,7 @@
from parsetools import (
timeDifference,
convertTags,
lexMessage,
parseRegexpFunctions,
smiledict,
)
from mispeller import mispeller

_urlre = re.compile(r"(?i)(?:^|(?<=\s))(?:(?:https?|ftp)://|magnet:)[^\s]+")
# _url2re = re.compile(r"(?i)(?<!//)\bwww\.[^\s]+?\.")
_groupre = re.compile(r"\\([0-9]+)")
_upperre = re.compile(r"upper\(([\w<>\\]+)\)")
_lowerre = re.compile(r"lower\(([\w<>\\]+)\)")
_scramblere = re.compile(r"scramble\(([\w<>\\]+)\)")
_reversere = re.compile(r"reverse\(([\w<>\\]+)\)")
_ctagre = re.compile("(</?c=?.*?>)", re.I)
_smilere = re.compile("|".join(list(smiledict.keys())))
_memore = re.compile(r"(\s|^)(#[A-Za-z0-9_]+)")
_handlere = re.compile(r"(\s|^)(@[A-Za-z0-9_]+)")
_alternian = re.compile(r"<alt>.*?</alt>")


class pesterQuirk:
def __init__(self, quirk):
if not isinstance(quirk, dict):
raise ValueError("Quirks must be given a dictionary")
self.quirk = quirk
self.type = self.quirk["type"]
if "on" not in self.quirk:
self.quirk["on"] = True
self.on = self.quirk["on"]
if "group" not in self.quirk:
self.quirk["group"] = "Miscellaneous"
self.group = self.quirk["group"]
try:
self.checkstate = self.quirk["checkstate"]
except KeyError:
pass

def apply(self, string, first=False, last=False):
if not self.on:
return string
elif self.type == "prefix":
return self.quirk["value"] + string
elif self.type == "suffix":
return string + self.quirk["value"]
elif self.type == "replace":
return string.replace(self.quirk["from"], self.quirk["to"])
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
to = self.quirk["to"]
pt = parseRegexpFunctions(to)
return re.sub(fr, pt.expand, string)
elif self.type == "random":
if len(self.quirk["randomlist"]) == 0:
return string
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"])
pt = parseRegexpFunctions(choice)
return pt.expand(mo)

return re.sub(self.quirk["from"], randomrep, string)
elif self.type == "spelling":
percentage = self.quirk["percentage"] / 100.0
words = string.split(" ")
newl = []
ctag = re.compile("(</?c=?.*?>)", re.I)
for w in words:
p = random.random()
if not ctag.search(w) and p < percentage:
newl.append(mispeller(w))
elif p < percentage:
split = ctag.split(w)
tmp = []
for s in split:
if s and not ctag.search(s):
tmp.append(mispeller(s))
else:
tmp.append(s)
newl.append("".join(tmp))
else:
newl.append(w)
return " ".join(newl)

def __str__(self):
if self.type == "prefix":
return "BEGIN WITH: %s" % (self.quirk["value"])
elif self.type == "suffix":
return "END WITH: %s" % (self.quirk["value"])
elif self.type == "replace":
return "REPLACE {} WITH {}".format(self.quirk["from"], self.quirk["to"])
elif self.type == "regexp":
return "REGEXP: {} REPLACED WITH {}".format(
self.quirk["from"],
self.quirk["to"],
)
elif self.type == "random":
return "REGEXP: {} RANDOMLY REPLACED WITH {}".format(
self.quirk["from"],
[r for r in self.quirk["randomlist"]],
)
elif self.type == "spelling":
return "MISPELLER: %d%%" % (self.quirk["percentage"])


class pesterQuirks:
def __init__(self, quirklist):
self.quirklist = []
for q in quirklist:
self.addQuirk(q)

def plainList(self):
return [q.quirk for q in self.quirklist]

def addQuirk(self, q):
if isinstance(q, dict):
self.quirklist.append(pesterQuirk(q))
elif isinstance(q, pesterQuirk):
self.quirklist.append(q)

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"]

newlist = []
for i, o in enumerate(lexed):
if not isinstance(o, str):
if i == 0:
string = " "
for p in prefix:
string += p.apply(string)
newlist.append(string)
newlist.append(o)
continue
lastStr = i == len(lexed) - 1
string = o
for q in self.quirklist:
try:
checkstate = int(q.checkstate)
except Exception:
checkstate = 0

# Exclude option is checked
if checkstate == 2:
# Check for substring that should be excluded.
excludes = []
# Return matches for links, smilies, handles, memos.
# Chain the iterators and add to excludes list.
matches = itertools.chain(
re.finditer(_urlre, string),
re.finditer(_smilere, string),
re.finditer(_handlere, string),
re.finditer(_memore, string),
re.finditer(_alternian, string),
)
excludes.extend(matches)

if excludes:
# SORT !!!
excludes.sort(key=lambda exclude: exclude.start())
# Recursion check.
# Strings like http://:3: require this.
for n in range(0, len(excludes) - 1):
if excludes[n].end() > excludes[n + 1].start():
excludes.pop(n)
# Seperate parts to be quirked.
sendparts = []
# Add string until start of exclude at index 0.
until = excludes[0].start()
sendparts.append(string[:until])
# Add strings between excludes.
for part in range(1, len(excludes)):
after = excludes[part - 1].end()
until = excludes[part].start()
sendparts.append(string[after:until])
# Add string after exclude at last index.
after = excludes[-1].end()
sendparts.append(string[after:])

# Quirk to-be-quirked parts.
recvparts = []
for part in sendparts:
# No split, apply like normal.
if q.type in ("regexp", "random"):
recvparts.append(
q.apply(part, first=(i == 0), last=lastStr)
)
elif q.type == "prefix" and i == 0:
recvparts.append(q.apply(part))
elif q.type == "suffix" and lastStr:
recvparts.append(q.apply(part))
else:
recvparts.append(q.apply(part))
# Reconstruct and update string.
string = ""
# print("excludes: " + str(excludes))
# print("sendparts: " + str(sendparts))
# print("recvparts: " + str(recvparts))
for part, exclude in enumerate(excludes):
string += recvparts[part]
string += exclude.group()
string += recvparts[-1]
else:
# No split, apply like normal.
if q.type not in ("prefix", "suffix"):
if q.type in ("regexp", "random"):
string = q.apply(string, first=(i == 0), last=lastStr)
else:
string = q.apply(string)
elif q.type == "prefix" and i == 0:
string = q.apply(string)
elif q.type == "suffix" and lastStr:
string = q.apply(string)
else:
# No split, apply like normal.
if q.type not in ("prefix", "suffix"):
if q.type in ("regexp", "random"):
string = q.apply(string, first=(i == 0), last=lastStr)
else:
string = q.apply(string)
elif q.type == "prefix" and i == 0:
string = q.apply(string)
elif q.type == "suffix" and lastStr:
string = q.apply(string)
newlist.append(string)
final = []
for n in newlist:
if isinstance(n, str):
final.extend(lexMessage(n))
else:
final.append(n)
return final

def __iter__(self):
yield from self.quirklist


class PesterProfile:
Expand Down
5 changes: 3 additions & 2 deletions menus.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
import parsetools
from theme_repo_manager import ThemeManagerWidget
from generic import RightClickList, RightClickTree, MultiTextDialog
from dataobjs import pesterQuirk, PesterProfile, PesterHistory
from dataobjs import PesterProfile, PesterHistory
from quirks import PesterQuirkFactory
from memos import TimeSlider, TimeInput
from version import _pcVersion
from convo import PesterInput, PesterText
Expand Down Expand Up @@ -925,7 +926,7 @@ def addQuirk(self):
self.quirkadd = None
return

quirk = pesterQuirk(vdict)
quirk = PesterQuirkFactory(vdict)
if self.quirkadd.quirk is None:
item = PesterQuirkItem(quirk)
self.quirkList.addItem(item)
Expand Down
11 changes: 5 additions & 6 deletions parsetools.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@
print("PyQt5 fallback (parsetools.py)")
from PyQt5 import QtGui, QtWidgets

import dataobjs

# karxi: My own contribution to this - a proper lexer.
from pnc import lexercon
from generic import mysteryTime
from quirks import ScriptQuirks
from pyquirks import PythonQuirks
from pyquirks import ScriptQuirks, PythonQuirks
from scripts.services import BOTNAMES
import quirks

PchumLog = logging.getLogger("pchumLogger")

Expand Down Expand Up @@ -764,16 +763,16 @@ def kxhandleInput(ctx, text=None, flavor=None, irc_compatible=False):
if should_quirk and not (is_action or is_ooc):
if flavor != "menus":
# Fetch the quirks we'll have to apply.
quirks = ctx.mainwindow.userprofile.quirks
quirk_collection = ctx.mainwindow.userprofile.quirks
else:
# The quirk testing window uses a different set.
quirks = dataobjs.pesterQuirks(ctx.parent().testquirks())
quirk_collection = quirks.PesterQuirkCollection(ctx.parent().testquirks())

try:
# Do quirk things. (Ugly, but it'll have to do for now.)
# TODO: Look into the quirk system, modify/redo it.
# Gotta encapsulate or we might parse the wrong way.
msg = quirks.apply([msg])
msg = quirk_collection.apply([msg])
except Exception as err:
# Tell the user we couldn't do quirk things.
# TODO: Include the actual error...and the quirk it came from?
Expand Down
5 changes: 3 additions & 2 deletions pesterchum.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
AddChumDialog,
)
from mood import Mood, PesterMoodAction, PesterMoodHandler, PesterMoodButton
from dataobjs import PesterProfile, pesterQuirk, pesterQuirks
from dataobjs import PesterProfile
from quirks import PesterQuirkCollection
from generic import (
PesterIcon,
RightClickTree,
Expand Down Expand Up @@ -2895,7 +2896,7 @@ def updateQuirks(self):
item.checkState(0) == QtCore.Qt.CheckState.Checked
)
item.quirk.quirk["group"] = item.quirk.group = curgroup
quirks = pesterQuirks(self.quirkmenu.quirks())
quirks = PesterQuirkCollection(self.quirkmenu.quirks())
self.userprofile.setQuirks(quirks)
if hasattr(self.quirkmenu, "quirktester") and self.quirkmenu.quirktester:
self.quirkmenu.quirktester.close()
Expand Down
Loading