36163-vm/api.php
2025-11-24 05:17:23 +00:00

208 lines
6.5 KiB
PHP

<?php
session_start();
if (!isset($_SESSION['user_id'])) {
http_response_code(401);
echo json_encode(['error' => 'User not authenticated']);
exit;
}
require_once 'db/config.php';
header('Content-Type: application/json');
$action = isset($_POST['action']) ? $_POST['action'] : ($_GET['action'] ?? '');
$current_user_id = $_SESSION['user_id'];
try {
switch ($action) {
case 'get_new_messages':
getNewMessages();
break;
case 'send_message':
sendMessage();
break;
case 'create_room':
createRoom();
break;
case 'start_private_chat':
startPrivateChat();
break;
default:
throw new Exception("Invalid action.");
}
} catch (Exception $e) {
http_response_code(400);
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
function sendMessage() {
global $current_user_id;
$message = trim($_POST['message'] ?? '');
$room_id = $_POST['room_id'] ?? null;
if (empty($message) && empty($_FILES['attachment']['name'])) {
throw new Exception("Message or attachment cannot be empty.");
}
if (!$room_id) {
throw new Exception("Invalid room.");
}
$pdo = db();
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$has_attachment = false;
$file_data = null;
// Handle file upload
if (isset($_FILES['attachment']) && $_FILES['attachment']['error'] == UPLOAD_ERR_OK) {
$file = $_FILES['attachment'];
if ($file['size'] > 100 * 1024 * 1024) { // 100MB limit
throw new Exception("File size exceeds the 100MB limit.");
}
$upload_dir = 'uploads/';
if (!is_dir($upload_dir)) {
mkdir($upload_dir, 0775, true);
}
$file_name = uniqid() . '-' . basename($file['name']);
$file_path = $upload_dir . $file_name;
if (move_uploaded_file($file['tmp_name'], $file_path)) {
$has_attachment = true;
$file_data = [
'name' => $file['name'],
'path' => $file_path,
'size' => $file['size'],
'type' => $file['type']
];
} else {
throw new Exception("Failed to upload file.");
}
}
$pdo->beginTransaction();
$stmt = $pdo->prepare("INSERT INTO messages (user_id, room_id, message) VALUES (?, ?, ?)");
$stmt->execute([$current_user_id, $room_id, $message]);
$message_id = $pdo->lastInsertId();
if ($has_attachment && $file_data) {
$stmt = $pdo->prepare("INSERT INTO files (message_id, original_name, file_path, file_size, mime_type) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$message_id, $file_data['name'], $file_data['path'], $file_data['size'], $file_data['type']]);
}
$pdo->commit();
echo json_encode(['success' => true]);
}
function getNewMessages() {
global $current_user_id;
$roomId = $_GET['room_id'] ?? 0;
$lastMessageId = $_GET['last_message_id'] ?? 0;
if (empty($roomId)) {
echo json_encode([]);
exit;
}
$pdo = db();
// Check if user is a member of the room
$stmt = $pdo->prepare("SELECT 1 FROM room_members WHERE room_id = ? AND user_id = ?");
$stmt->execute([$roomId, $current_user_id]);
if ($stmt->fetchColumn() === false) {
// If not a member, check if it's a public room (no members defined)
$stmt = $pdo->prepare("SELECT COUNT(*) FROM room_members WHERE room_id = ?");
$stmt->execute([$roomId]);
if ($stmt->fetchColumn() > 0) {
http_response_code(403);
throw new Exception("Access denied to room");
}
}
// Poll for new messages
$startTime = time();
$timeout = 25; // 25 seconds timeout for long polling
while (time() - $startTime < $timeout) {
$stmt = $pdo->prepare("
SELECT
m.id, m.message, m.created_at, u.username,
f.original_name as file_name, f.file_path, f.file_size, f.mime_type as file_type
FROM messages m
JOIN users u ON m.user_id = u.id
LEFT JOIN files f ON m.id = f.message_id
WHERE m.room_id = ? AND m.id > ?
ORDER BY m.id ASC
");
$stmt->execute([$roomId, $lastMessageId]);
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (!empty($messages)) {
echo json_encode($messages);
exit;
}
// Wait for a short period before polling again
sleep(1);
}
// If no new messages after timeout, return empty array
echo json_encode([]);
}
function createRoom() {
global $current_user_id;
$room_name = trim($_POST['room_name'] ?? '');
if (empty($room_name)) {
throw new Exception("Room name cannot be empty.");
}
$pdo = db();
$stmt = $pdo->prepare("INSERT INTO rooms (name, created_by) VALUES (?, ?)");
$stmt->execute([$room_name, $current_user_id]);
$new_room_id = $pdo->lastInsertId();
$stmt = $pdo->prepare("INSERT INTO room_members (room_id, user_id) VALUES (?, ?)");
$stmt->execute([$new_room_id, $current_user_id]);
echo json_encode(['success' => true, 'room_id' => $new_room_id]);
}
function startPrivateChat() {
global $current_user_id;
$other_user_id = $_POST['user_id'] ?? null;
if (!$other_user_id || $other_user_id == $current_user_id) {
throw new Exception("Invalid user ID.");
}
$pdo = db();
// Check if a private room already exists between the two users
$stmt = $pdo->prepare("
SELECT r.id FROM rooms r
JOIN room_members rm1 ON r.id = rm1.room_id
JOIN room_members rm2 ON r.id = rm2.room_id
WHERE r.is_private = 1
AND rm1.user_id = ?
AND rm2.user_id = ?
");
$stmt->execute([$current_user_id, $other_user_id]);
$room = $stmt->fetch();
if ($room) {
echo json_encode(['success' => true, 'room_id' => $room['id']]);
} else {
// Create a new private room
$stmt = $pdo->prepare("INSERT INTO rooms (name, created_by, is_private) VALUES (?, ?, 1)");
$stmt->execute(["Private Chat", $current_user_id]);
$new_room_id = $pdo->lastInsertId();
// Add both users to the new room
$stmt = $pdo->prepare("INSERT INTO room_members (room_id, user_id) VALUES (?, ?), (?, ?)");
$stmt->execute([$new_room_id, $current_user_id, $new_room_id, $other_user_id]);
echo json_encode(['success' => true, 'room_id' => $new_room_id]);
}
}