"""Microsoft Teams Adaptive Card 构建器。 提供常用交互卡片的构建函数,返回 Adaptive Card JSON schema (v1.5)。 """ from __future__ import annotations from typing import Any def build_vote_card( title: str, options: list[str], callback_data: dict[str, Any] | None = None, max_selections: int | None = None, ) -> dict[str, Any]: choices = [{"title": opt, "value": opt} for opt in options[:12]] allow_multi = max_selections is not None and max_selections > 1 choice_set: dict[str, Any] = { "type": "Input.ChoiceSet", "id": "voteOption", "style": "expanded", "isMultiSelect": allow_multi, "choices": choices, } if allow_multi: choice_set["maxSelections"] = max_selections return { "type": "AdaptiveCard", "version": "1.5", "body": [ {"type": "TextBlock", "size": "Large", "weight": "Bolder", "text": title}, choice_set, ], "actions": [ { "type": "Action.Submit", "title": "投票", "data": callback_data or {}, } ], } def build_confirm_card( title: str, message: str, confirm_text: str = "确认", cancel_text: str = "取消", confirm_data: dict[str, Any] | None = None, cancel_data: dict[str, Any] | None = None, ) -> dict[str, Any]: return { "type": "AdaptiveCard", "version": "1.5", "body": [ {"type": "TextBlock", "size": "Large", "weight": "Bolder", "text": title}, {"type": "TextBlock", "text": message, "wrap": True}, ], "actions": [ { "type": "Action.Submit", "title": confirm_text, "style": "positive", "data": confirm_data or {"action": "confirm"}, }, { "type": "Action.Submit", "title": cancel_text, "style": "default", "data": cancel_data or {"action": "cancel"}, }, ], } def build_info_card( title: str, facts: dict[str, str], subtitle: str | None = None, ) -> dict[str, Any]: body: list[dict[str, Any]] = [ {"type": "TextBlock", "size": "Large", "weight": "Bolder", "text": title}, ] if subtitle: body.append({"type": "TextBlock", "text": subtitle, "isSubtle": True, "wrap": True}) body.append( { "type": "FactSet", "facts": [{"title": k, "value": v} for k, v in facts.items()], } ) return {"type": "AdaptiveCard", "version": "1.5", "body": body} def build_input_card( title: str, fields: list[dict[str, Any]], submit_text: str = "提交", callback_data: dict[str, Any] | None = None, ) -> dict[str, Any]: body: list[dict[str, Any]] = [ {"type": "TextBlock", "size": "Large", "weight": "Bolder", "text": title}, ] for field in fields: body.append(field) return { "type": "AdaptiveCard", "version": "1.5", "body": body, "actions": [ { "type": "Action.Submit", "title": submit_text, "data": callback_data or {}, } ], } def wrap_as_attachment(card: dict[str, Any]) -> dict[str, Any]: return { "contentType": "application/vnd.microsoft.card.adaptive", "content": card, } def create_hero_card( title: str, text: str, images: list[str] | None = None, buttons: list[dict[str, str]] | None = None, ) -> dict[str, Any]: card: dict[str, Any] = { "contentType": "application/vnd.microsoft.card.hero", "content": {"title": title, "text": text}, } if images: card["content"]["images"] = [{"url": url} for url in images] if buttons: card["content"]["buttons"] = [ {"type": "imBack", "title": btn["title"], "value": btn["value"]} for btn in buttons ] return card