From ffcf7ee77638f1259c20968f7a8a48251115d446 Mon Sep 17 00:00:00 2001 From: wayne liu <43563618+wayneliu0019@users.noreply.github.com> Date: Fri, 8 May 2026 18:35:57 +0800 Subject: [PATCH 1/3] add moderation for issue and comments --- .github/scripts/valid_check.py | 109 ++++++++++++++++++++++++++++++ .github/workflows/valid_check.yml | 40 +++++++++++ 2 files changed, 149 insertions(+) create mode 100644 .github/scripts/valid_check.py create mode 100644 .github/workflows/valid_check.yml diff --git a/.github/scripts/valid_check.py b/.github/scripts/valid_check.py new file mode 100644 index 000000000..8741f948c --- /dev/null +++ b/.github/scripts/valid_check.py @@ -0,0 +1,109 @@ +import os +import requests +from openai import OpenAI + +def check_violation(content): + """调用大模型判断内容进行合法性判断""" + + client = OpenAI( + api_key=os.environ.get("LLM_API_KEY"), + base_url="https://api.deepseek.com" # 或替换为智谱 GLM 等其他 API + ) + + prompt = f""" + 你是一个 GitHub 开源仓库管理员助手。请判断以下内容是否包含以下三种情况中的任意一种: + 1. 质疑、抱怨或讨论该项目的 Star 数量(例如:指责刷 Star、买 Star、造假、名不副实等)。 + 2. 辱骂、人身攻击、粗俗或不文明的语言。 + 3. 毁谤、恶意抹黑项目或开发者。 + + 待检测内容: + {content} + + 请严格按照以下格式输出: + 如果包含上述任何一种情况,请仅输出 "YES"; + 如果是正常的技术交流、Bug 反馈或功能建议,请仅输出 "NO"。 + 不要输出任何其他多余的字符。 + """ + + try: + response = client.chat.completions.create( + model="deepseek-chat", + messages=[{"role": "user", "content": prompt}], + temperature=0.1 + ) + result = response.choices[0].message.content.strip().upper() + return "YES" in result + except Exception as e: + print(f"大模型调用失败: {e}") + return False + +def add_comment(repo, issue_number, token, message): + """向指定的 Issue 添加回复""" + url = f"https://api.github.com/repos/{repo}/issues/{issue_number}/comments" + headers = { + "Authorization": f"Bearer {token}", + "Accept": "application/vnd.github.v3+json", + "X-GitHub-Api-Version": "2022-11-28" + } + requests.post(url, headers=headers, json={"body": message}) + print("已成功发送礼貌回复。") + +def close_issue(repo, issue_number, token): + """关闭 Issue""" + url = f"https://api.github.com/repos/{repo}/issues/{issue_number}" + headers = { + "Authorization": f"Bearer {token}", + "Accept": "application/vnd.github.v3+json" + } + requests.patch(url, headers=headers, json={"state": "closed", "state_reason": "not_planned"}) + print(f"Issue #{issue_number} 已关闭。") + +def delete_comment(repo, comment_id, token): + """删除指定的 Comment""" + url = f"https://api.github.com/repos/{repo}/issues/comments/{comment_id}" + headers = { + "Authorization": f"Bearer {token}", + "Accept": "application/vnd.github.v3+json" + } + requests.delete(url, headers=headers) + print(f"Comment {comment_id} 已删除。") + +if __name__ == "__main__": + event_name = os.environ.get("GITHUB_EVENT_NAME") + repo = os.environ.get("GITHUB_REPOSITORY") + gh_token = os.environ.get("GITHUB_TOKEN") + issue_number = os.environ.get("ISSUE_NUMBER") + + if not all([event_name, repo, gh_token, issue_number]): + print("核心环境变量缺失,退出执行。") + exit(1) + + print(f"触发事件类型: {event_name}") + + if event_name == "issues": + # 处理新建 Issue + title = os.environ.get("ISSUE_TITLE", "") + body = os.environ.get("ISSUE_BODY", "") + content_to_check = f"标题: {title}\n内容: {body}" + + if check_violation(content_to_check): + print("判定结果:Issue 违规。执行回复并关闭操作。") + reply_msg = "您好,感谢您的关注。本项目欢迎对代码、架构和技术本身进行深入探讨。但由于您的 Issue 涉及与技术无关的争议内容(如辱骂、不当言辞等),为保持开源社区的专业和整洁,该 Issue 将予以自动关闭。感谢理解。" + add_comment(repo, issue_number, gh_token, reply_msg) + close_issue(repo, issue_number, gh_token) + else: + print("判定结果:正常 Issue,放行。") + + elif event_name == "issue_comment": + # 处理新增 Comment + comment_id = os.environ.get("COMMENT_ID") + comment_body = os.environ.get("COMMENT_BODY", "") + content_to_check = f"评论内容: {comment_body}" + + if check_violation(content_to_check): + print("判定结果:Comment 违规。执行回复并删除评论操作。") + reply_msg = "您好,感谢您的关注。由于您刚刚发布的评论涉及与技术探讨无关的争议内容(如辱骂、不当言辞等),为保持社区环境的专业和整洁,系统已自动将其清理。希望大家聚焦技术交流,感谢理解。" + add_comment(repo, issue_number, gh_token, reply_msg) + delete_comment(repo, comment_id, gh_token) + else: + print("判定结果:正常 Comment,放行。") diff --git a/.github/workflows/valid_check.yml b/.github/workflows/valid_check.yml new file mode 100644 index 000000000..da7888e42 --- /dev/null +++ b/.github/workflows/valid_check.yml @@ -0,0 +1,40 @@ +name: Auto Moderation for Issues and Comments + +on: + issues: + types: [opened] + issue_comment: + types: [created] + +jobs: + moderate_content: + runs-on: ubuntu-latest + permissions: + issues: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.10' + + - name: Install dependencies + run: pip install requests openai + + - name: Run LLM Content Moderator + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + LLM_API_KEY: ${{ secrets.LLM_API_KEY }} + GITHUB_EVENT_NAME: ${{ github.event_name }} + GITHUB_REPOSITORY: ${{ github.repository }} + # 针对 Issue 的变量 + ISSUE_NUMBER: ${{ github.event.issue.number }} + ISSUE_TITLE: ${{ github.event.issue.title || '' }} + ISSUE_BODY: ${{ github.event.issue.body || '' }} + # 针对 Comment 的变量 + COMMENT_ID: ${{ github.event.comment.id || '' }} + COMMENT_BODY: ${{ github.event.comment.body || '' }} + run: python .github/scripts/valid_check.py From da2d9eacadbb5f4628c862377814eda652ee2479 Mon Sep 17 00:00:00 2001 From: wayne liu <43563618+wayneliu0019@users.noreply.github.com> Date: Fri, 8 May 2026 19:05:39 +0800 Subject: [PATCH 2/3] switch to English comments --- .github/scripts/valid_check.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/scripts/valid_check.py b/.github/scripts/valid_check.py index 8741f948c..6e1f1736f 100644 --- a/.github/scripts/valid_check.py +++ b/.github/scripts/valid_check.py @@ -3,11 +3,11 @@ from openai import OpenAI def check_violation(content): - """调用大模型判断内容进行合法性判断""" + """Call LLM to judge the content for legality.""" client = OpenAI( api_key=os.environ.get("LLM_API_KEY"), - base_url="https://api.deepseek.com" # 或替换为智谱 GLM 等其他 API + base_url="https://api.deepseek.com" # GLM , MiniMax or other LLM API ) prompt = f""" @@ -38,7 +38,7 @@ def check_violation(content): return False def add_comment(repo, issue_number, token, message): - """向指定的 Issue 添加回复""" + """add comment to specific Issue""" url = f"https://api.github.com/repos/{repo}/issues/{issue_number}/comments" headers = { "Authorization": f"Bearer {token}", @@ -49,7 +49,7 @@ def add_comment(repo, issue_number, token, message): print("已成功发送礼貌回复。") def close_issue(repo, issue_number, token): - """关闭 Issue""" + ""close Issue""" url = f"https://api.github.com/repos/{repo}/issues/{issue_number}" headers = { "Authorization": f"Bearer {token}", @@ -59,7 +59,7 @@ def close_issue(repo, issue_number, token): print(f"Issue #{issue_number} 已关闭。") def delete_comment(repo, comment_id, token): - """删除指定的 Comment""" + """Delete Comment""" url = f"https://api.github.com/repos/{repo}/issues/comments/{comment_id}" headers = { "Authorization": f"Bearer {token}", @@ -81,7 +81,7 @@ def delete_comment(repo, comment_id, token): print(f"触发事件类型: {event_name}") if event_name == "issues": - # 处理新建 Issue + # for new Issue title = os.environ.get("ISSUE_TITLE", "") body = os.environ.get("ISSUE_BODY", "") content_to_check = f"标题: {title}\n内容: {body}" @@ -95,7 +95,7 @@ def delete_comment(repo, comment_id, token): print("判定结果:正常 Issue,放行。") elif event_name == "issue_comment": - # 处理新增 Comment + # for new Comment comment_id = os.environ.get("COMMENT_ID") comment_body = os.environ.get("COMMENT_BODY", "") content_to_check = f"评论内容: {comment_body}" From 3c1165f1a6ccb1b2281c294a412341dc230b23fd Mon Sep 17 00:00:00 2001 From: wayne liu <43563618+wayneliu0019@users.noreply.github.com> Date: Fri, 8 May 2026 20:58:34 +0800 Subject: [PATCH 3/3] support english and chinese comments --- .github/scripts/valid_check.py | 47 +++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/.github/scripts/valid_check.py b/.github/scripts/valid_check.py index 6e1f1736f..038f057ec 100644 --- a/.github/scripts/valid_check.py +++ b/.github/scripts/valid_check.py @@ -1,13 +1,19 @@ import os +import re import requests from openai import OpenAI +def is_chinese(text): + """Determine if the text contains Chinese characters""" + # 匹配基本汉字范围 + return bool(re.search(r'[\u4e00-\u9fff]', text)) + def check_violation(content): - """Call LLM to judge the content for legality.""" + """The LLM is used to determine whether the content involves insults, or defamation.""" client = OpenAI( api_key=os.environ.get("LLM_API_KEY"), - base_url="https://api.deepseek.com" # GLM , MiniMax or other LLM API + base_url="https://api.deepseek.com" # 或替换为智谱 GLM 等其他 API ) prompt = f""" @@ -38,7 +44,7 @@ def check_violation(content): return False def add_comment(repo, issue_number, token, message): - """add comment to specific Issue""" + """add comments to specific Issue""" url = f"https://api.github.com/repos/{repo}/issues/{issue_number}/comments" headers = { "Authorization": f"Bearer {token}", @@ -46,10 +52,10 @@ def add_comment(repo, issue_number, token, message): "X-GitHub-Api-Version": "2022-11-28" } requests.post(url, headers=headers, json={"body": message}) - print("已成功发送礼貌回复。") + print("已成功发送回复。") def close_issue(repo, issue_number, token): - ""close Issue""" + """close Issue""" url = f"https://api.github.com/repos/{repo}/issues/{issue_number}" headers = { "Authorization": f"Bearer {token}", @@ -59,7 +65,7 @@ def close_issue(repo, issue_number, token): print(f"Issue #{issue_number} 已关闭。") def delete_comment(repo, comment_id, token): - """Delete Comment""" + """delete Comment""" url = f"https://api.github.com/repos/{repo}/issues/comments/{comment_id}" headers = { "Authorization": f"Bearer {token}", @@ -81,28 +87,39 @@ def delete_comment(repo, comment_id, token): print(f"触发事件类型: {event_name}") if event_name == "issues": - # for new Issue + # handle new Issue title = os.environ.get("ISSUE_TITLE", "") body = os.environ.get("ISSUE_BODY", "") - content_to_check = f"标题: {title}\n内容: {body}" + content_to_check = f"{title} {body}" if check_violation(content_to_check): - print("判定结果:Issue 违规。执行回复并关闭操作。") - reply_msg = "您好,感谢您的关注。本项目欢迎对代码、架构和技术本身进行深入探讨。但由于您的 Issue 涉及与技术无关的争议内容(如辱骂、不当言辞等),为保持开源社区的专业和整洁,该 Issue 将予以自动关闭。感谢理解。" + print("判定结果:Issue 违规。准备执行回复并关闭操作。") + + # Determine the language and select a reply template. + if is_chinese(content_to_check): + reply_msg = "您好,感谢您的关注。本项目欢迎对代码、架构和技术本身进行深入探讨。但由于您的 Issue 涉及与技术无关的争议内容(如辱骂、不当言辞等),为保持开源社区的专业和整洁,该 Issue 将予以自动关闭。感谢理解。" + else: + reply_msg = "Hello, thank you for your interest. We welcome in-depth discussions on code, architecture, and technology. However, since your issue involves non-technical controversial content (such as inappropriate language, etc.), it will be automatically closed to maintain a professional and clean open-source community. Thank you for your understanding." + add_comment(repo, issue_number, gh_token, reply_msg) close_issue(repo, issue_number, gh_token) else: print("判定结果:正常 Issue,放行。") elif event_name == "issue_comment": - # for new Comment + # handle new Comment comment_id = os.environ.get("COMMENT_ID") comment_body = os.environ.get("COMMENT_BODY", "") - content_to_check = f"评论内容: {comment_body}" - if check_violation(content_to_check): - print("判定结果:Comment 违规。执行回复并删除评论操作。") - reply_msg = "您好,感谢您的关注。由于您刚刚发布的评论涉及与技术探讨无关的争议内容(如辱骂、不当言辞等),为保持社区环境的专业和整洁,系统已自动将其清理。希望大家聚焦技术交流,感谢理解。" + if check_violation(comment_body): + print("判定结果:Comment 违规。准备执行回复并删除评论操作。") + + # 判断语言并选择回复模板 + if is_chinese(comment_body): + reply_msg = "您好,感谢您的关注。由于您刚刚发布的评论涉及与技术探讨无关的争议内容(如辱骂、不当言辞等),为保持社区环境的专业和整洁,系统已自动将其清理。希望大家聚焦技术交流,感谢理解。" + else: + reply_msg = "Hello, thank you for your interest. Because your recent comment involves non-technical controversial content (such as inappropriate language, etc.), it has been automatically removed to maintain a professional and clean community environment. We hope everyone can focus on technical exchanges. Thank you for your understanding." + add_comment(repo, issue_number, gh_token, reply_msg) delete_comment(repo, comment_id, gh_token) else: