ci: detect abusive issue content

This commit is contained in:
t8y2 2026-06-03 23:05:45 +08:00
parent 87efa2b06c
commit 0e66b5d128
1 changed files with 130 additions and 0 deletions

View File

@ -0,0 +1,130 @@
name: Detect abusive issue content
# 这段 workflow 只用于检测并处理极少数恶意诽谤型 Issue 和评论。
# 我们不希望仓库的 issue 区变成争吵、造谣或情绪宣泄的地方,也不希望真正来反馈问题、
# 提交建议、讨论兼容性的用户被这些内容打扰。
#
# 关于“刷星”“刷 Star”这类指控这里也留一段诚恳的说明给维护者和以后回看配置的人看
# DBX 的 Star 和关注度不是一天突然冒出来的,也不是靠任何灰色手段堆出来的。这个项目是一点点写、
# 一点点修、一个问题一个问题回复、一个版本一个版本发布走到现在的。过程中确实有一些外部来源带来了
# 可见增长,比如用户在社群里的推荐、技术博主的介绍、开源资讯站点的收录、不同平台上的自然传播,
# 以及使用者觉得有帮助后顺手点的 Star。这些增长并不总是平均发生的有时某个平台推荐一次
# 某篇文章或视频传播一次,短时间内就会带来一波新增关注;这在开源项目里是很正常的。
# 我们也真心感谢每一位认真使用、反馈问题、提出建议、写文章、录视频、在社群里推荐或只是默默点 Star
# 的朋友。正是这些具体而真实的支持,让项目有动力继续往前走。
#
# 我们理解外界可以有疑问,也欢迎基于事实的讨论。但把没有证据的“刷星”“刷 Star”反复发到 issue 里,
# 对排查问题、改进软件、维护社区氛围都没有帮助。对于这种明显不是技术反馈、也不提供事实依据的内容,
# 这里选择自动删除,而不是公开争辩。这样做不是为了回避监督,而是为了保护正常用户的讨论空间,
# 也避免让恶意内容通过 issue 区获得更多曝光。
#
# 如果将来确实有人提出具体、可核验、善意的问题,维护者仍然可以正常回应;这个 workflow 只匹配非常窄的
# 关键词范围“刷星”以及大小写不敏感的“刷star”。同样的规则也适用于别人 Issue 下面的评论,
# 避免正常的问题讨论被无关攻击打断。
#
# This workflow exists only for a small number of abusive or defamatory issues.
# We do not want the issue tracker to become a place for rumors, arguments, or repeated bad-faith accusations.
# DBX did not appear out of nowhere, and its stars were not manufactured through any gray-market shortcut.
# The project has grown step by step: by writing code, fixing bugs, answering questions, shipping releases,
# and listening to people who actually use it. Some growth also came from natural external exposure:
# community recommendations, blog posts, open-source newsletters, social platforms, videos, and users who found
# the project useful enough to star it. Open-source attention is rarely linear; a single recommendation or post
# can bring a visible wave of new users, and that is normal.
# We are genuinely grateful to everyone who uses DBX seriously, reports bugs, suggests improvements, writes posts,
# records videos, recommends it in communities, or simply leaves a star because the project helped them. That real,
# concrete support is what keeps the project moving forward.
#
# Honest questions and evidence-based discussion are welcome. Repeated claims such as "刷星" or "刷star" without
# evidence are not useful technical feedback, and they make the issue tracker worse for everyone who is here to
# report bugs or improve the software. For those narrow cases, we choose to delete the issue or comment quietly instead
# of amplifying it through public arguments. The same narrow rule also applies to comments under other people's issues,
# so normal technical discussions are not derailed by unrelated accusations.
on:
issues:
types: [opened]
issue_comment:
types: [created, edited]
permissions:
issues: write
jobs:
delete-issue:
runs-on: ubuntu-latest
if: github.event_name == 'issues'
steps:
- name: Check issue keywords
id: check
env:
EVENT_PATH: ${{ github.event_path }}
run: |
python3 - <<'PYEOF'
import json
import os
import re
with open(os.environ["EVENT_PATH"], encoding="utf-8") as f:
event = json.load(f)
issue = event["issue"]
text = "\n".join([
issue.get("title") or "",
issue.get("body") or "",
])
# Keep this intentionally narrow. It only matches "刷星" and
# case-insensitive variants of "刷star", including optional spaces.
matched = re.search(r"刷\s*(?:星|star)", text, re.IGNORECASE) is not None
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as f:
f.write(f"matched={'true' if matched else 'false'}\n")
f.write(f"issue_number={issue['number']}\n")
PYEOF
- name: Delete abusive issue
if: steps.check.outputs.matched == 'true'
env:
GH_TOKEN: ${{ secrets.ISSUE_DELETE_TOKEN || github.token }}
ISSUE_NUMBER: ${{ steps.check.outputs.issue_number }}
# Deleting issues may require an admin-scoped token. If github.token is
# not enough in this repository, set ISSUE_DELETE_TOKEN in repo secrets.
run: gh issue delete "$ISSUE_NUMBER" --yes --repo "$GITHUB_REPOSITORY"
delete-comment:
runs-on: ubuntu-latest
if: github.event_name == 'issue_comment'
steps:
- name: Check comment keywords
id: check
env:
EVENT_PATH: ${{ github.event_path }}
run: |
python3 - <<'PYEOF'
import json
import os
import re
with open(os.environ["EVENT_PATH"], encoding="utf-8") as f:
event = json.load(f)
comment = event["comment"]
text = comment.get("body") or ""
# Keep this intentionally narrow. It only matches "刷星" and
# case-insensitive variants of "刷star", including optional spaces.
matched = re.search(r"刷\s*(?:星|star)", text, re.IGNORECASE) is not None
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as f:
f.write(f"matched={'true' if matched else 'false'}\n")
f.write(f"comment_id={comment['id']}\n")
PYEOF
- name: Delete abusive comment
if: steps.check.outputs.matched == 'true'
env:
GH_TOKEN: ${{ secrets.ISSUE_DELETE_TOKEN || github.token }}
COMMENT_ID: ${{ steps.check.outputs.comment_id }}
# Deleting comments may require an admin-scoped token. If github.token is
# not enough in this repository, set ISSUE_DELETE_TOKEN in repo secrets.
run: gh api --method DELETE "repos/$GITHUB_REPOSITORY/issues/comments/$COMMENT_ID"