应该 OK 了

This commit is contained in:
Cheng Zheng
2025-12-20 13:38:18 +08:00
parent 811ae026ca
commit 57e9b3e238

View File

@@ -1,54 +1,49 @@
import os import os
import re import re
import datetime import datetime
from github import Github # https://github.com/PyGithub/PyGithub from github import Github
from openai import OpenAI from openai import OpenAI
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
# ================= 配置区 ================= # ================= 配置区 =================
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
API_KEY = os.getenv("LLM_API_KEY") API_KEY = os.getenv("LLM_API_KEY")
BASE_URL = os.getenv("LLM_BASE_URL", "https://api.openai.com/v1") BASE_URL = os.getenv("LLM_BASE_URL", "https://api.openai.com/v1")
REPO_NAME = "1c7/chinese-independent-developer" # os.getenv("GITHUB_REPOSITORY") REPO_NAME = "1c7/chinese-independent-developer"
ISSUE_NUMBER = 160 # 你在维护的那个 Issue 编号 ISSUE_NUMBER = 160
ADMIN_HANDLE = "1c7" # 替换为你的 GitHub ID ADMIN_HANDLE = "1c7"
TRIGGER_EMOJI = "rocket" # 🚀 TRIGGER_EMOJI = "rocket" # 🚀
SUCCESS_EMOJI = "hooray" # 🎉 SUCCESS_EMOJI = "hooray" # 🎉
# ========================================== # ==========================================
def remove_quote_blocks(text: str) -> str: def remove_quote_blocks(text: str) -> str:
"""移除 GitHub 引用回复块(以 > 开头的行)""" """移除 GitHub 引用回复块"""
lines = text.split('\n') lines = text.split('\n')
cleaned_lines = [] cleaned_lines = []
for line in lines: for line in lines:
# 检查去除前导空格后是否以 > 开头
if not line.lstrip().startswith('>'): if not line.lstrip().startswith('>'):
cleaned_lines.append(line) cleaned_lines.append(line)
# 重新拼接,并清理多余空行
result = '\n'.join(cleaned_lines) result = '\n'.join(cleaned_lines)
# 移除连续多个空行,保留单个空行
result = re.sub(r'\n{3,}', '\n\n', result) result = re.sub(r'\n{3,}', '\n\n', result)
return result.strip() return result.strip()
def get_ai_format(raw_text): def get_ai_project_line(raw_text):
"""只让 AI 提取项目名称、链接和描述行"""
client = OpenAI(api_key=API_KEY, base_url=BASE_URL) client = OpenAI(api_key=API_KEY, base_url=BASE_URL)
prompt = f""" prompt = f"""
你是一个严格的文案编辑。任务将用户的项目介绍转换为标准的 Markdown 格式。 任务将用户的项目介绍转换为单行 Markdown 格式。
要求:
4. 格式模板: 1. 严格禁止使用“一款、一个、完全免费、高效、简洁、强大、快速、好用”等营销废话。
#### 制作者名字 - [Github](链接) 2. 描述必须以“用途”或“功能”作为动词开头。
* :white_check_mark: [项目名](链接):用途描述 3. 严禁使用加粗格式(不要使用 **)。
4. 仅输出以下格式的一行文字:
* :white_check_mark: [项目名](网址):用途描述
待处理文本: 待处理文本:
{raw_text} {raw_text}
""" """
response = client.chat.completions.create( response = client.chat.completions.create(
model="deepseek-reasoner", # 或者使用 deepseek-chat model="deepseek-chat",
messages=[{"role": "user", "content": prompt}], messages=[{"role": "user", "content": prompt}],
temperature=0.3 temperature=0.3
) )
@@ -59,87 +54,95 @@ def main():
repo = g.get_repo(REPO_NAME) repo = g.get_repo(REPO_NAME)
issue = repo.get_issue(ISSUE_NUMBER) issue = repo.get_issue(ISSUE_NUMBER)
# 计算 3 天前的时间GitHub API 使用的是 UTC 时间)
time_threshold = datetime.now(timezone.utc) - timedelta(days=3) time_threshold = datetime.now(timezone.utc) - timedelta(days=3)
# 如果你一定要死守 2025-12-15也可以手动指定
# time_threshold = datetime(2025, 12, 15, tzinfo=timezone.utc)
# 重点:在这里加上 since 参数
comments = issue.get_comments(since=time_threshold) comments = issue.get_comments(since=time_threshold)
processed_count = 0 processed_count = 0
for comment in comments: for comment in comments:
# 1. 检查是否有你的 🚀 反应
reactions = comment.get_reactions() reactions = comment.get_reactions()
has_trigger = any(r.content == TRIGGER_EMOJI and r.user.login == ADMIN_HANDLE for r in reactions) has_trigger = any(r.content == TRIGGER_EMOJI and r.user.login == ADMIN_HANDLE for r in reactions)
# 2. 检查是否已经标记过成功 🎉
has_success = any(r.content == SUCCESS_EMOJI for r in reactions) has_success = any(r.content == SUCCESS_EMOJI for r in reactions)
if has_trigger and not has_success: if has_trigger and not has_success:
print(f"发现待处理评论 ID: {comment.id}") print(f"处理评论 ID: {comment.id}")
# 清理引用块,然后 AI 格式化内容
cleaned_body = remove_quote_blocks(comment.body) cleaned_body = remove_quote_blocks(comment.body)
formatted_entry = get_ai_format(cleaned_body)
# --- 新逻辑:判断用户是否自带了 Header ---
# 匹配以 #### 开头的行
header_match = re.search(r'^####\s+.*', cleaned_body, re.MULTILINE)
# 准备修改 README.md if header_match:
# 1. 提取用户自己写的 Header
header_line = header_match.group(0).strip()
# 2. 从正文中移除这一行,避免干扰 AI
body_for_ai = cleaned_body.replace(header_line, "").strip()
print(f"检测到用户自带 Header: {header_line}")
else:
# 1. 自动生成 Header
author_name = comment.user.login
author_url = comment.user.html_url
header_line = f"#### {author_name} - [Github]({author_url})"
body_for_ai = cleaned_body
print(f"自动生成 Header: {header_line}")
# 3. AI 仅处理项目详情行
project_line = get_ai_project_line(body_for_ai)
# 组合成最终条目
formatted_entry = f"{header_line}\n{project_line}"
# 4. 更新 README.md 逻辑
content = repo.get_contents("README.md", ref="master") content = repo.get_contents("README.md", ref="master")
readme_text = content.decoded_content.decode("utf-8") readme_text = content.decoded_content.decode("utf-8")
# 插入日期逻辑
today_str = datetime.now().strftime("%Y 年 %m 月 %d 号添加") today_str = datetime.now().strftime("%Y 年 %m 月 %d 号添加")
date_header = f"### {today_str}" date_header = f"### {today_str}"
if date_header not in readme_text: if date_header not in readme_text:
# 在 "3. 项目列表" 下方插入新日期
new_readme = readme_text.replace("3. 项目列表\n", f"3. 项目列表\n\n{date_header}\n") new_readme = readme_text.replace("3. 项目列表\n", f"3. 项目列表\n\n{date_header}\n")
else: else:
new_readme = readme_text new_readme = readme_text
# 在日期标题下插入新条目
insertion_point = new_readme.find(date_header) + len(date_header) insertion_point = new_readme.find(date_header) + len(date_header)
final_readme = new_readme[:insertion_point] + "\n\n" + formatted_entry + new_readme[insertion_point:] final_readme = new_readme[:insertion_point] + "\n\n" + formatted_entry + new_readme[insertion_point:]
# 创建新分支并提交 PR # 5. 提交 PR 逻辑
branch_name = f"add-project-{comment.id}" branch_name = f"add-project-{comment.id}"
base = repo.get_branch("master") base = repo.get_branch("master")
# 检查分支是否已存在,如果存在则删除
try: try:
existing_ref = repo.get_git_ref(f"heads/{branch_name}") repo.get_git_ref(f"heads/{branch_name}").delete()
existing_ref.delete()
print(f"已删除现有分支: {branch_name}")
except: except:
pass # 分支不存在,继续 pass
repo.create_git_ref(ref=f"refs/heads/{branch_name}", sha=base.commit.sha) repo.create_git_ref(ref=f"refs/heads/{branch_name}", sha=base.commit.sha)
repo.update_file( repo.update_file(
"README.md", "README.md",
f"docs: add new project from comment {comment.id}", f"docs: add project from {comment.user.login}",
final_readme, final_readme,
content.sha, content.sha,
branch=branch_name branch=branch_name
) )
# 为了彻底消除 Issue 里的 "mentioned this" 红框,
# 在 https:// 后面插入一个不可见字符 \u200b
safe_url = comment.html_url.replace("https://", "https://\u200b")
pr = repo.create_pull( pr = repo.create_pull(
title=f"新增项目:来自评论 {comment.id}", title=f"新增项目:来自 {comment.user.login} 的评论",
body=f"{comment.body}\n\n---\n原始评论:`{comment.html_url}`", body=f"由管理员标记并自动提取。\n\n原始评论:{safe_url}",
head=branch_name, head=branch_name,
base="master" base="master"
) )
# 用表情标记为成功,并回复
comment.create_reaction(SUCCESS_EMOJI) comment.create_reaction(SUCCESS_EMOJI)
# comment.create_comment(f"感谢提交,已添加!\n\nPR 链接:{pr.html_url}") comment.create_comment(f"感谢提交,已添加!\n\nPR 链接:{pr.html_url}")
processed_count += 1 processed_count += 1
print(f"评论 {comment.id} 处理成功,已创建 PR。")
if processed_count == 0: if processed_count == 0:
print("没有发现需要处理的新评论") print("未发现新标记的任务")
if __name__ == "__main__": if __name__ == "__main__":
main() main()