ForcePilot/backend/package/yuxi/channel/extensions/line/template_messages.py
Kris 7fd658af57 feat(channel): 添加 LINE 渠道扩展
新增 LINE 渠道扩展,支持在 Yuxi 平台中集成 LINE 即时通讯渠道。

包含以下功能模块:
- bot: LINE Bot 客户端封装
- config: 渠道配置管理
- gateway: SSE/WebSocket 网关接入
- webhook: Webhook 事件处理
- outbound: 外发消息管理
- streaming: 流式消息处理
- pairing: 用户配对与绑定
- security: 安全校验
- signature: 请求签名验证
- token_manager: Token 管理
- dedupe: 消息去重
- monitor: 渠道状态监控
- status: 会话状态管理
- session: 会话管理
- flex_templates: Flex 模板消息
- card_command: 卡片指令处理
- template_messages: 模板消息
- rich_menu: 富菜单管理
- actions: 动作处理
- directives: 指令处理
- delivery: 消息送达确认
- loading: 加载动画
- media: 媒体资源处理
- types: 类型定义
2026-05-21 11:16:16 +08:00

126 lines
3.8 KiB
Python

from __future__ import annotations
def create_confirm_template(
text: str,
confirm_action: dict,
cancel_action: dict | None = None,
) -> dict:
cancel = cancel_action or {"type": "message", "label": "Cancel", "text": "cancel"}
return {
"type": "confirm",
"text": text,
"actions": [
{"type": confirm_action.get("type", "message"), **{k: v for k, v in confirm_action.items() if k != "type"}},
{"type": cancel.get("type", "message"), **{k: v for k, v in cancel.items() if k != "type"}},
],
}
def create_buttons_template(
title: str,
text: str,
actions: list[dict],
*,
thumbnail_image_url: str | None = None,
image_aspect_ratio: str | None = None,
image_size: str | None = None,
default_action: dict | None = None,
) -> dict:
template: dict = {
"type": "buttons",
"text": text[:160],
"actions": actions[:4],
}
if title:
template["title"] = title[:40]
if thumbnail_image_url:
template["thumbnailImageUrl"] = thumbnail_image_url
if image_aspect_ratio:
template["imageAspectRatio"] = image_aspect_ratio
if image_size:
template["imageSize"] = image_size
if default_action:
template["defaultAction"] = {
"type": default_action.get("type", "uri"),
**{k: v for k, v in default_action.items() if k != "type"},
}
return template
def create_carousel_template(columns: list[dict]) -> dict:
return {
"type": "carousel",
"columns": columns[:12],
}
def create_image_carousel_template(columns: list[dict]) -> dict:
return {
"type": "image_carousel",
"columns": columns[:12],
}
def create_carousel_column(
title: str,
text: str,
actions: list[dict],
*,
thumbnail_image_url: str | None = None,
image_background_color: str | None = None,
default_action: dict | None = None,
) -> dict:
column: dict = {
"text": text[:120],
"actions": actions[:3],
}
if title:
column["title"] = title[:40]
if thumbnail_image_url:
column["thumbnailImageUrl"] = thumbnail_image_url
if image_background_color:
column["imageBackgroundColor"] = image_background_color
if default_action:
column["defaultAction"] = {
"type": default_action.get("type", "uri"),
**{k: v for k, v in default_action.items() if k != "type"},
}
return column
def create_yes_no_confirm(text: str, *, yes_text: str = "Yes", no_text: str = "No") -> dict:
return create_confirm_template(
text=text,
confirm_action={"type": "message", "label": yes_text, "text": yes_text.lower()},
cancel_action={"type": "message", "label": no_text, "text": no_text.lower()},
)
def create_button_menu(title: str, text: str, buttons: list[dict]) -> dict:
return create_buttons_template(title=title, text=text, actions=buttons)
def create_link_menu(title: str, text: str, links: list[tuple[str, str]]) -> dict:
actions = [{"type": "uri", "label": label[:20], "uri": url} for label, url in links[:4]]
return create_buttons_template(title=title, text=text, actions=actions)
def create_product_carousel(title: str, products: list[dict]) -> dict:
columns = []
for product in products[:12]:
columns.append(create_carousel_column(
title=product.get("title", ""),
text=product.get("text", ""),
actions=product.get("actions", []),
thumbnail_image_url=product.get("thumbnail_image_url"),
))
return create_carousel_template(columns)
def to_template_message(alt_text: str, template: dict) -> dict:
return {
"type": "template",
"altText": alt_text[:400],
"template": template,
}