Add comment spam classification and captcha checks.
Score artwork comments with local signatures plus Together AI, and optionally require Turnstile before posting.
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
use App\Services\Moderation\TogetherCommentSpamClassifier;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Tests\TestCase;
|
||||
|
||||
uses(TestCase::class);
|
||||
|
||||
beforeEach(function (): void {
|
||||
config([
|
||||
'comment_spam.ai.api_key' => 'test-key',
|
||||
'comment_spam.ai.base_url' => 'https://api.together.test/v1',
|
||||
'comment_spam.ai.model' => 'meta-llama/Llama-3.2-3B-Instruct-Turbo',
|
||||
]);
|
||||
});
|
||||
|
||||
it('classifies using the strict Together JSON contract', function (string $model): void {
|
||||
config(['comment_spam.ai.model' => $model]);
|
||||
Http::fake([
|
||||
'https://api.together.test/*' => Http::response([
|
||||
'choices' => [['message' => ['content' => '{"spam":true,"confidence":0.95,"reason":"Unsolicited promotion."}']]],
|
||||
]),
|
||||
]);
|
||||
|
||||
$result = app(TogetherCommentSpamClassifier::class)->classify('Buy now at example.test');
|
||||
|
||||
expect($result->spam)->toBeTrue()
|
||||
->and($result->confidence)->toBe(0.95)
|
||||
->and($result->provider)->toBe('together')
|
||||
->and($result->model)->toBe($model);
|
||||
})->with([
|
||||
'Llama' => ['meta-llama/Llama-3.2-3B-Instruct-Turbo'],
|
||||
'Bonsai' => ['Prism-ML/Ternary-Bonsai-27B'],
|
||||
]);
|
||||
|
||||
it('rejects an unsupported configured model before making an HTTP request', function (): void {
|
||||
config(['comment_spam.ai.model' => 'some/unsupported-model']);
|
||||
Http::fake();
|
||||
|
||||
expect(fn () => app(TogetherCommentSpamClassifier::class)->classify('hello'))
|
||||
->toThrow(RuntimeException::class, 'Unsupported Together AI comment spam model.');
|
||||
|
||||
Http::assertNothingSent();
|
||||
});
|
||||
|
||||
it('rejects malformed or out of range classifier output', function (array $json): void {
|
||||
Http::fake([
|
||||
'https://api.together.test/*' => Http::response([
|
||||
'choices' => [['message' => ['content' => json_encode($json)]]],
|
||||
]),
|
||||
]);
|
||||
|
||||
expect(fn () => app(TogetherCommentSpamClassifier::class)->classify('hello'))
|
||||
->toThrow(RuntimeException::class);
|
||||
})->with([
|
||||
[['spam' => 'true', 'confidence' => 0.9, 'reason' => 'bad type']],
|
||||
[['spam' => true, 'confidence' => 1.1, 'reason' => 'out of range']],
|
||||
[['spam' => true, 'confidence' => 0.9]],
|
||||
]);
|
||||
|
||||
it('fails closed when Together is not configured', function (): void {
|
||||
config(['comment_spam.ai.api_key' => '']);
|
||||
|
||||
expect(fn () => app(TogetherCommentSpamClassifier::class)->classify('hello'))
|
||||
->toThrow(RuntimeException::class);
|
||||
});
|
||||
Reference in New Issue
Block a user