Реалізація системи модерації контенту на сайті

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Реалізація системи модерації контенту на сайті
Складна
~1-2 тижні
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Реалізація системи модерації контенту

Система модерації перевіряє користувацький контент перед публікацією або після неї. Включає ручну модерацію, автоматичну фільтрацію (стоп-слова, посилання, ML-моделі), жалоби користувачів, чергу завдань для модераторів.

Архітектура

[Користувач публікує контент]
         ↓
[Автофільтр: перевірка спаму/токсичності]
    ↙           ↘
[Автоутвердження]  [Відправити в чергу модерації]
                         ↓
               [Панель модератора]
               ↙          ↘       ↘
         [Затвердити]  [Відхилити]  [Тіньовий бан]
              ↓           ↓
       [Публікація]  [Уведомити користувача]

Модель зі станами модерації

// ModerationStatus: pending, approved, rejected, spam, shadow_banned

class Comment extends Model
{
    use HasModerationStatus;

    protected $casts = [
        'moderation_metadata' => 'array',
        'moderated_at'        => 'datetime',
    ];

    public function scopeVisible(Builder $query): Builder
    {
        return $query->where('status', 'approved');
    }

    public function scopePendingModeration(Builder $query): Builder
    {
        return $query->where('status', 'pending');
    }
}

Автоматична фільтрація

class ContentModerationService
{
    private array $spamPatterns = [
        '/https?:\/\/[^\s]+/i',         // зовнішні посилання
        '/\b(casino|viagra|loan|crypto)\b/i',
        '/(.)\1{5,}/',                  // повторювані символи (ааааааа)
    ];

    private array $bannedWords;  // завантажується з БД/конфіга

    public function analyze(string $content, User|null $author): ModerationResult
    {
        $signals = [];
        $spamScore = 0;

        // Перевірка стоп-слів
        foreach ($this->bannedWords as $word) {
            if (stripos($content, $word) !== false) {
                $signals[] = "banned_word:{$word}";
                $spamScore += 40;
            }
        }

        // Перевірка паттернів
        foreach ($this->spamPatterns as $pattern) {
            if (preg_match($pattern, $content)) {
                $signals[] = "pattern_match:{$pattern}";
                $spamScore += 30;
            }
        }

        // Історія автора
        if ($author) {
            $authorSpamRate = $author->comments()
                ->where('status', 'spam')
                ->count() / max($author->comments()->count(), 1);

            if ($authorSpamRate > 0.3) {
                $signals[] = 'author_spam_history';
                $spamScore += 50;
            }
        } else {
            $spamScore += 10;  // анонімні — вищий ризик
        }

        // Довжина контенту
        if (strlen($content) < 5) {
            $signals[] = 'too_short';
            $spamScore += 20;
        }

        return new ModerationResult(
            score: $spamScore,
            signals: $signals,
            decision: match (true) {
                $spamScore >= 80 => ModerationDecision::SPAM,
                $spamScore >= 50 => ModerationDecision::PENDING,
                default          => ModerationDecision::APPROVE,
            }
        );
    }
}

Панель модератора

class ModerationController extends Controller
{
    public function queue(Request $request): JsonResponse
    {
        $items = Comment::pendingModeration()
            ->with('user:id,name,email', 'entity')
            ->when($request->type, fn($q) => $q->where('entity_type', $request->type))
            ->orderBy('moderation_score', 'desc')  // спочатку найбільш підозрілі
            ->paginate(50);

        return response()->json($items);
    }

    public function decision(Request $request, Comment $comment): JsonResponse
    {
        $request->validate([
            'action' => 'required|in:approve,reject,spam,shadow_ban',
            'reason' => 'nullable|string|max:500',
        ]);

        $comment->update([
            'status'         => match ($request->action) {
                'approve'     => 'approved',
                'reject'      => 'rejected',
                'spam'        => 'spam',
                'shadow_ban'  => 'shadow_banned',
            },
            'moderated_by'   => auth()->id(),
            'moderated_at'   => now(),
            'rejection_reason' => $request->reason,
        ]);

        if ($request->action === 'approve') {
            event(new CommentApprovedEvent($comment));
        }

        if (in_array($request->action, ['reject', 'spam'])) {
            $comment->user?->notify(new CommentRejectedNotification($comment));
        }

        UpdateAuthorReputationJob::dispatch($comment->user, $request->action);

        return response()->json(['status' => 'ok']);
    }
}

Жалоби користувачів

class ReportController extends Controller
{
    public function store(Request $request, Comment $comment): JsonResponse
    {
        $request->validate(['reason' => 'required|in:spam,abuse,misinformation,other']);

        Report::firstOrCreate(
            ['reporter_id' => auth()->id(), 'comment_id' => $comment->id],
            ['reason' => $request->reason]
        );

        $reportCount = Report::where('comment_id', $comment->id)->count();

        if ($reportCount >= 3 && $comment->status === 'approved') {
            $comment->update(['status' => 'pending', 'auto_flagged' => true]);
        }

        return response()->json(['reported' => true]);
    }
}

Термін реалізації

Задача Термін
Автофільтр (стоп-слова + паттерни) 1–2 дні
Чергу модерації + панель для модератора 2–3 дні
Жалоби користувачів +1 день
Інтеграція Perspective API (Google) +1 день
Статистика та звіти +1–2 дні
Повна система з репутацією авторів 5–8 днів