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>
This commit is contained in:
318
f_core/f_classes/class.moderation.enhanced.php
Normal file
318
f_core/f_classes/class.moderation.enhanced.php
Normal file
@@ -0,0 +1,318 @@
|
||||
<?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'");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user