';
} elseif ($isFa) {
return '';
} elseif ($isCustomEmote) {
// Fetch emote path
static $ce_icons_cache;
if ($ce_icons_cache === null) {
try { $ce_icons_cache = db()->query("SELECT code, path FROM custom_emotes")->fetchAll(PDO::FETCH_KEY_PAIR); } catch (Exception $e) { $ce_icons_cache = []; }
}
if (isset($ce_icons_cache[$icon])) {
return '';
}
return '' . htmlspecialchars($icon) . '';
} else {
return '' . htmlspecialchars($icon) . '';
}
}
// Helper to parse emotes in content
function parse_emotes($content) {
static $custom_emotes_cache;
if ($custom_emotes_cache === null) {
try {
$custom_emotes_cache = db()->query("SELECT name, path, code FROM custom_emotes")->fetchAll();
} catch (Exception $e) {
$custom_emotes_cache = [];
}
}
$result = htmlspecialchars($content);
foreach ($custom_emotes_cache as $ce) {
$emote_html = '
';
$result = str_replace($ce['code'], $emote_html, $result);
}
return $result;
}
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();
$is_dm_view = (isset($_GET['server_id']) && $_GET['server_id'] == 'dms') || !isset($_GET['server_id']) && empty($servers);
if ($is_dm_view) {
$active_server_id = 'dms';
// Fetch DM channels
$stmt = db()->prepare("
SELECT c.id, u.username as other_user, u.avatar_url, u.status, u.id as other_user_id
FROM channels c
JOIN channel_members cm1 ON c.id = cm1.channel_id
JOIN channel_members cm2 ON c.id = cm2.channel_id
JOIN users u ON cm2.user_id = u.id
WHERE c.type = 'dm' AND cm1.user_id = ? AND cm2.user_id != ?
");
$stmt->execute([$current_user_id, $current_user_id]);
$dm_channels = $stmt->fetchAll();
$active_channel_id = $_GET['channel_id'] ?? ($dm_channels[0]['id'] ?? 0);
$channel_theme = null; // DMs don't have custom themes for now
if ($active_channel_id) {
// Fetch DM 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 = 'Direct Message';
foreach($dm_channels as $dm) {
if ($dm['id'] == $active_channel_id) {
$current_channel_name = $dm['other_user'];
break;
}
}
} else {
$messages = [];
$current_channel_name = 'Direct Messages';
}
$channels = [];
$members = []; // Members list is different for DMs or hidden
} else {
$active_server_id = $_GET['server_id'] ?? ($servers[0]['id'] ?? 1);
// Fetch channels
$stmt = db()->prepare("SELECT * FROM channels WHERE server_id = ? ORDER BY position ASC, id ASC");
$stmt->execute([$active_server_id]);
$all_channels = $stmt->fetchAll();
require_once 'includes/permissions.php';
$channels = [];
foreach($all_channels as $c) {
if (Permissions::canViewChannel($current_user_id, $c['id'])) {
$channels[] = $c;
}
}
$active_channel_id = $_GET['channel_id'] ?? ($channels[0]['id'] ?? 0);
// Fetch active channel details for theme
$active_channel = null;
foreach($channels as $c) {
if($c['id'] == $active_channel_id) {
$active_channel = $c;
break;
}
}
$is_owner = false;
$can_manage_channels = false;
$can_manage_server = false;
$active_server = null;
foreach($servers as $s) {
if($s['id'] == $active_server_id) {
$active_server = $s;
$is_owner = ($s['owner_id'] == $current_user_id);
$can_manage_channels = Permissions::hasPermission($current_user_id, $active_server_id, Permissions::MANAGE_CHANNELS) || $is_owner;
$can_manage_server = Permissions::hasPermission($current_user_id, $active_server_id, Permissions::MANAGE_SERVER) || Permissions::hasPermission($current_user_id, $active_server_id, Permissions::ADMINISTRATOR) || $is_owner;
break;
}
}
$channel_theme = $active_server['theme_color'] ?? null;
$channel_type = $active_channel['type'] ?? 'chat';
$active_thread_id = $_GET['thread_id'] ?? null;
$active_thread = null;
if ($active_thread_id) {
$stmt = db()->prepare("SELECT t.*, u.username FROM forum_threads t JOIN users u ON t.user_id = u.id WHERE t.id = ?");
$stmt->execute([$active_thread_id]);
$active_thread = $stmt->fetch();
if ($active_thread) {
$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,
(SELECT r.icon_url 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_icon
FROM messages m
JOIN users u ON m.user_id = u.id
WHERE m.thread_id = ?
ORDER BY m.created_at ASC
");
$stmt->execute([$active_server_id, $active_server_id, $active_thread_id]);
$messages = $stmt->fetchAll();
}
}
if (!$active_thread && $channel_type === 'rules') {
$stmt = db()->prepare("SELECT * FROM channel_rules WHERE channel_id = ? ORDER BY position ASC");
$stmt->execute([$active_channel_id]);
$rules = $stmt->fetchAll();
} elseif ($channel_type === 'autorole') {
$stmt = db()->prepare("SELECT ca.*, r.name as role_name FROM channel_autoroles ca JOIN roles r ON ca.role_id = r.id WHERE ca.channel_id = ? ORDER BY ca.id ASC");
$stmt->execute([$active_channel_id]);
$autoroles = $stmt->fetchAll();
} elseif ($channel_type === 'forum') {
$filter_status = $_GET['status'] ?? 'all';
$status_where = "";
if ($filter_status === 'resolved') {
$status_where = " AND t.solution_message_id IS NOT NULL";
} elseif ($filter_status === 'unresolved') {
$status_where = " AND t.solution_message_id IS NULL";
}
$stmt = db()->prepare("
SELECT t.*, u.username, u.avatar_url,
(SELECT COUNT(*) FROM messages m WHERE m.thread_id = t.id) as message_count,
(SELECT MAX(created_at) FROM messages m WHERE m.thread_id = t.id) as last_activity,
(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,
(SELECT r.icon_url 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_icon,
(SELECT GROUP_CONCAT(CONCAT(ft.name, ':', ft.color) SEPARATOR '|') FROM thread_tags tt JOIN forum_tags ft ON tt.tag_id = ft.id WHERE tt.thread_id = t.id) as tags
FROM forum_threads t
JOIN users u ON t.user_id = u.id
WHERE t.channel_id = ? " . $status_where . "
ORDER BY last_activity DESC, t.created_at DESC
");
$stmt->execute([$active_server_id, $active_server_id, $active_channel_id]);
$threads = $stmt->fetchAll();
} else {
// Fetch messages
$display_limit = !empty($active_channel['message_limit']) ? (int)$active_channel['message_limit'] : 50;
$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,
(SELECT r.icon_url 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_icon
FROM messages m
JOIN users u ON m.user_id = u.id
WHERE m.channel_id = ?
ORDER BY m.created_at ASC
LIMIT " . $display_limit . "
");
$stmt->execute([$active_server_id, $active_server_id, $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.id, u.username, u.avatar_url, u.status,
(SELECT GROUP_CONCAT(r.id) FROM roles r JOIN user_roles ur ON r.id = ur.role_id WHERE ur.user_id = u.id AND r.server_id = ?) as role_ids,
(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,
(SELECT r.icon_url 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_icon
FROM users u
JOIN server_members sm ON u.id = sm.user_id
WHERE sm.server_id = ?
");
$stmt->execute([$active_server_id, $active_server_id, $active_server_id, $active_server_id]);
$all_server_members = $stmt->fetchAll();
$members = [];
foreach($all_server_members as $m) {
if (Permissions::canViewChannel($m['id'], $active_channel_id)) {
$members[] = $m;
}
}
// Fetch all server roles
$stmt = db()->prepare("SELECT * FROM roles WHERE server_id = ? ORDER BY position DESC");
$stmt->execute([$active_server_id]);
$server_roles = $stmt->fetchAll();
}
// SEO & Env tags
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Discord-like messaging app built with PHP';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
?>