143 lines
3.8 KiB
Python
143 lines
3.8 KiB
Python
|
|
"""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
|