ForcePilot/backend/package/yuxi/channels/adapters/msteams/presentation.py

143 lines
3.8 KiB
Python
Raw Normal View History

"""Microsoft Teams Presentation Card Builder。
buildMSTeamsPresentationCard支持 title/text/context/divider/buttons
通用 block 类型转换为 Adaptive Card
"""
from __future__ import annotations
from typing import Any
def build_presentation_card(
title: str = "",
blocks: list[dict[str, Any]] | None = None,
) -> dict[str, Any]:
body: list[dict[str, Any]] = []
if title:
body.append(
{
"type": "TextBlock",
"size": "Large",
"weight": "Bolder",
"text": title,
}
)
for block in blocks or []:
converted = _convert_block(block)
if converted:
if isinstance(converted, list):
body.extend(converted)
else:
body.append(converted)
return {
"type": "AdaptiveCard",
"version": "1.5",
"body": body,
}
def _convert_block(block: dict[str, Any]) -> dict[str, Any] | list[dict[str, Any]] | None:
block_type = block.get("type", "text")
if block_type == "text":
return {
"type": "TextBlock",
"text": block.get("text", ""),
"wrap": block.get("wrap", True),
"size": block.get("size", "default"),
"weight": block.get("weight", "default"),
"isSubtle": block.get("is_subtle", False),
"spacing": block.get("spacing", "default"),
}
if block_type == "context":
return {
"type": "TextBlock",
"text": block.get("text", ""),
"wrap": True,
"isSubtle": True,
"size": "small",
"spacing": "small",
}
if block_type == "divider":
return []
if block_type == "section":
items: list[dict[str, Any]] = []
title = block.get("title", "")
if title:
items.append(
{
"type": "TextBlock",
"text": title,
"weight": "Bolder",
"wrap": True,
}
)
text = block.get("text", "")
if text:
items.append(
{
"type": "TextBlock",
"text": text,
"wrap": True,
}
)
return items
if block_type == "facts":
facts = block.get("facts", {})
return {
"type": "FactSet",
"facts": [{"title": k, "value": v} for k, v in facts.items()],
}
if block_type == "image":
return {
"type": "Image",
"url": block.get("url", ""),
"altText": block.get("alt", ""),
"size": block.get("size", "auto"),
}
if block_type == "buttons":
buttons = block.get("buttons", [])
return {
"type": "ActionSet",
"actions": [
{
"type": "Action.OpenUrl" if btn.get("url") else "Action.Submit",
"title": btn.get("title", "Button"),
"url": btn.get("url", ""),
"data": btn.get("data", {}),
"style": btn.get("style", "default"),
}
for btn in buttons
],
}
return None
def add_actions_to_card(
card: dict[str, Any],
actions: list[dict[str, Any]],
) -> dict[str, Any]:
formatted = [
{
"type": "Action.OpenUrl" if a.get("url") else "Action.Submit",
"title": a.get("title", "Action"),
"url": a.get("url", ""),
"data": a.get("data", {}),
"style": a.get("style", "default"),
}
for a in actions
]
card["actions"] = formatted
return card