diff --git a/ircrobots/formatting.py b/ircrobots/formatting.py new file mode 100644 index 0000000..d62e008 --- /dev/null +++ b/ircrobots/formatting.py @@ -0,0 +1,44 @@ +from typing import List + +BOLD = "\x02" +COLOR = "\x03" +INVERT = "\x16" +ITALIC = "\x1D" +UNDERLINE = "\x1F" +RESET = "\x0F" + +FORMATTERS = [ + BOLD, + INVERT, + ITALIC, + UNDERLINE, + RESET +] + +def tokens(s: str) -> List[str]: + tokens: List[str] = [] + + s_copy = list(s) + while s_copy: + token = s_copy.pop(0) + if token == COLOR: + for i in range(2): + if s_copy and s_copy[0].isdigit(): + token += s_copy.pop(0) + if (len(s_copy) > 1 and + s_copy[0] == "," and + s_copy[1].isdigit()): + token += s_copy.pop(0) + token += s_copy.pop(0) + if s_copy and s_copy[0].isdigit(): + token += s_copy.pop(0) + + tokens.append(token) + elif token in FORMATTERS: + tokens.append(token) + return tokens + +def strip(s: str): + for token in tokens(s): + s = s.replace(token, "", 1) + return s diff --git a/ircrobots/matching/params.py b/ircrobots/matching/params.py index 5979c9d..22b031e 100644 --- a/ircrobots/matching/params.py +++ b/ircrobots/matching/params.py @@ -1,6 +1,7 @@ -from typing import Optional -from irctokens import Hostmask -from ..interface import IMatchResponseParam, IMatchResponseHostmask, IServer +from typing import Optional +from irctokens import Hostmask +from ..interface import IMatchResponseParam, IMatchResponseHostmask, IServer +from .. import formatting class Any(IMatchResponseParam): def __repr__(self) -> str: @@ -22,12 +23,20 @@ class Folded(IMatchResponseParam): self._value = value self._folded: Optional[str] = None def __repr__(self) -> str: - return f"FoldString({self._value!r})" + return f"Folded({self._value!r})" def match(self, server: IServer, arg: str) -> bool: if self._folded is None: self._folded = server.casefold(self._value) return self._folded == server.casefold(arg) +class Formatless(Literal): + def __repr__(self) -> str: + brepr = super().__repr__() + return f"Formatless({brepr})" + def match(self, server: IServer, arg: str) -> bool: + strip = formatting.strip(arg) + return super().match(server, strip) + class Not(IMatchResponseParam): def __init__(self, param: IMatchResponseParam): self._param = param