返回 DeepSeek-Reasonix
spam-comment-guard.yml
根目录 / .github / workflows / spam-comment-guard.yml
1 name: Spam comment guard
2
3 # Activity-farming bots post short emoji-padded template comments on whatever
4 # issue is currently active. They are cheap to spot structurally: a recently
5 # registered account with no history here, no followers, and a pile of forked
6 # repos, posting a sub-50 character comment with emoji and no code/link/log.
7 # Every signal must fire — on 7604 replayed comments that caught all 83 known
8 # spam posts with no false positive. Loosening any one of them reintroduces
9 # real users ("点赞", "同样的问题", a 2020 account posting "感谢各位❤").
10
11 on:
12 issue_comment:
13 types: [created]
14
15 permissions:
16 issues: write
17 pull-requests: write
18
19 concurrency:
20 group: spam-guard-${{ github.event.comment.id }}
21
22 jobs:
23 screen:
24 if: github.event.comment.user.type != 'Bot' && github.event.comment.author_association == 'NONE'
25 runs-on: ubuntu-latest
26 steps:
27 - uses: actions/github-script@v9
28 with:
29 script: |
30 const EMOJI = /[\u{1F300}-\u{1FAFF}\u{2600}-\u{27BF}\u{2B00}-\u{2BFF}\u{FE0F}]/gu;
31 const comment = context.payload.comment;
32 const body = comment.body || '';
33
34 const hasSubstance = /```|https?:\/\/|!\[|^>/m.test(body);
35 const emojiCount = (body.match(EMOJI) || []).length;
36 const bare = body.replace(EMOJI, '').trim();
37
38 const { data: author } = await github.rest.users.getByUsername({
39 username: comment.user.login,
40 });
41
42 const ageDays = (Date.now() - Date.parse(author.created_at)) / 86400000;
43
44 const signals = {
45 newAccount: ageDays < 365,
46 noFollowers: author.followers === 0,
47 forkPadded: author.public_repos >= 15,
48 tooShort: bare.length <= 45,
49 emojiPadded: emojiCount >= 1,
50 noSubstance: !hasSubstance,
51 };
52 const failed = Object.entries(signals).filter(([, v]) => !v).map(([k]) => k);
53 core.info(`${comment.user.login}: ${failed.length ? `kept (${failed.join(',')})` : 'spam'}`);
54 if (failed.length) return;
55
56 await github.graphql(
57 `mutation($id: ID!) {
58 minimizeComment(input: { subjectId: $id, classifier: SPAM }) {
59 minimizedComment { isMinimized }
60 }
61 }`,
62 { id: comment.node_id },
63 );
64 core.notice(`Minimized spam comment by ${comment.user.login}`);
65
65 lines YAML