( client: Octokit, owner: string, repo: string, commentId: number, commentBody: string, commentAuthor: string )
| 204 | } |
| 205 | |
| 206 | async function processSingleComment( |
| 207 | client: Octokit, |
| 208 | owner: string, |
| 209 | repo: string, |
| 210 | commentId: number, |
| 211 | commentBody: string, |
| 212 | commentAuthor: string |
| 213 | ): Promise<boolean> { |
| 214 | console.log(`Checking comment #${commentId} by @${commentAuthor}...`); |
| 215 | |
| 216 | if (await isOrgMember(client, owner, commentAuthor)) { |
| 217 | console.log(`@${commentAuthor} is an org member — skipping spam check.`); |
| 218 | return false; |
| 219 | } |
| 220 | |
| 221 | const result = await isSpamComment(commentBody); |
| 222 | |
| 223 | if (!result.isSpam) { |
| 224 | console.log(`Clean (confidence: ${result.confidence.toFixed(2)}). Reason: ${result.reason}`); |
| 225 | return false; |
| 226 | } |
| 227 | |
| 228 | console.log(`First pass flagged spam (confidence: ${result.confidence.toFixed(2)}). Running confirmation pass...`); |
| 229 | const confirmed = await confirmSpam(commentBody, result); |
| 230 | |
| 231 | if (!confirmed) { |
| 232 | console.log(`Confirmation pass did NOT agree — keeping comment #${commentId}.`); |
| 233 | return false; |
| 234 | } |
| 235 | |
| 236 | await deleteComment(client, owner, repo, commentId); |
| 237 | console.log(`--- Audit Log: Deleted comment #${commentId} ---`); |
| 238 | console.log(`Author: @${commentAuthor}`); |
| 239 | console.log(`Confidence: ${result.confidence.toFixed(2)}`); |
| 240 | console.log(`Reason: ${result.reason}`); |
| 241 | console.log(`Body length: ${commentBody.length} chars`); |
| 242 | console.log(`Timestamp: ${new Date().toISOString()}`); |
| 243 | console.log(`---`); |
| 244 | return true; |
| 245 | } |
| 246 | |
| 247 | |
| 248 | async function main() { |
no test coverage detected