新增 Google Chat 对接的全套工具模块,包括: - 会话线程管理、消息解析与格式化 - Pub/Sub 消息解码、提及和命令识别 - 权限审批、目录管理和审计日志 - 消息缓存、媒体上传下载和 SSFR 防护 - 策略配置、卡片构建和流式回复支持
219 lines
6.0 KiB
Python
219 lines
6.0 KiB
Python
from __future__ import annotations
|
|
|
|
|
|
def build_approval_card(title: str, action_id: str, confirm_text: str = "确认", reject_text: str = "拒绝") -> dict:
|
|
return {
|
|
"cards_v2": [
|
|
{
|
|
"card_id": action_id,
|
|
"card": {
|
|
"header": {"title": title, "imageType": "SQUARE"},
|
|
"sections": [
|
|
{
|
|
"widgets": [
|
|
{
|
|
"buttonList": {
|
|
"buttons": [
|
|
_make_button(confirm_text, "approve", green=True),
|
|
_make_button(reject_text, "reject", green=False),
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
],
|
|
},
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
def build_poll_card(question: str, options: list[str], action_id: str) -> dict:
|
|
buttons = [_make_button(opt, f"poll_vote_{i}_{action_id}") for i, opt in enumerate(options)]
|
|
|
|
sections: list[dict] = []
|
|
while buttons:
|
|
chunk = buttons[:2]
|
|
buttons = buttons[2:]
|
|
sections.append({"widgets": [{"buttonList": {"buttons": chunk}}]})
|
|
|
|
return {
|
|
"cards_v2": [
|
|
{
|
|
"card_id": action_id,
|
|
"card": {
|
|
"header": {"title": question, "imageType": "SQUARE"},
|
|
"sections": sections,
|
|
},
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
def build_info_card(title: str, fields: dict[str, str]) -> dict:
|
|
widgets = []
|
|
for key, value in fields.items():
|
|
widgets.append(
|
|
{
|
|
"decoratedText": {
|
|
"topLabel": key,
|
|
"text": value,
|
|
}
|
|
}
|
|
)
|
|
|
|
return {
|
|
"cards_v2": [
|
|
{
|
|
"card": {
|
|
"header": {"title": title},
|
|
"sections": [{"widgets": widgets}],
|
|
}
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
def build_form_card(title: str, fields: list[dict], submit_action: str) -> dict:
|
|
widgets = []
|
|
for field in fields:
|
|
field_input_type = field.get("input_type", "SINGLE_LINE")
|
|
|
|
if field_input_type in ("SINGLE_SELECT", "MULTI_SELECT"):
|
|
widgets.append(
|
|
{
|
|
"selectionInput": {
|
|
"label": field.get("label", ""),
|
|
"name": field.get("name", ""),
|
|
"type": field_input_type,
|
|
"items": _build_selection_items(field.get("options", [])),
|
|
}
|
|
}
|
|
)
|
|
elif field_input_type == "DIVIDER":
|
|
widgets.append({"divider": {}})
|
|
else:
|
|
widgets.append(
|
|
{
|
|
"textInput": {
|
|
"label": field.get("label", ""),
|
|
"name": field.get("name", ""),
|
|
"type": field_input_type,
|
|
}
|
|
}
|
|
)
|
|
|
|
widgets.append({"buttonList": {"buttons": [_make_button("提交", submit_action, green=True)]}})
|
|
|
|
return {
|
|
"cards_v2": [
|
|
{
|
|
"card": {
|
|
"header": {"title": title},
|
|
"sections": [{"widgets": widgets}],
|
|
}
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
def build_exec_approval_card(
|
|
title: str,
|
|
action_id: str,
|
|
detail_fields: dict[str, str] | None = None,
|
|
) -> dict:
|
|
widgets = []
|
|
|
|
if detail_fields:
|
|
for key, value in detail_fields.items():
|
|
widgets.append(
|
|
{
|
|
"decoratedText": {
|
|
"topLabel": key,
|
|
"text": value,
|
|
}
|
|
}
|
|
)
|
|
|
|
widgets.append(
|
|
{
|
|
"buttonList": {
|
|
"buttons": [
|
|
_make_button("确认执行", f"exec_approve_{action_id}", green=True),
|
|
_make_button("拒绝执行", f"exec_reject_{action_id}", green=False),
|
|
]
|
|
}
|
|
}
|
|
)
|
|
|
|
return {
|
|
"cards_v2": [
|
|
{
|
|
"card": {
|
|
"header": {"title": title, "imageType": "SQUARE"},
|
|
"sections": [{"widgets": widgets}],
|
|
}
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
def build_selection_card(
|
|
title: str,
|
|
selection_name: str,
|
|
label: str,
|
|
options: list[dict[str, str]],
|
|
selection_type: str = "SINGLE_SELECT",
|
|
submit_action: str | None = None,
|
|
) -> dict:
|
|
widgets = [
|
|
{
|
|
"selectionInput": {
|
|
"label": label,
|
|
"name": selection_name,
|
|
"type": selection_type,
|
|
"items": _build_selection_items(options),
|
|
}
|
|
}
|
|
]
|
|
|
|
if submit_action:
|
|
widgets.append({"buttonList": {"buttons": [_make_button("提交", submit_action, green=True)]}})
|
|
|
|
return {
|
|
"cards_v2": [
|
|
{
|
|
"card": {
|
|
"header": {"title": title},
|
|
"sections": [{"widgets": widgets}],
|
|
}
|
|
}
|
|
]
|
|
}
|
|
|
|
|
|
def _make_divider() -> dict:
|
|
return {"divider": {}}
|
|
|
|
|
|
def _build_selection_items(options: list[dict[str, str]]) -> list[dict]:
|
|
items = []
|
|
for opt in options:
|
|
items.append(
|
|
{
|
|
"text": opt.get("text", opt.get("label", "")),
|
|
"value": opt.get("value", ""),
|
|
"selected": opt.get("selected", False),
|
|
}
|
|
)
|
|
return items
|
|
|
|
|
|
def _make_button(text: str, action: str, green: bool = False) -> dict:
|
|
color = {"red": 0, "green": 0.6, "blue": 0} if green else {"red": 0.6, "green": 0, "blue": 0}
|
|
return {
|
|
"text": text,
|
|
"color": color,
|
|
"onClick": {"action": {"function": action}},
|
|
}
|