Bot & Automation

jorgasisten

/root/hermes-projects/jorgasisten

apps/jorgasisten/services/text.py text
import re
from collections.abc import Iterable
from typing import Any

TOKEN_RE = re.compile(r"[a-z0-9]+", re.IGNORECASE)

SEARCH_NOISE_TOKENS = {
    "ada",
    "admin",
    "aku",
    "apakah",
    "barang",
    "bantu",
    "bantuin",
    "berapa",
    "bisa",
    "buat",
    "cari",
    "cariin",
    "carikan",
    "cek",
    "cekin",
    "chatbot",
    "data",
    "detail",
    "dari",
    "dimana",
    "dong",
    "dongss",
    "gua",
    "gue",
    "gw",
    "haloo",
    "halo",
    "hai",
    "harga",
    "info",
    "informasi",
    "ini",
    "itu",
    "kasih",
    "lihat",
    "liat",
    "lokasi",
    "mana",
    "mau",
    "minta",
    "produk",
    "sekarang",
    "saja",
    "saya",
    "sebutin",
    "sheet",
    "siapa",
    "stok",
    "stoknya",
    "suppliernya",
    "tampilkan",
    "tentang",
    "terbaru",
    "tolong",
    "untuk",
    "yang",
    "yaa",
    "ya",
}

VOICE_SEARCH_TOKEN_ALIASES = {
    "asalnya": "asal",
    "block": "blok",
    "brapa": "berapa",
    "dimna": "dimana",
    "fedral": "federal",
    "fario": "vario",
    "harganya": "harga",
    "forjet": "forged",
    "forjid": "forged",
    "kasting": "casting",
    "lokasinya": "lokasi",
    "pederal": "federal",
    "recing": "racing",
    "resing": "racing",
    "secher": "seher",
    "statusnya": "status",
    "seker": "seher",
    "stoknya": "stok",
    "suppliernya": "supplier",
    "tanggalnya": "tanggal",
}

VOICE_SEARCH_PHRASE_ALIASES = (
    (re.compile(r"\ber\s+e(?:ks|x)\s*(?:7|tujuh)\b", re.IGNORECASE), "rx7"),
    (re.compile(r"\berex\s*(?:7|tujuh)\b", re.IGNORECASE), "rx7"),
    (re.compile(r"\bem\s+pe\s+(?:eks|ex)\b", re.IGNORECASE), "mpx"),
)


def normalize_key(value: str) -> str:
    return "".join(TOKEN_RE.findall(value.lower()))


def tokenize(value: str) -> set[str]:
    return {token.lower() for token in TOKEN_RE.findall(value)}


def normalize_voice_search_text(value: str) -> str:
    normalized = value
    for pattern, replacement in VOICE_SEARCH_PHRASE_ALIASES:
        normalized = pattern.sub(replacement, normalized)
    return normalized


def search_token_sequence(value: str) -> list[str]:
    normalized = normalize_voice_search_text(value)
    return [
        VOICE_SEARCH_TOKEN_ALIASES.get(token.lower(), token.lower())
        for token in TOKEN_RE.findall(normalized)
    ]


def compact_search_token_sequence(value: str) -> list[str]:
    return [token for token in search_token_sequence(value) if token not in SEARCH_NOISE_TOKENS]


def search_tokens(value: str) -> set[str]:
    return set(search_token_sequence(value))


def normalize_search_key(value: str) -> str:
    return "".join(search_token_sequence(value))


def normalize_compact_search_key(value: str) -> str:
    return "".join(compact_search_token_sequence(value))


def safe_string(value: Any) -> str:
    if value is None:
        return ""
    return str(value).strip()


def compact_jsonable_rows(rows: Iterable[dict[str, Any]], limit: int = 5) -> list[dict[str, str]]:
    compacted: list[dict[str, str]] = []
    for row in rows:
        compacted.append({safe_string(key): safe_string(value) for key, value in row.items()})
        if len(compacted) >= limit:
            break
    return compacted


def split_long_message(message: str, limit: int = 3900) -> list[str]:
    if len(message) <= limit:
        return [message]

    chunks: list[str] = []
    current = ""
    for line in message.splitlines():
        if len(current) + len(line) + 1 > limit:
            if current:
                chunks.append(current.rstrip())
            current = line + "\n"
        else:
            current += line + "\n"
    if current:
        chunks.append(current.rstrip())
    return chunks