Files
Otkritiebot/session_bot/render.py
Verum d8231c13a4
Some checks failed
CI / Lint (ruff + mypy) (push) Failing after 32s
CI / Run tests (push) Has been skipped
CI / Docker build test (push) Successful in 10s
post message
2026-04-02 20:59:04 +07:00

91 lines
2.9 KiB
Python

from __future__ import annotations
DEFAULT_STATUS_LABELS = {
"open": "исполняет роль",
"backstage": "в закулисье",
"delay": "задержки",
"rest": "антракт",
}
MARKDOWN_V2_SPECIALS = r"_*[]()~`>#+-=|{}.!"
def escape_markdown_v2(value: str) -> str:
return "".join(f"\\{char}" if char in MARKDOWN_V2_SPECIALS else char for char in value)
def escape_markdown_v2_url(value: str) -> str:
return value.replace("\\", "\\\\").replace(")", "\\)")
def build_hidden_link(config: dict) -> str:
url = config.get("hidden_link_url", "").strip()
if not url:
return ""
invisible = config.get("hidden_link_char", "\u2063")
return f"[{invisible}]({escape_markdown_v2_url(url)})"
def build_actor_lines(config: dict, state: dict) -> str:
actor_lines: list[str] = []
actor_state = state.get("actors", {})
status_labels = {**DEFAULT_STATUS_LABELS, **config.get("status_labels", {})}
for actor in config["actors"]:
current = actor_state.get(actor["key"], {})
status = current.get("status", actor.get("default_status", "backstage"))
phrase = current.get("phrase", actor.get("phrases", {}).get(status, ""))
label = status_labels.get(status, status)
display_name = actor.get("display_md", actor["display_name"])
meta = actor.get("meta_md", actor["pronouns"])
emoji = actor.get("emoji_md", actor.get("emoji", ""))
line = (
f"{emoji} "
f"[{escape_markdown_v2(display_name)}]({escape_markdown_v2_url(actor['link'])}) "
f"{escape_markdown_v2(meta)} "
f"{escape_markdown_v2(label)}\\."
)
if phrase:
line = f"{line}\n {escape_markdown_v2(phrase)}"
actor_lines.append(line)
actor_lines.extend(config.get("static_actor_lines_md", []))
return "\n".join(actor_lines)
def build_default_template(config: dict) -> str:
blocks = []
hidden = build_hidden_link(config)
if hidden:
blocks.append(hidden)
for key in ("header", "intro_links", "projects_block", "actors_title"):
value = config.get(key, "").strip()
if value:
blocks.append(escape_markdown_v2(value))
blocks.append("{{actors}}")
for key in ("legend", "footer"):
value = config.get(key, "").strip()
if value:
blocks.append(escape_markdown_v2(value))
return "\n\n".join(blocks)
def build_channel_text(config: dict, state: dict) -> str:
template = state.get("template", {}).get("text") or config.get("template_text") or build_default_template(config)
actors_block = build_actor_lines(config, state)
hidden_link = build_hidden_link(config)
text = template.replace("{{actors}}", actors_block)
text = text.replace("{{hidden_link}}", hidden_link)
if "{{hidden_link}}" not in template and hidden_link:
text = f"{hidden_link}\n{text}"
return text