53 lines
1.6 KiB
Python
53 lines
1.6 KiB
Python
import re
|
|
|
|
from .constants import BACKEND_TELEGRAM, PREFIXES
|
|
from .models import Command
|
|
|
|
NAME_RE = re.compile(r"^[a-z][a-z0-9_]{0,31}$")
|
|
QUOTES = {'"': '"', "“": "”", "„": "“"}
|
|
|
|
|
|
def tokenize(text: str) -> list[str]:
|
|
tokens: list[str] = []
|
|
current: list[str] = []
|
|
in_token = False
|
|
closing: str | None = None
|
|
for char in text:
|
|
if closing:
|
|
if char == closing:
|
|
closing = None
|
|
else:
|
|
current.append(char)
|
|
elif char in QUOTES and not in_token:
|
|
closing, in_token = QUOTES[char], True
|
|
elif char.isspace():
|
|
if in_token:
|
|
tokens.append("".join(current))
|
|
current, in_token = [], False
|
|
else:
|
|
current.append(char)
|
|
in_token = True
|
|
if in_token:
|
|
tokens.append("".join(current))
|
|
return tokens
|
|
|
|
|
|
def parse(backend: str, text: str, bot_name: str | None = None) -> Command | None:
|
|
prefix = PREFIXES.get(backend)
|
|
text = text.strip()
|
|
if not prefix or not text.startswith(prefix):
|
|
return None
|
|
body = text[len(prefix):]
|
|
if not body or body[0].isspace():
|
|
return None
|
|
parts = body.split(None, 1)
|
|
head, rest = parts[0], parts[1] if len(parts) > 1 else ""
|
|
head, _, addressed = head.partition("@")
|
|
if addressed and (backend != BACKEND_TELEGRAM or (bot_name and addressed.lower() != bot_name.lower().lstrip("@"))):
|
|
return None
|
|
name = head.lower()
|
|
if not NAME_RE.match(name):
|
|
return None
|
|
rest = rest.strip()
|
|
return Command(name, tuple(tokenize(rest)), rest)
|