# Fix: Update comment moderation logic Inspired by #38450 to help fix/complete the moderation script, this updates the moderation script to: - Add language detection for non-English comments - Implement profanity filtering - Check for off-topic content - Improve forbidden link detection - Add owner exemption logic - Enhance error handling and logging - Add a message indicating why the comment was deleted. *To configure the moderation lists:* - Go to repository Settings > Secrets > Actions - Add `MODERATION_PROFANITY` secret containing a JSON array of terms - Add `MODERATION_OFFTOPIC` secret containing a JSON array of phrases - Example format for each: `["term1","term2","term3"]` Resources for priming the PROFANITY and OFFTOPIC lists: - https://www.cs.cmu.edu/~biglou/resources/ (first link) - https://github.com/OOPSpam/spam-words/blob/main/spam-words-EN.txt Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
76 lines
2.7 KiB
YAML
76 lines
2.7 KiB
YAML
# Github action to experiment automatic moderation
|
|
name: Moderation Bot
|
|
|
|
on:
|
|
issue_comment:
|
|
types: [created, edited]
|
|
pull_request_review_comment:
|
|
types: [created, edited]
|
|
|
|
permissions:
|
|
issues: write
|
|
pull-requests: write
|
|
|
|
jobs:
|
|
moderate:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Install franc
|
|
run: npm install franc
|
|
|
|
- name: Moderate comments
|
|
uses: actions/github-script@v9
|
|
with:
|
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
script: |
|
|
const forbiddenPatterns = [
|
|
'music.youtube.com',
|
|
'youtu.be',
|
|
'youtube.com/watch'
|
|
]
|
|
|
|
const profanityList = JSON.parse(process.env.PROFANITY_LIST || '[]')
|
|
const offTopicKeywords = JSON.parse(process.env.OFFTOPIC_LIST || '[]')
|
|
|
|
const comment = context.payload.comment.body || ''
|
|
const commentAuthor = context.payload.comment.user.login
|
|
const repoOwner = context.repo.owner
|
|
const isOwner = commentAuthor === repoOwner
|
|
|
|
const isForbidden = forbiddenPatterns.some(p => comment.toLowerCase().includes(p))
|
|
const isProfane = profanityList.some(word => new RegExp(`\\b${word}\\b`, 'i').test(comment))
|
|
const isOffTopic = offTopicKeywords.some(kw => comment.toLowerCase().includes(kw.toLowerCase()))
|
|
|
|
let isEnglish = true
|
|
try {
|
|
const franc = require('franc')
|
|
const lang = franc(comment)
|
|
isEnglish = lang && lang.startsWith('eng')
|
|
} catch (e) {
|
|
console.log('Language detection failed:', e)
|
|
}
|
|
|
|
if ((isForbidden || isProfane || isOffTopic || !isEnglish) && !isOwner) {
|
|
try {
|
|
const issueNumber = context.payload.issue?.number || context.payload.pull_request?.number
|
|
const reason = !isEnglish ? 'non-English comment' :
|
|
isForbidden ? 'forbidden link' :
|
|
isProfane ? 'profanity' : 'off-topic content'
|
|
|
|
await github.rest.issues.createComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
issue_number: issueNumber,
|
|
body: `Comment auto removed: ${reason} violates repository guidelines.`
|
|
})
|
|
|
|
await github.rest.issues.deleteComment({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
comment_id: context.payload.comment.id
|
|
})
|
|
} catch (error) {
|
|
console.error('Moderation error:', error)
|
|
throw error
|
|
}
|
|
}
|