feat(feishu): add Feishu inbound webhook, /gh commands and card actions

- add feishu_links D1 table and link store helpers
- implement X-Lark-Signature verification, url_verification, /gh login|logout|comment|merge|close and card.action.trigger Merge/Close
- render interactive cards with clickable title link, inline links and callback buttons (no whole-card card_link)
- bind Feishu account in OAuth callback
- document event subscription and required scopes
This commit is contained in:
RhenCloud 2026-08-27 00:04:49 +08:00
parent 3437ac5513
commit 4b99f6d33d
No known key found for this signature in database
GPG key ID: A574A617378C4E0B
38 changed files with 2449 additions and 1412 deletions

View file

@ -143,6 +143,7 @@ const en: Dict = {
"route.thread": "THREAD",
"route.chat": "CHAT",
"route.topic": "TOPIC",
"route.feishu": "Feishu",
"route.fallback": "fallback",
"route.stop": "stop",
"route.moveUp": "Move up",
@ -224,11 +225,13 @@ const en: Dict = {
"routeEditor.threadNote": "(optional)",
"routeEditor.threadPlaceholder": "Optional thread ID",
"routeEditor.platform": "Platform",
"routeEditor.platformFeishu": "Feishu",
"routeEditor.chat": "Chat ID",
"routeEditor.chatPlaceholder": "Telegram group chat ID",
"routeEditor.topic": "Topic ID",
"routeEditor.topicNote": "(optional)",
"routeEditor.topicPlaceholder": "Optional topic (message_thread_id)",
"routeEditor.feishuChatPlaceholder": "Feishu chat ID (chat_id)",
"routeEditor.errChat": "Target {n} chat ID is required",
"routeEditor.targets": "Targets",
"routeEditor.targetsNote": "(one or more destinations)",
@ -327,10 +330,12 @@ const en: Dict = {
"groupEditor.logTarget": "Webhook log channel",
"groupEditor.logTargetNote": "(optional)",
"groupEditor.logDisabled": "— Disabled —",
"groupEditor.logFeishu": "Feishu",
"groupEditor.logTargetHint":
"A Discord channel/thread or Telegram chat/topic that receives a summary of every webhook this group's routes dispatch.",
"A Discord channel/thread, Telegram chat/topic or Feishu chat that receives a summary of every webhook this group's routes dispatch.",
"groupEditor.errLogChannel": "Log channel ID is required when Discord is selected",
"groupEditor.errLogChat": "Log chat ID is required when Telegram is selected",
"groupEditor.errLogFeishuChat": "Log chat ID is required when Feishu is selected",
"groupEditor.cancel": "Cancel",
"groupEditor.save": "Save group",
"groupEditor.errIdFormat": "ID must be a-z / 0-9 / dashes",
@ -521,6 +526,7 @@ const zh: Dict = {
"route.thread": "子区",
"route.chat": "群组",
"route.topic": "话题",
"route.feishu": "飞书",
"route.fallback": "兜底",
"route.stop": "停止",
"route.moveUp": "上移",
@ -601,11 +607,13 @@ const zh: Dict = {
"routeEditor.threadNote": "(可选)",
"routeEditor.threadPlaceholder": "可选的子区 ID",
"routeEditor.platform": "平台",
"routeEditor.platformFeishu": "飞书",
"routeEditor.chat": "群组 ID",
"routeEditor.chatPlaceholder": "Telegram 群组聊天 ID",
"routeEditor.topic": "话题 ID",
"routeEditor.topicNote": "(可选)",
"routeEditor.topicPlaceholder": "可选的话题 (message_thread_id)",
"routeEditor.feishuChatPlaceholder": "飞书群组 ID (chat_id)",
"routeEditor.errChat": "第 {n} 个目标群组 ID 为必填项",
"routeEditor.targets": "目标",
"routeEditor.targetsNote": "(一个或多个推送目标)",
@ -703,10 +711,12 @@ const zh: Dict = {
"groupEditor.logTarget": "Webhook 日志频道",
"groupEditor.logTargetNote": "(可选)",
"groupEditor.logDisabled": "— 未启用 —",
"groupEditor.logFeishu": "飞书",
"groupEditor.logTargetHint":
"一个 Discord 频道/子区或 Telegram 群组/话题本分组路由分发dispatch的每个 webhook 都会向其发送摘要。",
"一个 Discord 频道/子区、Telegram 群组/话题或飞书群组本分组路由分发dispatch的每个 webhook 都会向其发送摘要。",
"groupEditor.errLogChannel": "选择 Discord 时必须填写日志频道 ID",
"groupEditor.errLogChat": "选择 Telegram 时必须填写日志群组 ID",
"groupEditor.errLogFeishuChat": "选择飞书时必须填写日志群组 ID",
"groupEditor.cancel": "取消",
"groupEditor.save": "保存分组",
"groupEditor.errIdFormat": "ID 只能是 a-z / 0-9 / 短横线",