View file api/fetch.php

File size: 4.18Kb
<?php
session_start();
require '../db.php';

header('Content-Type: application/json');

if (!isset($_SESSION['user_id'])) {
    echo json_encode(['status' => 'error', 'message' => 'Unauthorized']);
    exit;
}

// Проверка статуса блокировки
$stmt = $pdo->prepare("SELECT status FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$uStatus = $stmt->fetchColumn();
if ($uStatus === 'blocked') {
    session_destroy();
    echo json_encode(['status' => 'error', 'message' => 'Blocked']);
    exit;
}

try {
    $roomId = isset($_GET['room_id']) ? intval($_GET['room_id']) : 1;
    $lastId = isset($_GET['last_id']) ? intval($_GET['last_id']) : 0;

    // Получить последние 50 сообщений с информацией об ответе
    $sql = "SELECT m.id, m.type, m.content, m.created_at, u.username, u.avatar, u.role, u.id as user_id_real, u.email, m.user_id, m.reply_to, m.is_deleted,
               p.content AS reply_content, p.type AS reply_type, pu.username AS reply_username
        FROM messages m 
        JOIN users u ON m.user_id = u.id 
        LEFT JOIN messages p ON m.reply_to = p.id
        LEFT JOIN users pu ON p.user_id = pu.id
        WHERE (m.room_id = :room_id OR m.room_id = 0) AND m.id > :last_id
        ORDER BY m.created_at ASC";

    if ($lastId == 0) {
        $sql = "SELECT * FROM (
            SELECT m.id, m.type, m.content, m.created_at, u.username, u.avatar, u.role, u.id as user_id_real, u.email, m.user_id, m.reply_to, m.is_deleted,
               p.content AS reply_content, p.type AS reply_type, pu.username AS reply_username
            FROM messages m 
            JOIN users u ON m.user_id = u.id 
            LEFT JOIN messages p ON m.reply_to = p.id
            LEFT JOIN users pu ON p.user_id = pu.id
            WHERE (m.room_id = :room_id OR m.room_id = 0)
            ORDER BY m.created_at DESC LIMIT 50
        ) t ORDER BY created_at ASC";
    }

    $stmt = $pdo->prepare($sql);
    $stmt->bindValue(':room_id', $roomId, PDO::PARAM_INT);
    if ($lastId > 0) {
        $stmt->bindValue(':last_id', $lastId, PDO::PARAM_INT);
    }
    $stmt->execute();
    $messages = $stmt->fetchAll();

    // Флаг для себя и обработка удаленных
    foreach ($messages as &$msg) {
        $msg['is_me'] = ($msg['user_id'] == $_SESSION['user_id']);
        if ($msg['is_deleted']) {
            $msg['type'] = 'deleted';
            $msg['content'] = '';
        }
    }

    // --- ЛОГИКА СТАТУСА ОНЛАЙН ---
    $onlineUsers = [];
    try {
        // 1. Обновить собственный last_seen
        $stmt = $pdo->prepare("UPDATE users SET last_seen = NOW() WHERE id = ?");
        $stmt->execute([$_SESSION['user_id']]);

        // 2. Получить онлайн пользователей (активных за последние 30 секунд)
        // Проверка существования столбца сначала неэффективна в цикле, 
        // relying on the try-catch block for safety during migration.
        $stmt = $pdo->prepare("SELECT username FROM users WHERE (last_seen > (NOW() - INTERVAL 30 SECOND) OR username = 'ChatBot') AND id != ?");
        $stmt->execute([$_SESSION['user_id']]);
        $onlineUsers = $stmt->fetchAll(PDO::FETCH_COLUMN);
    } catch (Exception $e) { /* ignore during migration delay */
    }

    // Получить пользователей, которые сейчас печатают (Активные за последние 3 секунды)
    $typingUsers = [];
    try {
        $stmt = $pdo->prepare("SELECT username FROM users WHERE last_typing > (NOW() - INTERVAL 3 SECOND) AND id != ?");
        $stmt->execute([$_SESSION['user_id']]);
        $typingUsers = $stmt->fetchAll(PDO::FETCH_COLUMN);
    } catch (Exception $e) { /* ignore */
    }

    echo json_encode([
        'status' => 'success',
        'messages' => $messages,
        'typing_users' => $typingUsers,
        'online_users' => $onlineUsers
    ]);
} catch (PDOException $e) {
    echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
}