38443-vm/index.php
Flatlogic Bot ef520f4259 v3
2026-02-15 10:33:41 +00:00

293 lines
16 KiB
PHP

<?php
require_once 'auth/session.php';
requireLogin();
$user = getCurrentUser();
$current_user_id = $user['id'];
// Fetch servers user is member of
$stmt = db()->prepare("
SELECT s.* FROM servers s
JOIN server_members sm ON s.id = sm.server_id
WHERE sm.user_id = ?
LIMIT 20
");
$stmt->execute([$current_user_id]);
$servers = $stmt->fetchAll();
$active_server_id = $_GET['server_id'] ?? ($servers[0]['id'] ?? 1);
// If no servers found, we might want to show a default or an empty state
// For now, let's assume the seed data or the first server works
// Fetch channels
$stmt = db()->prepare("SELECT * FROM channels WHERE server_id = ?");
$stmt->execute([$active_server_id]);
$channels = $stmt->fetchAll();
$active_channel_id = $_GET['channel_id'] ?? ($channels[0]['id'] ?? 1);
// Fetch messages
$stmt = db()->prepare("
SELECT m.*, u.username, u.avatar_url
FROM messages m
JOIN users u ON m.user_id = u.id
WHERE m.channel_id = ?
ORDER BY m.created_at ASC
LIMIT 50
");
$stmt->execute([$active_channel_id]);
$messages = $stmt->fetchAll();
$current_channel_name = 'general';
foreach($channels as $c) if($c['id'] == $active_channel_id) $current_channel_name = $c['name'];
// Fetch members
$stmt = db()->prepare("
SELECT u.username, u.avatar_url, u.status
FROM users u
JOIN server_members sm ON u.id = sm.user_id
WHERE sm.server_id = ?
");
$stmt->execute([$active_server_id]);
$members = $stmt->fetchAll();
// SEO & Env tags
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Discord-like messaging app built with PHP';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#<?php echo htmlspecialchars($current_channel_name); ?> | <?php echo htmlspecialchars($projectDescription); ?></title>
<meta name="description" content="<?php echo htmlspecialchars($projectDescription); ?>">
<meta property="og:description" content="<?php echo htmlspecialchars($projectDescription); ?>">
<meta property="twitter:description" content="<?php echo htmlspecialchars($projectDescription); ?>">
<?php if ($projectImageUrl): ?>
<meta property="og:image" content="<?php echo htmlspecialchars($projectImageUrl); ?>">
<meta property="twitter:image" content="<?php echo htmlspecialchars($projectImageUrl); ?>">
<?php endif; ?>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/discord.css?v=<?php echo time(); ?>">
</head>
<body>
<div class="discord-app">
<!-- Servers Sidebar -->
<div class="servers-sidebar">
<a href="index.php" class="server-icon active" title="Home">
<svg width="28" height="20" viewBox="0 0 28 20" fill="currentColor"><path d="M23.0212 1.67671C21.3107 0.883335 19.4805 0.314845 17.5566 0C17.3137 0.434033 17.0423 1.00252 16.8488 1.46581C14.8193 1.16016 12.8016 1.16016 10.8011 1.46581C10.6076 1.00252 10.3255 0.434033 10.0827 0C8.14811 0.314845 6.31792 0.883335 4.60741 1.67671C1.14775 6.84711 0.210418 11.8962 0.67293 16.8681C2.9723 18.5677 5.19143 19.5997 7.37191 20C7.91578 19.2558 8.3897 18.4616 8.79155 17.6166C7.99616 17.3148 7.2343 16.9416 6.51603 16.505C6.70881 16.3639 6.89745 16.2125 7.07923 16.052C11.4116 18.0494 16.1264 18.0494 20.4137 16.052C20.597 16.2125 20.7856 16.3639 20.9784 16.505C20.2586 16.9416 19.4967 17.3148 18.7013 17.6166C19.1031 18.4616 19.577 19.2558 20.1209 20C22.3014 19.5997 24.5205 18.5677 26.8199 16.8681C27.3693 11.127 25.9189 6.13063 23.0212 1.67671ZM9.51636 13.6749C8.21405 13.6749 7.14188 12.4839 7.14188 11.026C7.14188 9.56816 8.19284 8.3771 9.51636 8.3771C10.8399 8.3771 11.912 9.56816 11.8908 11.026C11.8908 12.4839 10.8399 13.6749 9.51636 13.6749ZM18.0051 13.6749C16.7028 13.6749 15.6306 12.4839 15.6306 11.026C15.6306 9.56816 16.6815 8.3771 18.0051 8.3771C19.3286 8.3771 20.4008 9.56816 20.3796 11.026C20.3796 12.4839 19.3286 13.6749 18.0051 13.6749Z"/></svg>
</a>
<hr style="width: 32px; border-color: #35363c; margin: 4px 0;">
<?php foreach($servers as $s): ?>
<a href="?server_id=<?php echo $s['id']; ?>"
class="server-icon <?php echo $s['id'] == $active_server_id ? 'active' : ''; ?>"
title="<?php echo htmlspecialchars($s['name']); ?>">
<?php echo mb_substr($s['name'], 0, 1); ?>
</a>
<?php endforeach; ?>
<a href="#" class="server-icon add-btn" title="Add a Server" data-bs-toggle="modal" data-bs-target="#addServerModal">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
</a>
</div>
<!-- Channels Sidebar -->
<div class="channels-sidebar">
<div class="channels-header">
<?php
$active_server_name = 'Server';
foreach($servers as $s) if($s['id'] == $active_server_id) $active_server_name = $s['name'];
echo htmlspecialchars($active_server_name);
?>
</div>
<div class="channels-list">
<div class="channel-category">
<span>Text Channels</span>
<span class="add-channel-btn" title="Create Channel" data-bs-toggle="modal" data-bs-target="#addChannelModal" data-type="text">+</span>
</div>
<?php foreach($channels as $c): if($c['type'] !== 'text') continue; ?>
<a href="?server_id=<?php echo $active_server_id; ?>&channel_id=<?php echo $c['id']; ?>"
class="channel-item <?php echo $c['id'] == $active_channel_id ? 'active' : ''; ?>">
<?php echo htmlspecialchars($c['name']); ?>
</a>
<?php endforeach; ?>
<div class="channel-category" style="margin-top: 16px;">
<span>Voice Channels</span>
<span class="add-channel-btn" title="Create Channel" data-bs-toggle="modal" data-bs-target="#addChannelModal" data-type="voice">+</span>
</div>
<?php foreach($channels as $c): if($c['type'] !== 'voice') continue; ?>
<div class="channel-item voice-item" data-channel-id="<?php echo $c['id']; ?>">
<?php echo htmlspecialchars($c['name']); ?>
</div>
<?php endforeach; ?>
</div>
<div class="user-panel">
<div class="user-info">
<div class="message-avatar" style="width: 32px; height: 32px;"></div>
<div style="flex: 1; min-width: 0;">
<div style="font-weight: bold; font-size: 0.85em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
<?php echo htmlspecialchars($user['username']); ?>
</div>
<div style="color: var(--text-muted); font-size: 0.75em;">#<?php echo str_pad($user['id'], 4, '0', STR_PAD_LEFT); ?></div>
</div>
</div>
<div class="user-actions">
<a href="auth/logout.php" title="Logout" style="color: var(--text-muted);"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg></a>
</div>
</div>
<div style="padding: 10px; font-size: 10px; color: #4e5058; border-top: 1px solid #1e1f22;">
PHP <?php echo PHP_VERSION; ?> | <?php echo date('H:i'); ?>
</div>
</div>
<!-- Chat Area -->
<div class="chat-container">
<div class="chat-header">
<span style="color: var(--text-muted); margin-right: 8px;">#</span>
<?php echo htmlspecialchars($current_channel_name); ?>
</div>
<div class="messages-list" id="messages-list">
<?php if(empty($messages)): ?>
<div style="text-align: center; color: var(--text-muted); margin-top: 40px;">
<h4>Welcome to #<?php echo htmlspecialchars($current_channel_name); ?>!</h4>
<p>This is the start of the #<?php echo htmlspecialchars($current_channel_name); ?> channel.</p>
</div>
<?php endif; ?>
<?php foreach($messages as $m): ?>
<div class="message-item">
<div class="message-avatar"></div>
<div class="message-content">
<div class="message-author">
<?php echo htmlspecialchars($m['username']); ?>
<span class="message-time"><?php echo date('H:i', strtotime($m['created_at'])); ?></span>
</div>
<div class="message-text">
<?php echo nl2br(htmlspecialchars($m['content'])); ?>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
<div class="chat-input-container">
<form id="chat-form">
<div class="chat-input-wrapper">
<input type="text" id="chat-input" class="chat-input" placeholder="Message #<?php echo htmlspecialchars($current_channel_name); ?>" autocomplete="off">
</div>
</form>
</div>
</div>
<!-- Members Sidebar -->
<div class="members-sidebar">
<div style="color: var(--text-muted); font-size: 0.75em; text-transform: uppercase; font-weight: bold; margin-bottom: 16px;">
Members — <?php echo count($members); ?>
</div>
<?php foreach($members as $m): ?>
<div class="channel-item" style="color: var(--text-primary); margin-bottom: 8px;">
<div class="message-avatar" style="width: 32px; height: 32px; background-color: <?php echo $m['status'] == 'online' ? '#23a559' : '#80848e'; ?>; position: relative;">
<?php if($m['status'] == 'online'): ?>
<div style="position: absolute; bottom: 0; right: 0; width: 10px; height: 10px; background-color: #23a559; border-radius: 50%; border: 2px solid var(--bg-members);"></div>
<?php endif; ?>
</div>
<span style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
<?php echo htmlspecialchars($m['username']); ?>
</span>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- Add Server Modal -->
<div class="modal fade" id="addServerModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Create or Join a server</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body p-0">
<ul class="nav nav-tabs nav-fill" id="serverTabs" role="tablist">
<li class="nav-item">
<button class="nav-link active text-white border-0 bg-transparent" id="create-tab" data-bs-toggle="tab" data-bs-target="#create-pane" type="button">Create</button>
</li>
<li class="nav-item">
<button class="nav-link text-white border-0 bg-transparent" id="join-tab" data-bs-toggle="tab" data-bs-target="#join-pane" type="button">Join</button>
</li>
</ul>
<div class="tab-content p-3">
<div class="tab-pane fade show active" id="create-pane">
<form action="api_v1_servers.php" method="POST">
<p style="color: var(--text-muted); font-size: 0.9em;">Give your new server a personality with a name.</p>
<div class="mb-3">
<label class="form-label text-uppercase fw-bold" style="font-size: 0.7em; color: var(--text-muted);">Server Name</label>
<input type="text" name="name" class="form-control" placeholder="My Awesome Server" required>
</div>
<button type="submit" class="btn btn-primary w-100" style="background-color: var(--blurple); border: none;">Create Server</button>
</form>
</div>
<div class="tab-pane fade" id="join-pane">
<form action="api_v1_servers.php" method="POST">
<input type="hidden" name="action" value="join">
<p style="color: var(--text-muted); font-size: 0.9em;">Enter an invite code to join an existing server.</p>
<div class="mb-3">
<label class="form-label text-uppercase fw-bold" style="font-size: 0.7em; color: var(--text-muted);">Invite Code</label>
<input type="text" name="invite_code" class="form-control" placeholder="GEN-123" required>
</div>
<button type="submit" class="btn btn-success w-100" style="background-color: #23a559; border: none;">Join Server</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Add Channel Modal -->
<div class="modal fade" id="addChannelModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Create Channel</h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<form action="api_v1_channels.php" method="POST">
<input type="hidden" name="server_id" value="<?php echo $active_server_id; ?>">
<input type="hidden" name="type" id="channel-type-input" value="text">
<div class="modal-body">
<div class="mb-3">
<label class="form-label text-uppercase fw-bold" style="font-size: 0.7em; color: var(--text-muted);">Channel Name</label>
<div class="input-group">
<span class="input-group-text bg-dark border-0 text-muted" id="channel-hash-prefix">#</span>
<input type="text" name="name" class="form-control" placeholder="new-channel" required>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-link text-white text-decoration-none" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary" style="background-color: var(--blurple); border: none; padding: 10px 24px;">Create Channel</button>
</div>
</form>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script src="assets/js/voice.js?v=<?php echo time(); ?>"></script>
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
<script>
// Handle channel type in modal
document.querySelectorAll('.add-channel-btn').forEach(btn => {
btn.addEventListener('click', function() {
const type = this.getAttribute('data-type');
document.getElementById('channel-type-input').value = type;
document.getElementById('channel-hash-prefix').textContent = type === 'text' ? '#' : '🔊';
});
});
</script>
</body>
</html>