from __future__ import annotations import json import logging from yuxi.channel.security.html_guard import sanitize_text_content_preserve_entities logger = logging.getLogger(__name__) def build_markdown_card(text: str) -> dict: return { "schema": "2.0", "config": { "width_mode": "fill", "enable_forward": True, }, "body": { "elements": [ { "tag": "markdown", "content": sanitize_text_content_preserve_entities(text), } ] }, } def build_structured_card( text: str, *, title: str | None = None, template: str = "blue", note: str | None = None, ) -> dict: card: dict = { "schema": "2.0", "config": {"width_mode": "fill"}, } if title: card["header"] = { "title": {"tag": "plain_text", "content": title}, "template": template, } card["body"] = { "elements": [ { "tag": "markdown", "content": sanitize_text_content_preserve_entities(text), } ] } if note: card["note"] = { "elements": [ {"tag": "plain_text", "content": note} ] } return card def build_presentation_card( text: str, *, title: str, template: str = "blue", actions: list[dict] | None = None, ) -> dict: card: dict = { "schema": "2.0", "config": {"width_mode": "fill"}, "header": { "title": {"tag": "plain_text", "content": title}, "template": template, }, "body": { "elements": [ {"tag": "markdown", "content": sanitize_text_content_preserve_entities(text)}, {"tag": "hr"}, ] }, } if actions: card["elements"] = card.get("elements", []) + actions return card def build_button( text: str, *, action: str = "", value: str = "", button_type: str = "default", confirm: dict | None = None, ) -> dict: btn = { "tag": "button", "text": {"tag": "plain_text", "content": text}, "type": button_type, } if action: btn["value"] = json.dumps({"action": action, "value": value}, ensure_ascii=False) if confirm: btn["confirm"] = confirm return btn def build_select_menu( placeholder: str, *, options: list[dict] | None = None, action: str = "", ) -> dict: select = { "tag": "select_static", "placeholder": {"tag": "plain_text", "content": placeholder}, } if options: select["options"] = [ {"text": {"tag": "plain_text", "content": opt.get("text", "")}, "value": opt.get("value", "")} for opt in options ] return select HEADER_TEMPLATE_COLORS = { "blue": "blue", "green": "green", "red": "red", "orange": "orange", "purple": "purple", "indigo": "indigo", "wathet": "wathet", "turquoise": "turquoise", "yellow": "yellow", "grey": "grey", "carmine": "carmine", "violet": "violet", "lime": "lime", } TEMPLATE_TO_PRESENTATION_TONE = { "blue": "default", "green": "success", "red": "danger", "orange": "warning", }