name: QQ Notify on: issues: types: [opened] pull_request_target: types: [opened, closed] release: types: [published, released] jobs: notify: runs-on: ubuntu-latest if: ${{ github.event_name != 'release' || (!github.event.release.draft && !github.event.release.prerelease) }} steps: - name: Build message id: msg env: EVENT_NAME: ${{ github.event_name }} EVENT_ACTION: ${{ github.event.action }} ISSUE_TITLE: ${{ github.event.issue.title }} ISSUE_URL: ${{ github.event.issue.html_url }} ISSUE_USER: ${{ github.event.issue.user.login }} ISSUE_BODY: ${{ github.event.issue.body }} PR_TITLE: ${{ github.event.pull_request.title }} PR_URL: ${{ github.event.pull_request.html_url }} PR_USER: ${{ github.event.pull_request.user.login }} PR_MERGED: ${{ github.event.pull_request.merged }} PR_MERGED_BY: ${{ github.event.pull_request.merged_by.login }} RELEASE_TAG: ${{ github.event.release.tag_name }} RELEASE_NAME: ${{ github.event.release.name }} RELEASE_URL: ${{ github.event.release.html_url }} RELEASE_BODY: ${{ github.event.release.body }} run: | python3 - <<'PYEOF' import os event = os.environ["EVENT_NAME"] action = os.environ.get("EVENT_ACTION", "") msg = None if event == "issues": title = os.environ["ISSUE_TITLE"] url = os.environ["ISSUE_URL"] user = os.environ["ISSUE_USER"] msg = "\n".join([ "📋 新 Issue", f"标题: {title}", f"提交者: {user}", f"链接: {url}", ]) elif event == "release": tag = os.environ["RELEASE_TAG"] name = os.environ["RELEASE_NAME"] url = os.environ["RELEASE_URL"] body = os.environ.get("RELEASE_BODY", "")[:800] import re body = re.sub(r'#{1,6}\s*', '', body) body = re.sub(r'\*\*(.+?)\*\*', r'\1', body) body = re.sub(r'\*(.+?)\*', r'\1', body) body = re.sub(r'`(.+?)`', r'\1', body) body = re.sub(r'\[(.+?)\]\(.+?\)', r'\1', body) body = re.sub(r'\n{3,}', '\n\n', body) body = body.strip() msg = "\n".join([ f"🚀 新版本发布 {tag}", "", body, "", f"下载: {url}", ]) elif event in ("pull_request", "pull_request_target"): title = os.environ["PR_TITLE"] url = os.environ["PR_URL"] if action == "opened": user = os.environ["PR_USER"] msg = "\n".join([ "🔀 新 Pull Request", f"标题: {title}", f"提交者: {user}", f"链接: {url}", ]) elif action == "closed" and os.environ.get("PR_MERGED") == "true": user = os.environ.get("PR_MERGED_BY", "unknown") msg = "\n".join([ "✅ PR 已合并", f"标题: {title}", f"合并者: {user}", f"链接: {url}", ]) with open(os.environ["GITHUB_OUTPUT"], "a") as f: if msg: f.write(f"skip=false\n") delim = "EOF_MSG" f.write(f"msg<<{delim}\n{msg}\n{delim}\n") else: f.write(f"skip=true\n") PYEOF - name: AI Analysis for Issue id: ai if: ${{ github.event_name == 'issues' && steps.msg.outputs.skip != 'true' }} env: ISSUE_TITLE: ${{ github.event.issue.title }} ISSUE_BODY: ${{ github.event.issue.body }} ISSUE_USER: ${{ github.event.issue.user.login }} DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }} run: | python3 - <<'PYEOF' import os, json, urllib.request title = os.environ["ISSUE_TITLE"] body = (os.environ.get("ISSUE_BODY") or "(无描述)")[:800] user = os.environ.get("ISSUE_USER", "unknown") api_key = os.environ.get("DEEPSEEK_API_KEY", "") if not api_key: with open(os.environ["GITHUB_OUTPUT"], "a") as f: f.write("analysis=\n") exit(0) prompt = f"""分析这个 GitHub Issue,用中文回复。格式要求(严格遵守,不要多余内容): 总结: [一句话概括核心问题] 优先级: [P0紧急/P1重要/P2普通/P3低优] 合理性: [有效问题/重复报告/信息不足/不是bug] 建议: [一句话给出处理建议或关联方向] --- 标题: {title} 提交者: {user} 内容: {body}""" req = urllib.request.Request( "https://api.deepseek.com/v1/chat/completions", data=json.dumps({ "model": "deepseek-v4-pro", "max_tokens": 300, "messages": [{"role": "user", "content": prompt}], }).encode(), headers={ "Authorization": f"Bearer {api_key}", "Content-Type": "application/json", }, ) try: resp = urllib.request.urlopen(req, timeout=20) data = json.loads(resp.read()) text = data["choices"][0]["message"]["content"] except Exception as e: text = f"(AI 分析暂时不可用: {e})" with open(os.environ["GITHUB_OUTPUT"], "a") as f: delim = "EOF_ANALYSIS" f.write(f"analysis<<{delim}\n{text}\n{delim}\n") PYEOF - name: Send to QQ group if: steps.msg.outputs.skip != 'true' env: SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} HOST: ${{ secrets.DEPLOY_HOST }} ASTRBOT_API_KEY: ${{ secrets.ASTRBOT_API_KEY }} MSG_CONTENT: ${{ steps.msg.outputs.msg }} AI_ANALYSIS: ${{ steps.ai.outputs.analysis }} run: | mkdir -p ~/.ssh echo "$SSH_KEY" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 ssh-keyscan -H "$HOST" >> ~/.ssh/known_hosts 2>/dev/null if [ -n "$AI_ANALYSIS" ]; then MSG_CONTENT="${MSG_CONTENT} 🤖 AI 分析: ${AI_ANALYSIS}" fi MSG=$(echo "$MSG_CONTENT" | jq -Rs .) ssh "root@${HOST}" "curl -s -X POST http://localhost:6185/api/v1/im/message \ -H 'Authorization: Bearer ${ASTRBOT_API_KEY}' \ -H 'Content-Type: application/json' \ -d '{\"umo\": \"default:GroupMessage:1087880322\", \"message\": ${MSG}}'"