dolibarr/.github/workflows/moderation.yml
MDW 29b60cd552
Fix: Update comment moderation logic (#38451)
# 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>
2026-06-10 21:15:32 +02:00

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
}
}