博客自动同步至TG

通过Github的Action,博客更新时自动同步至TG

字数统计:

通过Github的Action,博客更新时自动同步至TG

AI代码如下:


name: Notify Telegram on New Post

on:
push:
    branches:
    - main
    paths:
    - 'content/posts/**.md'
workflow_dispatch: # 允许在 Actions 页面点击 "Run workflow" 手动触发

env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true # 解决 Node.js 20 弃用警告

jobs:
notify:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout code
        uses: actions/checkout@v4
        with:
        fetch-depth: 0 # 获取完整历史以确保 git diff 能对比成功

    - name: Set up Python
        uses: actions/setup-python@v5
        with:
        python-version: '3.x'

    - name: Install dependencies
        run: pip install PyYAML requests

    - name: Run notification script
        env:
        TG_BOT_TOKEN: ${{ secrets.TG_BOT_TOKEN }}
        TG_CHAT_ID: ${{ secrets.TG_CHAT_ID }}
        BASE_URL: "http://iioioii.com"
        GITHUB_EVENT_NAME: ${{ github.event_name }}
        BEFORE_SHA: ${{ github.event.before }}
        AFTER_SHA: ${{ github.event.after }}
        run: |
        python << 'EOF'
        import os
        import re
        import yaml
        import requests
        import subprocess
        import html

        # 配置信息
        token = os.getenv('TG_BOT_TOKEN')
        chat_id = os.getenv('TG_CHAT_ID')
        base_url = os.getenv('BASE_URL').rstrip('/')
        event_name = os.getenv('GITHUB_EVENT_NAME')

        def send_tg_message(content):
            url = f"https://api.telegram.org/bot{token}/sendMessage"
            data = {
                "chat_id": chat_id, 
                "text": content, 
                "parse_mode": "HTML",
                "disable_web_page_preview": False
            }
            try:
                response = requests.post(url, data=data)
                print(f"DEBUG: TG API Status: {response.status_code}, Response: {response.text}")
            except Exception as e:
                print(f"ERROR: 消息发送失败: {e}")

        # 1. 确定要处理的文件列表
        changed_files = []

        if event_name == 'workflow_dispatch':
            print("DEBUG: 检测到手动触发,获取 posts 目录下最新的一篇博文...")
            find_cmd = "find content/posts -name '*.md' -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d' '"
            try:
                last_file = subprocess.check_output(find_cmd, shell=True).decode('utf-8').strip()
                if last_file: changed_files = [last_file]
            except: pass
        else:
            print("DEBUG: 检测到代码推送,计算变更范围...")
            before = os.getenv('BEFORE_SHA')
            after = os.getenv('AFTER_SHA')
            
            # 只有在有效的推送范围内才使用 diff,否则回退到显示当前 Commit
            if before and before != "0000000000000000000000000000000000000000":
                diff_cmd = f"git diff --name-only --diff-filter=AM {before} {after}"
            else:
                diff_cmd = "git show --name-only --diff-filter=AM --pretty=''"
            
            try:
                output = subprocess.check_output(diff_cmd, shell=True).decode('utf-8')
                changed_files = [f for f in output.splitlines() if f.startswith('content/posts/') and f.endswith('.md')]
            except Exception as e:
                print(f"ERROR: 获取变更文件失败: {e}")

        print(f"DEBUG: 最终锁定待处理文件: {changed_files}")

        # 2. 遍历并解析文件
        for file_path in changed_files:
            if not os.path.exists(file_path):
                continue
            
            print(f"DEBUG: 正在解析文件: {file_path}")
            with open(file_path, 'r', encoding='utf-8') as f:
                file_content = f.read()
                # 正则匹配 YAML Front Matter
                match = re.search(r'^---\s*\n(.*?)\n---\s*', file_content, re.DOTALL)
                
                if match:
                    try:
                        yaml_data = yaml.safe_load(match.group(1))
                        
                        # 提取并转义内容
                        title = html.escape(str(yaml_data.get('title', '无标题')))
                        
                        cats_list = yaml_data.get('categories', [])
                        cats = html.escape("、".join(cats_list) if isinstance(cats_list, list) else "无")
                        
                        tags_list = yaml_data.get('tags', [])
                        tags = html.escape("、".join(tags_list) if isinstance(tags_list, list) else "无")
                        
                        summary_raw = yaml_data.get('summary', yaml_data.get('description', '暂无摘要'))
                        summary = html.escape(str(summary_raw))
                        
                        # 3. URL 逻辑处理
                        # 移除 content/ 前缀和 .md 后缀
                        rel_path = os.path.relpath(file_path, 'content')
                        url_slug = os.path.splitext(rel_path)[0]
                        post_url = f"{base_url}/{url_slug}/"

                        # 4. 格式化消息
                        msg = (
                            f"<b>【标题】</b> {title}\n"
                            f"<b>【文章分类】</b> {cats}\n"
                            f"<b>【文章标签】</b> {tags}\n"
                            f"<b>【文章摘要】</b> {summary}\n"
                            f"<b>【原文链接】</b> {post_url}"
                        )
                        
                        send_tg_message(msg)
                    except Exception as e:
                        print(f"ERROR: YAML 解析出错: {e}")
                else:
                    print(f"DEBUG: 文件 {file_path} 缺少 Front Matter,跳过。")
        EOF