diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml
index ff9b24e..bc448a4 100644
--- a/.github/workflows/docker-build.yml
+++ b/.github/workflows/docker-build.yml
@@ -65,3 +65,60 @@ jobs:
GITHUB_REPO_URL=https://github.com/WrBug/PolyHermes
cache-from: type=registry,ref=wrbug/polyhermes:latest
cache-to: type=inline
+
+ - name: Send Telegram notification
+ env:
+ TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
+ TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
+ run: |
+ # 检查必要的环境变量
+ if [ -z "$TELEGRAM_BOT_TOKEN" ] || [ -z "$TELEGRAM_CHAT_ID" ]; then
+ echo "⚠️ Telegram Bot Token 或 Chat ID 未配置,跳过通知"
+ exit 0
+ fi
+
+ # 获取构建信息
+ VERSION="${{ steps.extract_version.outputs.VERSION }}"
+ TAG="${{ steps.extract_version.outputs.TAG }}"
+ RELEASE_NAME="${{ github.event.release.name }}"
+ RELEASE_URL="${{ github.event.release.html_url }}"
+ REPO_NAME="${{ github.repository }}"
+
+ # 构建消息内容(使用 HTML 格式)
+ MESSAGE="✅ Docker 镜像构建成功
+
+📦 版本: ${VERSION}
+🏷️ Tag: ${TAG}
+🔗 Release: 查看 Release
+🐳 Docker 镜像: wrbug/polyhermes:${TAG}"
+
+ # 添加 Release 名称(如果有)
+ if [ -n "$RELEASE_NAME" ] && [ "$RELEASE_NAME" != "null" ] && [ "$RELEASE_NAME" != "" ]; then
+ RELEASE_NAME_ESCAPED=$(echo "$RELEASE_NAME" | sed 's/&/\&/g' | sed 's/\</g' | sed 's/>/\>/g')
+ MESSAGE="${MESSAGE}
+📝 Release 名称: ${RELEASE_NAME_ESCAPED}"
+ fi
+
+ # 发送 Telegram 消息(使用 jq 转义 JSON)
+ curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
+ -H "Content-Type: application/json" \
+ -d "$(jq -n \
+ --arg chat_id "$TELEGRAM_CHAT_ID" \
+ --arg text "$MESSAGE" \
+ '{chat_id: $chat_id, text: $text, parse_mode: "HTML", disable_web_page_preview: false}')" > /tmp/telegram_response.json
+
+ # 检查发送结果
+ if [ $? -eq 0 ]; then
+ RESPONSE=$(cat /tmp/telegram_response.json)
+ if echo "$RESPONSE" | grep -q '"ok":true'; then
+ echo "✅ Telegram 通知发送成功"
+ else
+ echo "❌ Telegram 通知发送失败: $RESPONSE"
+ # 构建成功,通知失败不应该导致整个 job 失败
+ exit 0
+ fi
+ else
+ echo "❌ 发送 Telegram 消息时发生错误"
+ # 构建成功,通知失败不应该导致整个 job 失败
+ exit 0
+ fi
\ No newline at end of file
diff --git a/.github/workflows/telegram-notify.yml b/.github/workflows/telegram-notify.yml
new file mode 100644
index 0000000..5af1259
--- /dev/null
+++ b/.github/workflows/telegram-notify.yml
@@ -0,0 +1,156 @@
+name: Telegram Notification on PR Merge
+
+on:
+ pull_request:
+ types:
+ - closed # 当 PR 被关闭(合并或关闭)时触发
+
+jobs:
+ notify:
+ runs-on: ubuntu-latest
+
+ # 只在 PR 被合并到 main 分支时执行
+ if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main'
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Get PR details
+ id: pr_details
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ PR_NUMBER="${{ github.event.pull_request.number }}"
+ REPO="${{ github.repository }}"
+
+ # 获取 PR 详细信息
+ PR_RESPONSE=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \
+ -H "Accept: application/vnd.github.v3+json" \
+ "https://api.github.com/repos/${REPO}/pulls/${PR_NUMBER}")
+
+ # 获取 PR 变更的文件列表
+ FILES_RESPONSE=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" \
+ -H "Accept: application/vnd.github.v3+json" \
+ "https://api.github.com/repos/${REPO}/pulls/${PR_NUMBER}/files")
+
+ # 提取 PR 描述(body),保留换行,限制长度
+ PR_BODY=$(echo "$PR_RESPONSE" | jq -r '.body // ""')
+ if [ ${#PR_BODY} -gt 500 ]; then
+ PR_BODY="${PR_BODY:0:500}..."
+ fi
+
+ # 保存到输出变量(使用 base64 编码避免特殊字符问题)
+ echo "pr_body<> $GITHUB_OUTPUT
+ echo "$PR_BODY" >> $GITHUB_OUTPUT
+ echo "EOF" >> $GITHUB_OUTPUT
+
+ - name: Send Telegram notification
+ env:
+ TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
+ TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
+ run: |
+ # 检查必要的环境变量
+ # 注意:TELEGRAM_CHAT_ID 可以是个人聊天 ID(正数)或群组 ID(负数,如 -1001234567890)
+ if [ -z "$TELEGRAM_BOT_TOKEN" ] || [ -z "$TELEGRAM_CHAT_ID" ]; then
+ echo "⚠️ Telegram Bot Token 或 Chat ID 未配置,跳过通知"
+ exit 0
+ fi
+
+ # 获取 PR 基本信息
+ PR_NUMBER="${{ github.event.pull_request.number }}"
+ PR_TITLE="${{ github.event.pull_request.title }}"
+ PR_URL="${{ github.event.pull_request.html_url }}"
+ PR_MERGE_COMMIT="${{ github.event.pull_request.merge_commit_sha }}"
+
+ # 获取 PR 详细信息
+ PR_BODY="${{ steps.pr_details.outputs.pr_body }}"
+
+ # 转义 PR 标题和描述中的 HTML 特殊字符(但保留已有的 HTML 标签)
+ PR_TITLE_ESCAPED=$(echo "$PR_TITLE" | sed 's/&/\&/g' | sed 's/\</g' | sed 's/>/\>/g')
+
+ # 构建消息内容(使用 HTML 格式)
+ MESSAGE="🚀 PR 已合并到 main 分支
+
+📝 PR #${PR_NUMBER}: ${PR_TITLE_ESCAPED}
+🔗 链接: 查看 PR
+🔀 合并提交: ${PR_MERGE_COMMIT:0:7}"
+
+ # 添加 PR 描述(如果有)
+ if [ -n "$PR_BODY" ] && [ "$PR_BODY" != "null" ] && [ "$PR_BODY" != "" ]; then
+ # 使用 Python 将 Markdown 转换为 HTML(更可靠)
+ PR_BODY_HTML=$(python3 << 'PYTHON_SCRIPT'
+import sys
+import re
+
+text = sys.stdin.read()
+
+# 转义 HTML 特殊字符(先转义,避免破坏后续的转换)
+text = text.replace('&', '&')
+text = text.replace('<', '<')
+text = text.replace('>', '>')
+
+# 代码块:```code``` → code
+text = re.sub(r'```([^`]+)```', r'\1
', text, flags=re.DOTALL)
+
+# 行内代码:`code` → code(不在代码块中)
+text = re.sub(r'`([^`]+)`', r'\1', text)
+
+# 粗体:**text** → text
+text = re.sub(r'\*\*([^*]+)\*\*', r'\1', text)
+
+# 斜体:*text* → text(不在粗体或代码中)
+text = re.sub(r'(?]*)\*([^*<>]+)\*(?![^<]*>)', r'\1', text)
+
+# 链接:[text](url) → text
+text = re.sub(r'\[([^\]]+)\]\(([^)]+)\)', r'\1', text)
+
+# 标题:# Heading → Heading
+text = re.sub(r'^### (.+)$', r'\1', text, flags=re.MULTILINE)
+text = re.sub(r'^## (.+)$', r'\1', text, flags=re.MULTILINE)
+text = re.sub(r'^# (.+)$', r'\1', text, flags=re.MULTILINE)
+
+# 列表项:- item → • item
+text = re.sub(r'^- (.+)$', r'• \1', text, flags=re.MULTILINE)
+text = re.sub(r'^ - (.+)$', r' • \1', text, flags=re.MULTILINE)
+text = re.sub(r'^ - (.+)$', r' • \1', text, flags=re.MULTILINE)
+
+# 换行处理:Telegram HTML 模式不支持
标签,直接保留换行符 \n
+# Telegram 会自动将 \n 渲染为换行
+
+# 限制长度
+if len(text) > 1000:
+ text = text[:1000] + '...\n(内容已截断)'
+
+print(text, end='')
+PYTHON_SCRIPT
+ <<< "$PR_BODY")
+
+ MESSAGE="${MESSAGE}
+
+📄 PR 描述:
+${PR_BODY_HTML}"
+ fi
+
+ # 发送 Telegram 消息(使用 jq 转义 JSON)
+ curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
+ -H "Content-Type: application/json" \
+ -d "$(jq -n \
+ --arg chat_id "$TELEGRAM_CHAT_ID" \
+ --arg text "$MESSAGE" \
+ '{chat_id: $chat_id, text: $text, parse_mode: "HTML", disable_web_page_preview: false}')" > /tmp/telegram_response.json
+
+ # 检查发送结果
+ if [ $? -eq 0 ]; then
+ RESPONSE=$(cat /tmp/telegram_response.json)
+ if echo "$RESPONSE" | grep -q '"ok":true'; then
+ echo "✅ Telegram 通知发送成功"
+ else
+ echo "❌ Telegram 通知发送失败: $RESPONSE"
+ exit 1
+ fi
+ else
+ echo "❌ 发送 Telegram 消息时发生错误"
+ exit 1
+ fi
+