66 lines
2.5 KiB
PHP
66 lines
2.5 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Moderation;
|
|
|
|
use App\Enums\ModerationStatus;
|
|
use App\Models\ContentModerationFinding;
|
|
use App\Models\User;
|
|
|
|
class UserModerationProfileService
|
|
{
|
|
/**
|
|
* @return array<string, mixed>|null
|
|
*/
|
|
public function profile(?int $userId): ?array
|
|
{
|
|
if (! $userId) {
|
|
return null;
|
|
}
|
|
|
|
$user = User::query()->with('statistics:user_id,uploads_count')->find($userId);
|
|
if (! $user) {
|
|
return null;
|
|
}
|
|
|
|
$findings = ContentModerationFinding::query()->where('user_id', $userId)->get([
|
|
'id', 'status', 'is_auto_hidden', 'is_false_positive', 'matched_domains_json', 'campaign_key', 'priority_score', 'created_at',
|
|
]);
|
|
|
|
$confirmedSpam = $findings->where('status', ModerationStatus::ConfirmedSpam)->count();
|
|
$safeCount = $findings->where('status', ModerationStatus::ReviewedSafe)->count();
|
|
$autoHidden = $findings->where('is_auto_hidden', true)->count();
|
|
$falsePositives = $findings->where('is_false_positive', true)->count();
|
|
$clusters = $findings->pluck('campaign_key')->filter()->unique()->count();
|
|
$domains = $findings->flatMap(static fn (ContentModerationFinding $finding): array => (array) $finding->matched_domains_json)->filter()->unique()->values();
|
|
$risk = app(UserRiskScoreService::class)->assess($userId, $domains->all());
|
|
|
|
$tier = match (true) {
|
|
$risk['risk_score'] >= 75 => 'high_risk',
|
|
$risk['risk_score'] >= 45 => 'monitored',
|
|
$risk['risk_score'] <= 8 && $safeCount >= 2 => 'trusted',
|
|
default => 'normal',
|
|
};
|
|
|
|
$recommendedPolicy = match ($tier) {
|
|
'high_risk' => 'new_user_strict_mode',
|
|
'monitored' => 'comments_high_volume_antispam',
|
|
'trusted' => 'trusted_user_relaxed_mode',
|
|
default => 'default',
|
|
};
|
|
|
|
return [
|
|
'user' => $user,
|
|
'risk_score' => $risk['risk_score'],
|
|
'trust_score' => max(0, 100 - $risk['risk_score'] + ($safeCount * 3) - ($falsePositives * 2)),
|
|
'tier' => $tier,
|
|
'recommended_policy' => $recommendedPolicy,
|
|
'confirmed_spam_count' => $confirmedSpam,
|
|
'safe_count' => $safeCount,
|
|
'auto_hidden_count' => $autoHidden,
|
|
'false_positive_count' => $falsePositives,
|
|
'cluster_memberships' => $clusters,
|
|
'promoted_domains' => $domains->take(12)->all(),
|
|
'signals' => $risk['signals'],
|
|
];
|
|
}
|
|
} |