Files
SkinbaseNova/app/Services/Moderation/UserModerationProfileService.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'],
];
}
}