博客自动同步至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
