mirror of
https://github.com/1c7/chinese-independent-developer.git
synced 2025-12-27 18:35:57 +08:00
x
This commit is contained in:
28
.github/MAINTAINER.md
vendored
Normal file
28
.github/MAINTAINER.md
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
## 介绍 `.github/` 文件夹的用途
|
||||||
|
|
||||||
|
## 概括
|
||||||
|
用户在 https://github.com/1c7/chinese-independent-developer/issues/160 提交评论。
|
||||||
|
大部分情况下,格式是不符合规范的(可以理解)
|
||||||
|
需要用程序自动化处理,减少我的时间投入。
|
||||||
|
|
||||||
|
## 流程
|
||||||
|
1. 我(1c7)在用户提交的评论点击 🚀 图标(表情)
|
||||||
|
1. 触发 Github Action 执行(手动触发 或 定时执行(每 6 小时)
|
||||||
|
1. Github Action 会触发 .github/scripts/process_item.py
|
||||||
|
2. 查找 "当前日期-3天" 开始(这个时间点往后) 所有标记 🚀 图标 的评论
|
||||||
|
3. 处理格式,创建 Pull Request。
|
||||||
|
4. 给评论新增一个 🎉 图标(意思是"处理完成")
|
||||||
|
7. 回复这条评论:感谢提交,已添加。
|
||||||
|
|
||||||
|
我只需要修改 PR 然后 merge 就行。
|
||||||
|
|
||||||
|
一句话概括:我点击 🚀 标签,然后 PR 会自动创建,我只需要 merge PR。我大概点击 3 次左右就可以了(如果介绍语有改进空间,我还得改一下文字,然后才 merge)
|
||||||
|
|
||||||
|
## 本地运行(为了开发调试)
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
|
||||||
|
uv sync
|
||||||
|
|
||||||
|
uv run .github/scripts/process_item.py
|
||||||
|
```
|
||||||
80
.github/scripts/process_item.py
vendored
80
.github/scripts/process_item.py
vendored
@@ -57,7 +57,9 @@ def main():
|
|||||||
time_threshold = datetime.now(timezone.utc) - timedelta(days=3)
|
time_threshold = datetime.now(timezone.utc) - timedelta(days=3)
|
||||||
comments = issue.get_comments(since=time_threshold)
|
comments = issue.get_comments(since=time_threshold)
|
||||||
|
|
||||||
processed_count = 0
|
# ===== 阶段 1:收集待处理评论 =====
|
||||||
|
pending_comments = []
|
||||||
|
formatted_entries = []
|
||||||
|
|
||||||
for comment in comments:
|
for comment in comments:
|
||||||
reactions = comment.get_reactions()
|
reactions = comment.get_reactions()
|
||||||
@@ -72,31 +74,35 @@ def main():
|
|||||||
|
|
||||||
cleaned_body = remove_quote_blocks(comment.body)
|
cleaned_body = remove_quote_blocks(comment.body)
|
||||||
|
|
||||||
# --- 新逻辑:判断用户是否自带了 Header ---
|
# 判断用户是否自带了 Header
|
||||||
# 匹配以 #### 开头的行
|
|
||||||
header_match = re.search(r'^####\s+.*', cleaned_body, re.MULTILINE)
|
header_match = re.search(r'^####\s+.*', cleaned_body, re.MULTILINE)
|
||||||
|
|
||||||
if header_match:
|
if header_match:
|
||||||
# 1. 提取用户自己写的 Header
|
|
||||||
header_line = header_match.group(0).strip()
|
header_line = header_match.group(0).strip()
|
||||||
# 2. 从正文中移除这一行,避免干扰 AI
|
|
||||||
body_for_ai = cleaned_body.replace(header_line, "").strip()
|
body_for_ai = cleaned_body.replace(header_line, "").strip()
|
||||||
print(f"检测到用户自带 Header: {header_line}")
|
print(f"检测到用户自带 Header: {header_line}")
|
||||||
else:
|
else:
|
||||||
# 1. 自动生成 Header
|
|
||||||
author_name = comment.user.login
|
author_name = comment.user.login
|
||||||
author_url = comment.user.html_url
|
author_url = comment.user.html_url
|
||||||
header_line = f"#### {author_name} - [Github]({author_url})"
|
header_line = f"#### {author_name} - [Github]({author_url})"
|
||||||
body_for_ai = cleaned_body
|
body_for_ai = cleaned_body
|
||||||
print(f"自动生成 Header: {header_line}")
|
print(f"自动生成 Header: {header_line}")
|
||||||
|
|
||||||
# 3. AI 仅处理项目详情行
|
# AI 处理项目详情行
|
||||||
project_line = get_ai_project_line(body_for_ai)
|
project_line = get_ai_project_line(body_for_ai)
|
||||||
|
|
||||||
# 组合成最终条目
|
|
||||||
formatted_entry = f"{header_line}\n{project_line}"
|
formatted_entry = f"{header_line}\n{project_line}"
|
||||||
|
|
||||||
# 4. 更新 README.md 逻辑
|
pending_comments.append(comment)
|
||||||
|
formatted_entries.append(formatted_entry)
|
||||||
|
|
||||||
|
# ===== 阶段 2:批量提交 =====
|
||||||
|
if not pending_comments:
|
||||||
|
print("无待处理评论")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"\n共收集 {len(pending_comments)} 个待处理评论")
|
||||||
|
|
||||||
|
# 更新 README
|
||||||
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")
|
||||||
|
|
||||||
@@ -108,11 +114,13 @@ def main():
|
|||||||
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:]
|
all_entries = "\n\n".join(formatted_entries)
|
||||||
|
final_readme = new_readme[:insertion_point] + "\n\n" + all_entries + new_readme[insertion_point:]
|
||||||
|
|
||||||
# 5. 提交 PR 逻辑
|
# 创建分支
|
||||||
branch_name = f"add-project-{comment.id}"
|
branch_name = f"batch-add-projects-{datetime.now().strftime('%Y%m%d-%H%M%S')}"
|
||||||
base = repo.get_branch("master")
|
base = repo.get_branch("master")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -123,33 +131,51 @@ def main():
|
|||||||
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 project from {comment.user.login}",
|
f"docs: batch add {len(pending_comments)} projects",
|
||||||
final_readme,
|
final_readme,
|
||||||
content.sha,
|
content.sha,
|
||||||
branch=branch_name
|
branch=branch_name
|
||||||
)
|
)
|
||||||
|
|
||||||
# 为了彻底消除 Issue 里的 "mentioned this" 红框,
|
# 构建 PR body
|
||||||
# 在 https:// 后面插入一个不可见字符 \u200b
|
comment_links = "\n".join([
|
||||||
safe_url = comment.html_url.replace("https://", "https://\u200b")
|
f"- [{c.user.login}]({c.html_url})"
|
||||||
|
for c in pending_comments
|
||||||
|
])
|
||||||
|
|
||||||
|
formatted_list = "\n\n".join([
|
||||||
|
f"### {i+1}. {formatted_entries[i]}"
|
||||||
|
for i in range(len(formatted_entries))
|
||||||
|
])
|
||||||
|
|
||||||
|
pr_body = f"""批量添加 {len(pending_comments)} 个项目
|
||||||
|
|
||||||
|
## 原始评论链接
|
||||||
|
{comment_links}
|
||||||
|
|
||||||
|
## 格式化结果
|
||||||
|
{formatted_list}
|
||||||
|
|
||||||
|
---
|
||||||
|
自动生成,触发机制:用户 {ADMIN_HANDLE} 点击 🚀
|
||||||
|
"""
|
||||||
|
|
||||||
pr = repo.create_pull(
|
pr = repo.create_pull(
|
||||||
title=f"新增项目:来自 {comment.user.login} 的评论",
|
title=f"新增项目:批量添加 {len(pending_comments)} 个项目",
|
||||||
body=f"原评论内容:```{comment.body}``` \n\n 原评论链接:{safe_url} \n\n --- \n\n 此 PR 自动生成,触发机制:Github 用户 1c7 在评论下方点击了'火箭'图标。",
|
body=pr_body,
|
||||||
head=branch_name,
|
head=branch_name,
|
||||||
base="master"
|
base="master"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
print(f"\n✅ PR 创建成功:{pr.html_url}")
|
||||||
|
|
||||||
|
# 标记所有评论
|
||||||
|
for comment in pending_comments:
|
||||||
comment.create_reaction(SUCCESS_EMOJI)
|
comment.create_reaction(SUCCESS_EMOJI)
|
||||||
|
reply_body = f"@{comment.user.login} 感谢提交,已添加至待审核列表!\n\nPR 链接:{pr.html_url}"
|
||||||
|
issue.create_comment(reply_body)
|
||||||
|
|
||||||
# 构建包含引用的回复评论
|
print(f"\n✅ 已标记所有 {len(pending_comments)} 个评论")
|
||||||
# reply_body = f"@{comment.user.login} 感谢提交,已添加至待审核列表!\n\nPR 链接:{pr.html_url}\n\n---\n*回复 [此评论]({comment.html_url})*"
|
|
||||||
# issue.create_comment(reply_body)
|
|
||||||
|
|
||||||
processed_count += 1
|
|
||||||
|
|
||||||
if processed_count == 0:
|
|
||||||
print("未发现新标记的任务。")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
4
.github/workflows/process_list.yml
vendored
4
.github/workflows/process_list.yml
vendored
@@ -1,7 +1,7 @@
|
|||||||
name: 提交项目
|
name: 提交项目
|
||||||
on:
|
on:
|
||||||
# schedule:
|
schedule:
|
||||||
# - cron: '0 */6 * * *' # 每 6 小时运行一次
|
- cron: '0 16 * * *' # 每天 UTC 16:00 运行(北京时间 00:00)
|
||||||
workflow_dispatch: # 支持手动触发
|
workflow_dispatch: # 支持手动触发
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
Reference in New Issue
Block a user