prepare("SELECT id FROM users WHERE bot_token = ? AND is_bot = TRUE"); $stmt->execute([$bot_token]); $bot = $stmt->fetch(); if ($bot) { $user_id = $bot['id']; } else { http_response_code(401); echo json_encode(['success' => false, 'error' => 'Invalid Bot Token']); exit; } } elseif (isset($_SESSION['user_id'])) { $user_id = $_SESSION['user_id']; } else { http_response_code(401); echo json_encode(['success' => false, 'error' => 'Unauthorized']); exit; } if ($_SERVER['REQUEST_METHOD'] === 'GET') { $channel_id = $_GET['channel_id'] ?? 0; $pinned = isset($_GET['pinned']) && $_GET['pinned'] == 1; if ($pinned) { try { // Get server_id for the channel $stmt = db()->prepare("SELECT server_id FROM channels WHERE id = ?"); $stmt->execute([$channel_id]); $server_id = $stmt->fetchColumn(); $stmt = db()->prepare(" SELECT m.*, u.username, u.avatar_url, (SELECT r.color FROM roles r JOIN user_roles ur ON r.id = ur.role_id WHERE ur.user_id = u.id AND r.server_id = ? ORDER BY r.position DESC LIMIT 1) as role_color FROM messages m JOIN users u ON m.user_id = u.id WHERE m.channel_id = ? AND m.is_pinned = 1 ORDER BY m.created_at DESC "); $stmt->execute([$server_id ?: 0, $channel_id]); $msgs = $stmt->fetchAll(); foreach ($msgs as &$m) { $m['time'] = date('H:i', strtotime($m['created_at'])); $m['metadata'] = $m['metadata'] ? json_decode($m['metadata']) : null; } echo json_encode(['success' => true, 'messages' => $msgs]); } catch (Exception $e) { echo json_encode(['success' => false, 'error' => $e->getMessage()]); } exit; } } if ($_SERVER['REQUEST_METHOD'] === 'PUT') { $data = json_decode(file_get_contents('php://input'), true); $message_id = $data['id'] ?? 0; $content = $data['content'] ?? ''; $action = $data['action'] ?? 'edit'; try { if ($action === 'pin') { $stmt = db()->prepare("UPDATE messages SET is_pinned = 1 WHERE id = ?"); $stmt->execute([$message_id]); echo json_encode(['success' => true]); exit; } if ($action === 'unpin') { $stmt = db()->prepare("UPDATE messages SET is_pinned = 0 WHERE id = ?"); $stmt->execute([$message_id]); echo json_encode(['success' => true]); exit; } if (empty($content)) { echo json_encode(['success' => false, 'error' => 'Content cannot be empty']); exit; } $stmt = db()->prepare("UPDATE messages SET content = ? WHERE id = ? AND user_id = ?"); $stmt->execute([$content, $message_id, $user_id]); if ($stmt->rowCount() > 0) { echo json_encode(['success' => true]); } else { echo json_encode(['success' => false, 'error' => 'Message not found or unauthorized']); } } catch (Exception $e) { echo json_encode(['success' => false, 'error' => $e->getMessage()]); } exit; } if ($_SERVER['REQUEST_METHOD'] === 'DELETE') { $data = json_decode(file_get_contents('php://input'), true); $message_id = $data['id'] ?? 0; try { $stmt = db()->prepare("DELETE FROM messages WHERE id = ? AND user_id = ?"); $stmt->execute([$message_id, $user_id]); if ($stmt->rowCount() > 0) { echo json_encode(['success' => true]); } else { echo json_encode(['success' => false, 'error' => 'Message not found or unauthorized']); } } catch (Exception $e) { echo json_encode(['success' => false, 'error' => $e->getMessage()]); } exit; } $content = ''; $channel_id = 0; $thread_id = null; $attachment_url = null; if (strpos($_SERVER['CONTENT_TYPE'] ?? '', 'application/json') !== false) { $data = json_decode(file_get_contents('php://input'), true); $content = $data['content'] ?? ''; $channel_id = $data['channel_id'] ?? 0; $thread_id = !empty($data['thread_id']) ? (int)$data['thread_id'] : null; } else { $content = $_POST['content'] ?? ''; $channel_id = $_POST['channel_id'] ?? 0; $thread_id = !empty($_POST['thread_id']) ? (int)$_POST['thread_id'] : null; // Check if file sharing is allowed in this channel $stmt = db()->prepare("SELECT allow_file_sharing FROM channels WHERE id = ?"); $stmt->execute([$channel_id]); $channel = $stmt->fetch(); $can_share_files = $channel ? (bool)$channel['allow_file_sharing'] : true; if (isset($_FILES['file']) && $_FILES['file']['error'] === UPLOAD_ERR_OK) { if (!$can_share_files) { echo json_encode(['success' => false, 'error' => 'File sharing is disabled in this channel.']); exit; } $upload_dir = 'assets/uploads/'; if (!is_dir($upload_dir)) mkdir($upload_dir, 0775, true); $filename = time() . '_' . basename($_FILES['file']['name']); $target_file = $upload_dir . $filename; if (move_uploaded_file($_FILES['file']['tmp_name'], $target_file)) { $attachment_url = $target_file; } } } if (empty($content) && empty($attachment_url)) { echo json_encode(['success' => false, 'error' => 'Empty content and no attachment']); exit; } // Check granular permissions if (!Permissions::canSendInChannel($user_id, $channel_id)) { echo json_encode(['success' => false, 'error' => 'You do not have permission to send messages in this channel.']); exit; } if (!empty($content)) { $moderation = moderateContent($content); if (!$moderation['is_safe']) { echo json_encode(['success' => false, 'error' => 'Message flagged as inappropriate: ' . ($moderation['reason'] ?? 'Violation of community standards')]); exit; } } $metadata = null; if (!empty($content)) { $urls = extractUrls($content); if (!empty($urls)) { // Fetch OG data for the first URL $ogData = fetchOpenGraphData($urls[0]); if ($ogData) { $metadata = json_encode($ogData); } } } try { $stmt = db()->prepare("INSERT INTO messages (channel_id, thread_id, user_id, content, attachment_url, metadata) VALUES (?, ?, ?, ?, ?, ?)"); $stmt->execute([$channel_id, $thread_id, $user_id, $content, $attachment_url, $metadata]); $last_id = db()->lastInsertId(); // Enforce message limit if set $stmt = db()->prepare("SELECT message_limit FROM channels WHERE id = ?"); $stmt->execute([$channel_id]); $channel = $stmt->fetch(); if ($channel && !empty($channel['message_limit'])) { $limit = (int)$channel['message_limit']; // Delete oldest messages that exceed the limit $stmt = db()->prepare(" DELETE FROM messages WHERE channel_id = ? AND id NOT IN ( SELECT id FROM ( SELECT id FROM messages WHERE channel_id = ? ORDER BY created_at DESC, id DESC LIMIT ? ) as tmp ) "); $stmt->execute([$channel_id, $channel_id, $limit]); } // Get server_id for the channel $stmt = db()->prepare("SELECT server_id FROM channels WHERE id = ?"); $stmt->execute([$channel_id]); $server_id = $stmt->fetchColumn(); // Fetch message with username and role color for the response $stmt = db()->prepare(" SELECT m.*, u.username, u.avatar_url, (SELECT r.color FROM roles r JOIN user_roles ur ON r.id = ur.role_id WHERE ur.user_id = u.id AND r.server_id = ? ORDER BY r.position DESC LIMIT 1) as role_color FROM messages m JOIN users u ON m.user_id = u.id WHERE m.id = ? "); $stmt->execute([$server_id ?: 0, $last_id]); $msg = $stmt->fetch(); echo json_encode([ 'success' => true, 'message' => [ 'id' => $msg['id'], 'user_id' => $msg['user_id'], 'username' => $msg['username'], 'avatar_url' => $msg['avatar_url'], 'role_color' => $msg['role_color'], 'content' => $msg['content'], 'attachment_url' => $msg['attachment_url'], 'metadata' => $msg['metadata'] ? json_decode($msg['metadata']) : null, 'time' => date('H:i', strtotime($msg['created_at'])) ] ]); } catch (Exception $e) { echo json_encode(['success' => false, 'error' => $e->getMessage()]); }