Files
easystream-main/f_core/f_classes/class.moderation.enhanced.php
SamiAhmed7777 d22b3e1c0d feat: Add complete Docker deployment with web-based setup wizard
Major additions:
- Web-based setup wizard (setup.php, setup_wizard.php, setup-wizard.js)
- Production Docker configuration (docker-compose.prod.yml, .env.production)
- Database initialization SQL files (deploy/init_settings.sql)
- Template builder system with drag-and-drop UI
- Advanced features (OAuth, CDN, enhanced analytics, monetization)
- Comprehensive documentation (deployment guides, quick start, feature docs)
- Design system with accessibility and responsive layout
- Deployment automation scripts (deploy.ps1, generate-secrets.ps1)

Setup wizard allows customization of:
- Platform name and branding
- Domain configuration
- Membership tiers and pricing
- Admin credentials
- Feature toggles

Database includes 270+ tables for complete video streaming platform with
advanced features for analytics, moderation, template building, and monetization.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 01:42:31 -07:00

319 lines
9.9 KiB
PHP

<?php
/**
* Easy Stream Enhanced Moderation System
* Advanced moderation with AI, rules, appeals
* Version: 1.0
*/
defined('_ISVALID') or header('Location: /error');
class VModerationEnhanced {
private static $db;
public static function init() {
self::$db = VDatabase::getInstance();
}
/**
* Submit content for moderation
* @param string $target_type Type (video, comment, user, post)
* @param string $target_id Target ID
* @param int $reporter_id Reporter user ID
* @param string $reason Reason for report
* @param string $priority Priority level
* @return int Queue ID
*/
public static function submitReport($target_type, $target_id, $reporter_id, $reason, $priority = 'medium') {
self::init();
$target_type = VDatabase::escape($target_type);
$target_id = VDatabase::escape($target_id);
$reporter_id = (int)$reporter_id;
$reason = VDatabase::escape($reason);
$priority = VDatabase::escape($priority);
$sql = "INSERT INTO db_moderation_queue
(target_type, target_id, reporter_id, reason, priority, status, created_at)
VALUES ('$target_type', '$target_id', $reporter_id, '$reason', '$priority', 'pending', NOW())";
if (self::$db->execute($sql)) {
return self::$db->insert_id();
}
return false;
}
/**
* Get moderation queue
* @param string $status Filter by status
* @param int $limit Number of items
* @return array Queue items
*/
public static function getQueue($status = 'pending', $limit = 50) {
self::init();
$status = VDatabase::escape($status);
$limit = (int)$limit;
$sql = "SELECT mq.*, au.usr_user as reporter_username
FROM db_moderation_queue mq
LEFT JOIN db_accountuser au ON mq.reporter_id = au.usr_id
WHERE mq.status = '$status'
ORDER BY
CASE priority
WHEN 'urgent' THEN 1
WHEN 'high' THEN 2
WHEN 'medium' THEN 3
ELSE 4
END,
mq.created_at ASC
LIMIT $limit";
$result = self::$db->execute($sql);
$queue = [];
if ($result) {
while ($row = $result->FetchRow()) {
$queue[] = $row;
}
}
return $queue;
}
/**
* Take moderation action
* @param int $queue_id Queue item ID
* @param int $moderator_id Moderator user ID
* @param string $action Action taken
* @param string $reason Reason for action
* @return bool Success
*/
public static function takeAction($queue_id, $moderator_id, $action, $reason) {
self::init();
$queue_id = (int)$queue_id;
$moderator_id = (int)$moderator_id;
$action = VDatabase::escape($action);
$reason = VDatabase::escape($reason);
// Get queue item
$sql = "SELECT * FROM db_moderation_queue WHERE queue_id = $queue_id";
$result = self::$db->execute($sql);
if (!$result || $result->RecordCount() == 0) {
return false;
}
$item = $result->FetchRow();
// Record action
$sql = "INSERT INTO db_moderation_actions
(target_type, target_id, moderator_id, action, reason, is_automated, created_at)
VALUES ('{$item['target_type']}', '{$item['target_id']}', $moderator_id, '$action', '$reason', 0, NOW())";
if (!self::$db->execute($sql)) {
return false;
}
$action_id = self::$db->insert_id();
// Update queue
$sql = "UPDATE db_moderation_queue
SET status = 'resolved',
resolved_by = $moderator_id,
resolution = '$reason',
resolved_at = NOW()
WHERE queue_id = $queue_id";
self::$db->execute($sql);
// Apply action based on type
self::applyAction($item['target_type'], $item['target_id'], $action);
// Add strike if needed
if ($action == 'removed' || $action == 'banned') {
self::addStrike($item['target_id'], $action_id, $action, $reason);
}
return true;
}
/**
* Apply moderation action to target
*/
private static function applyAction($target_type, $target_id, $action) {
switch ($action) {
case 'removed':
if ($target_type == 'video') {
$target_id_safe = VDatabase::escape($target_id);
self::$db->execute("UPDATE db_videofiles SET privacy = 'removed', approved = 0 WHERE file_key = '$target_id_safe'");
}
break;
case 'age_restricted':
if ($target_type == 'video') {
$target_id_safe = VDatabase::escape($target_id);
self::$db->execute("UPDATE db_videofiles SET file_adult = 1 WHERE file_key = '$target_id_safe'");
}
break;
case 'banned':
if ($target_type == 'user') {
$usr_id = (int)$target_id;
self::$db->execute("UPDATE db_accountuser SET usr_status = 'suspended' WHERE usr_id = $usr_id");
}
break;
}
}
/**
* Add strike to user
*/
private static function addStrike($usr_id, $action_id, $type, $reason) {
$usr_id = (int)$usr_id;
$action_id = (int)$action_id;
$type_safe = VDatabase::escape($type);
$reason_safe = VDatabase::escape($reason);
// Determine strike type based on severity
$strike_type = match($type) {
'removed' => 'strike',
'banned' => 'ban',
default => 'warning'
};
$sql = "INSERT INTO db_user_strikes
(usr_id, action_id, type, reason, is_active, created_at)
VALUES ($usr_id, $action_id, '$strike_type', '$reason_safe', 1, NOW())";
return self::$db->execute($sql);
}
/**
* Get user strikes
*/
public static function getUserStrikes($usr_id) {
self::init();
$usr_id = (int)$usr_id;
$sql = "SELECT * FROM db_user_strikes
WHERE usr_id = $usr_id AND is_active = 1
ORDER BY created_at DESC";
$result = self::$db->execute($sql);
$strikes = [];
if ($result) {
while ($row = $result->FetchRow()) {
$strikes[] = $row;
}
}
return $strikes;
}
/**
* Submit appeal
*/
public static function submitAppeal($action_id, $usr_id, $reason, $evidence = []) {
self::init();
$action_id = (int)$action_id;
$usr_id = (int)$usr_id;
$reason_safe = VDatabase::escape($reason);
$evidence_json = VDatabase::escape(json_encode($evidence));
$sql = "INSERT INTO db_moderation_appeals
(action_id, usr_id, reason, evidence, status, created_at)
VALUES ($action_id, $usr_id, '$reason_safe', '$evidence_json', 'pending', NOW())";
if (self::$db->execute($sql)) {
// Mark action as appealed
self::$db->execute("UPDATE db_moderation_actions SET is_appealed = 1 WHERE action_id = $action_id");
return self::$db->insert_id();
}
return false;
}
/**
* Get pending appeals
*/
public static function getPendingAppeals($limit = 50) {
self::init();
$limit = (int)$limit;
$sql = "SELECT ma.*, au.usr_user, au.usr_email
FROM db_moderation_appeals ma
JOIN db_accountuser au ON ma.usr_id = au.usr_id
WHERE ma.status = 'pending'
ORDER BY ma.created_at ASC
LIMIT $limit";
$result = self::$db->execute($sql);
$appeals = [];
if ($result) {
while ($row = $result->FetchRow()) {
$row['evidence'] = json_decode($row['evidence'], true);
$appeals[] = $row;
}
}
return $appeals;
}
/**
* Review appeal
*/
public static function reviewAppeal($appeal_id, $reviewer_id, $status, $notes) {
self::init();
$appeal_id = (int)$appeal_id;
$reviewer_id = (int)$reviewer_id;
$status_safe = VDatabase::escape($status);
$notes_safe = VDatabase::escape($notes);
$sql = "UPDATE db_moderation_appeals
SET status = '$status_safe',
reviewed_by = $reviewer_id,
review_notes = '$notes_safe',
reviewed_at = NOW()
WHERE appeal_id = $appeal_id";
if (!self::$db->execute($sql)) {
return false;
}
// If approved, restore content
if ($status == 'approved') {
$sql = "SELECT action_id FROM db_moderation_appeals WHERE appeal_id = $appeal_id";
$result = self::$db->execute($sql);
if ($result) {
$row = $result->FetchRow();
$action_id = (int)$row['action_id'];
// Get original action
$sql = "SELECT * FROM db_moderation_actions WHERE action_id = $action_id";
$result = self::$db->execute($sql);
if ($result) {
$action = $result->FetchRow();
self::restoreContent($action['target_type'], $action['target_id']);
}
}
}
return true;
}
/**
* Restore content after successful appeal
*/
private static function restoreContent($target_type, $target_id) {
if ($target_type == 'video') {
$target_id_safe = VDatabase::escape($target_id);
self::$db->execute("UPDATE db_videofiles SET privacy = 'public', approved = 1 WHERE file_key = '$target_id_safe'");
}
}
}