From 8be26418b1018dccc514dc7b400c030d9973f0de Mon Sep 17 00:00:00 2001 From: Verum Date: Thu, 2 Apr 2026 21:51:01 +0700 Subject: [PATCH] =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- session_bot/render.py | 26 +++++++++++++++++++++++++- tests/test_render.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/session_bot/render.py b/session_bot/render.py index b357b76..ba11e1c 100644 --- a/session_bot/render.py +++ b/session_bot/render.py @@ -43,6 +43,20 @@ def build_actor_line(actor: dict, state: dict, config: dict) -> str: return line +def build_actor_fragment(actor: dict, state: dict, config: dict) -> str: + actor_state = state.get("actors", {}) + status_labels = {**DEFAULT_STATUS_LABELS, **config.get("status_labels", {})} + 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) + + fragment = f"{escape(label)}." + if phrase: + fragment = f"{fragment}\n {escape(phrase)}" + return fragment + + def build_actor_lines(config: dict, state: dict, skip_keys: set[str] | None = None) -> str: actor_lines: list[str] = [] skip_keys = skip_keys or set() @@ -66,7 +80,17 @@ def replace_actor_placeholders(template: str, config: dict, state: dict) -> tupl if actor is None: return match.group(0) used_keys.add(actor["key"]) - return build_actor_line(actor, state, config) + + line_start = template.rfind("\n", 0, match.start()) + 1 + line_end = template.find("\n", match.end()) + if line_end == -1: + line_end = len(template) + line_text = template[line_start:line_end] + + if line_text.strip().lower() == match.group(0).strip().lower(): + return build_actor_line(actor, state, config) + + return build_actor_fragment(actor, state, config) return ACTOR_PLACEHOLDER_RE.sub(repl, template), used_keys diff --git a/tests/test_render.py b/tests/test_render.py index 57694bf..3dafba1 100644 --- a/tests/test_render.py +++ b/tests/test_render.py @@ -64,3 +64,32 @@ def test_build_channel_text_supports_per_actor_placeholders() -> None: assert text.count("ASTAT") == 1 assert text.count("MARI") == 1 + + +def test_build_channel_text_inlines_actor_fragment_without_duplication() -> None: + config = { + "template_text": ( + '🌟 LIEBE she/her {{actor:liebe}}\n' + '🌟 VICTOR tech bot' + ), + "actors": [ + { + "key": "liebe", + "display_name": "LIEBE", + "display_html": "LIEBE", + "link": "https://t.me/liebe", + "pronouns": "she/her", + "meta_html": " she/her ", + "emoji": "🌟", + "default_status": "backstage", + "phrases": {"backstage": "в закулисье."}, + } + ], + } + state = {"actors": {}} + + text = build_channel_text(config, state) + + assert text.count("LIEBE") == 1 + assert "she/her в закулисье." in text + assert "в закулисье." in text