Autosave: 20260219-121958

This commit is contained in:
Flatlogic Bot 2026-02-19 12:19:59 +00:00
parent 19b2a3e8d6
commit 430d57545f
7 changed files with 242 additions and 21 deletions

View File

@ -206,6 +206,18 @@ if (!Permissions::canSendInChannel($user_id, $channel_id)) {
exit;
}
// Check if thread is locked
if ($thread_id) {
$stmtThread = db()->prepare("SELECT is_locked, channel_id, server_id FROM forum_threads t JOIN channels c ON t.channel_id = c.id WHERE t.id = ?");
$stmtThread->execute([$thread_id]);
$threadData = $stmtThread->fetch();
if ($threadData && $threadData['is_locked']) {
// Strict lock: no one can post, not even admins. Admins must unlock first.
echo json_encode(['success' => false, 'error' => 'This thread is locked. Messages are disabled.']);
exit;
}
}
if (!empty($content)) {
$moderation = moderateContent($content);
if (!$moderation['is_safe']) {
@ -231,6 +243,12 @@ try {
$stmt->execute([$channel_id, $thread_id, $user_id, $content, $attachment_url, $metadata]);
$last_id = db()->lastInsertId();
// Update last activity for forum threads
if ($thread_id) {
$stmtActivity = db()->prepare("UPDATE forum_threads SET last_activity_at = CURRENT_TIMESTAMP WHERE id = ?");
$stmtActivity->execute([$thread_id]);
}
// Enforce message limit if set
enforceChannelLimit($channel_id);

View File

@ -1,6 +1,7 @@
<?php
header('Content-Type: application/json');
require_once 'auth/session.php';
require_once 'includes/permissions.php';
requireLogin();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
@ -13,7 +14,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
exit;
}
require_once 'includes/permissions.php';
if (!Permissions::canSendInChannel($user_id, $channel_id)) {
echo json_encode(['success' => false, 'error' => 'You do not have permission to create threads in this channel.']);
exit;
@ -45,10 +45,16 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'PATCH' || (isset($_GET['action']) && $_GET['action'] === 'solve')) {
if ($_SERVER['REQUEST_METHOD'] === 'PATCH' || $_SERVER['REQUEST_METHOD'] === 'DELETE' || (isset($_GET['action']) && in_array($_GET['action'], ['solve', 'pin', 'unpin', 'lock', 'unlock', 'delete']))) {
$data = json_decode(file_get_contents('php://input'), true) ?? $_POST;
$thread_id = $data['thread_id'] ?? 0;
$message_id = $data['message_id'] ?? null; // null to unsolve
$thread_id = $data['thread_id'] ?? $_GET['thread_id'] ?? 0;
$message_id = $data['message_id'] ?? null;
$action = $_GET['action'] ?? $data['action'] ?? 'solve';
if ($_SERVER['REQUEST_METHOD'] === 'DELETE') {
$action = 'delete';
}
$user_id = $_SESSION['user_id'];
if (!$thread_id) {
@ -70,14 +76,45 @@ if ($_SERVER['REQUEST_METHOD'] === 'PATCH' || (isset($_GET['action']) && $_GET['
$stmtServer->execute([$thread['server_id']]);
$server = $stmtServer->fetch();
if ($thread['user_id'] != $user_id && $server['owner_id'] != $user_id) {
$is_admin = Permissions::hasPermission($user_id, $thread['server_id'], Permissions::ADMINISTRATOR) ||
Permissions::hasPermission($user_id, $thread['server_id'], Permissions::MANAGE_SERVER) ||
Permissions::hasPermission($user_id, $thread['server_id'], Permissions::MANAGE_MESSAGES) ||
$server['owner_id'] == $user_id;
if ($thread['user_id'] != $user_id && !$is_admin) {
echo json_encode(['success' => false, 'error' => 'Unauthorized']);
exit;
}
try {
$stmt = db()->prepare("UPDATE forum_threads SET solution_message_id = ? WHERE id = ?");
$stmt->execute([$message_id, $thread_id]);
if ($action === 'solve') {
$stmt = db()->prepare("UPDATE forum_threads SET solution_message_id = ? WHERE id = ?");
$stmt->execute([$message_id, $thread_id]);
} elseif ($action === 'pin') {
$stmt = db()->prepare("UPDATE forum_threads SET is_pinned = 1 WHERE id = ?");
$stmt->execute([$thread_id]);
} elseif ($action === 'unpin') {
$stmt = db()->prepare("UPDATE forum_threads SET is_pinned = 0 WHERE id = ?");
$stmt->execute([$thread_id]);
} elseif ($action === 'lock') {
$stmt = db()->prepare("UPDATE forum_threads SET is_locked = 1 WHERE id = ?");
$stmt->execute([$thread_id]);
} elseif ($action === 'unlock') {
$stmt = db()->prepare("UPDATE forum_threads SET is_locked = 0 WHERE id = ?");
$stmt->execute([$thread_id]);
} elseif ($action === 'delete') {
db()->beginTransaction();
// Delete associated tags
$stmt = db()->prepare("DELETE FROM thread_tags WHERE thread_id = ?");
$stmt->execute([$thread_id]);
// Delete associated messages
$stmt = db()->prepare("DELETE FROM messages WHERE thread_id = ?");
$stmt->execute([$thread_id]);
// Delete thread
$stmt = db()->prepare("DELETE FROM forum_threads WHERE id = ?");
$stmt->execute([$thread_id]);
db()->commit();
}
echo json_encode(['success' => true]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);

View File

@ -2219,6 +2219,62 @@ document.addEventListener('DOMContentLoaded', () => {
manageTagsModal.show();
});
// Forum Thread Actions (Pin/Lock)
const pinThreadBtn = document.getElementById('toggle-pin-thread');
pinThreadBtn?.addEventListener('click', async () => {
const id = pinThreadBtn.dataset.id;
const pinned = pinThreadBtn.dataset.pinned == '1';
const action = pinned ? 'unpin' : 'pin';
try {
const resp = await fetch(`api_v1_threads.php?action=${action}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ thread_id: id })
});
const result = await resp.json();
if (result.success) location.reload();
else alert(result.error || 'Failed to update thread');
} catch (e) { console.error(e); }
});
const lockThreadBtn = document.getElementById('toggle-lock-thread');
lockThreadBtn?.addEventListener('click', async () => {
const id = lockThreadBtn.dataset.id;
const locked = lockThreadBtn.dataset.locked == '1';
const action = locked ? 'unlock' : 'lock';
try {
const resp = await fetch(`api_v1_threads.php?action=${action}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ thread_id: id })
});
const result = await resp.json();
if (result.success) location.reload();
else alert(result.error || 'Failed to update thread');
} catch (e) { console.error(e); }
});
const deleteThreadBtn = document.getElementById('delete-thread-btn');
deleteThreadBtn?.addEventListener('click', async () => {
if (!confirm('Are you sure you want to delete this thread? This action cannot be undone.')) return;
const id = deleteThreadBtn.dataset.id;
const channelId = deleteThreadBtn.dataset.channelId;
const serverId = deleteThreadBtn.dataset.serverId;
try {
const resp = await fetch(`api_v1_threads.php?action=delete`, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ thread_id: id })
});
const result = await resp.json();
if (result.success) {
location.href = `?server_id=${serverId}&channel_id=${channelId}`;
} else {
alert(result.error || 'Failed to delete thread');
}
} catch (e) { console.error(e); }
});
async function loadForumAdminTags() {
const list = document.getElementById('forum-tags-admin-list');
list.innerHTML = '<div class="text-center p-3 text-muted small">Loading tags...</div>';

View File

@ -1 +1 @@
{"1707c6672074b09b":{"id":"1707c6672074b09b","user_id":3,"name":"swefheim","avatar_url":"","last_seen":1771447993891,"is_muted":1,"is_deafened":0}}
[]

View File

@ -0,0 +1,7 @@
-- Add pinned, locked and activity tracking to forum threads
ALTER TABLE forum_threads ADD COLUMN is_pinned TINYINT(1) NOT NULL DEFAULT 0;
ALTER TABLE forum_threads ADD COLUMN is_locked TINYINT(1) NOT NULL DEFAULT 0;
ALTER TABLE forum_threads ADD COLUMN last_activity_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
-- Initialize last_activity_at with created_at for existing threads
UPDATE forum_threads SET last_activity_at = created_at;

View File

@ -228,7 +228,10 @@ if ($is_dm_view) {
$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;
$can_manage_server = Permissions::hasPermission($current_user_id, $active_server_id, Permissions::MANAGE_SERVER) ||
Permissions::hasPermission($current_user_id, $active_server_id, Permissions::MANAGE_MESSAGES) ||
Permissions::hasPermission($current_user_id, $active_server_id, Permissions::ADMINISTRATOR) ||
$is_owner;
break;
}
}
@ -279,14 +282,13 @@ if ($is_dm_view) {
$stmt = db()->prepare("
SELECT t.*, u.display_name as username, u.username as login_name, 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
ORDER BY t.is_pinned DESC, t.last_activity_at DESC, t.created_at DESC
");
$stmt->execute([$active_server_id, $active_server_id, $active_channel_id]);
$threads = $stmt->fetchAll();
@ -708,8 +710,27 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
<div class="messages-list" id="messages-list">
<?php if($active_thread): ?>
<div class="thread-view-container p-4">
<a href="?server_id=<?php echo $active_server_id; ?>&channel_id=<?php echo $active_channel_id; ?><?php echo isset($_GET['status']) ? '&status='.htmlspecialchars($_GET['status']) : ''; ?>" class="btn btn-sm btn-outline-secondary mb-3"> Back to Forum</a>
<h3>Discussion: <?php echo htmlspecialchars($active_thread['title']); ?></h3>
<div class="d-flex justify-content-between align-items-center mb-3">
<a href="?server_id=<?php echo $active_server_id; ?>&channel_id=<?php echo $active_channel_id; ?><?php echo isset($_GET['status']) ? '&status='.htmlspecialchars($_GET['status']) : ''; ?>" class="btn btn-sm btn-outline-secondary"> Back to Forum</a>
<?php if ($active_thread['user_id'] == $current_user_id || $can_manage_server): ?>
<div class="d-flex gap-2">
<button class="btn btn-sm <?php echo $active_thread['is_pinned'] ? 'btn-primary' : 'btn-outline-primary'; ?>" id="toggle-pin-thread" data-id="<?php echo $active_thread['id']; ?>" data-pinned="<?php echo $active_thread['is_pinned']; ?>">
<i class="fa-solid fa-thumbtack me-1"></i> <?php echo $active_thread['is_pinned'] ? 'Unpin' : 'Pin'; ?>
</button>
<button class="btn btn-sm <?php echo $active_thread['is_locked'] ? 'btn-warning' : 'btn-outline-warning'; ?>" id="toggle-lock-thread" data-id="<?php echo $active_thread['id']; ?>" data-locked="<?php echo $active_thread['is_locked']; ?>">
<i class="fa-solid <?php echo $active_thread['is_locked'] ? 'fa-unlock' : 'fa-lock'; ?> me-1"></i> <?php echo $active_thread['is_locked'] ? 'Unlock' : 'Lock'; ?>
</button>
<button class="btn btn-sm btn-outline-danger" id="delete-thread-btn" data-id="<?php echo $active_thread['id']; ?>" data-channel-id="<?php echo $active_channel_id; ?>" data-server-id="<?php echo $active_server_id; ?>">
<i class="fa-solid fa-trash me-1"></i> Delete
</button>
</div>
<?php endif; ?>
</div>
<h3>
<?php if($active_thread['is_pinned']): ?><i class="fa-solid fa-thumbtack text-primary me-2 small"></i><?php endif; ?>
<?php if($active_thread['is_locked']): ?><i class="fa-solid fa-lock text-warning me-2 small"></i><?php endif; ?>
Discussion: <?php echo htmlspecialchars($active_thread['title']); ?>
</h3>
<?php
// Fetch tags for this thread
$stmt_t = db()->prepare("SELECT ft.* FROM forum_tags ft JOIN thread_tags tt ON ft.id = tt.tag_id WHERE tt.thread_id = ?");
@ -917,13 +938,24 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
<div class="text-center text-muted mt-5">No discussions yet. Start one!</div>
<?php endif; ?>
<?php foreach($threads as $thread): ?>
<a href="?server_id=<?php echo $active_server_id; ?>&channel_id=<?php echo $active_channel_id; ?>&thread_id=<?php echo $thread['id']; ?><?php echo isset($_GET['status']) ? '&status='.htmlspecialchars($_GET['status']) : ''; ?>" class="thread-item d-flex align-items-center p-3 mb-2 rounded bg-dark text-decoration-none text-white border-start border-4 border-secondary">
<div class="thread-icon me-3">💬</div>
<a href="?server_id=<?php echo $active_server_id; ?>&channel_id=<?php echo $active_channel_id; ?>&thread_id=<?php echo $thread['id']; ?><?php echo isset($_GET['status']) ? '&status='.htmlspecialchars($_GET['status']) : ''; ?>" class="thread-item d-flex align-items-center p-3 mb-2 rounded bg-dark text-decoration-none text-white border-start border-4 <?php echo $thread['is_pinned'] ? 'border-primary' : 'border-secondary'; ?>">
<div class="thread-icon me-3">
<?php if($thread['is_pinned']): ?>
<i class="fa-solid fa-thumbtack text-primary"></i>
<?php elseif($thread['is_locked']): ?>
<i class="fa-solid fa-lock text-warning"></i>
<?php else: ?>
💬
<?php endif; ?>
</div>
<div class="thread-info flex-grow-1">
<div class="thread-title fw-bold">
<?php if($thread['solution_message_id']): ?>
<span class="text-success me-1" title="Solved"></span>
<?php endif; ?>
<?php if($thread['is_locked'] && !$thread['is_pinned']): ?>
<i class="fa-solid fa-lock small me-1 text-muted"></i>
<?php endif; ?>
<?php echo htmlspecialchars($thread['title']); ?>
<?php if($thread['tags']):
$tag_list = explode('|', $thread['tags']);
@ -940,8 +972,8 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
</div>
</div>
<div class="thread-activity text-end small text-muted">
<?php if($thread['last_activity']): ?>
Last active: <?php echo date('H:i', strtotime($thread['last_activity'])); ?>
<?php if($thread['last_activity_at']): ?>
Last active: <?php echo date('H:i', strtotime($thread['last_activity_at'])); ?>
<?php endif; ?>
</div>
</a>
@ -1097,17 +1129,21 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
<form id="chat-form" enctype="multipart/form-data">
<div class="chat-input-wrapper">
<?php if ($allow_files): ?>
<label for="file-upload" class="upload-btn-label" title="Upload File">
<label for="file-upload" class="upload-btn-label" title="Upload File" <?php echo (isset($active_thread) && $active_thread['is_locked']) ? 'style="opacity: 0.3; cursor: not-allowed;"' : ''; ?>>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>
</label>
<input type="file" id="file-upload" style="display: none;">
<input type="file" id="file-upload" style="display: none;" <?php echo (isset($active_thread) && $active_thread['is_locked']) ? 'disabled' : ''; ?>>
<?php else: ?>
<div class="upload-btn-label disabled" title="File sharing disabled" style="opacity: 0.3; cursor: not-allowed;">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="8" y1="8" x2="16" y2="16"></line><line x1="16" y1="8" x2="8" y2="16"></line></svg>
</div>
<?php endif; ?>
<textarea id="chat-input" class="chat-input" placeholder="Message #<?php echo htmlspecialchars($current_channel_name); ?>" autocomplete="off" rows="1"></textarea>
<button type="button" class="btn border-0 text-muted p-2" id="chat-emoji-btn" title="Emoji Picker">
<?php if (isset($active_thread) && $active_thread['is_locked']): ?>
<textarea id="chat-input" class="chat-input" placeholder="This discussion is locked." autocomplete="off" rows="1" disabled style="background-color: rgba(0,0,0,0.1); cursor: not-allowed;"></textarea>
<?php else: ?>
<textarea id="chat-input" class="chat-input" placeholder="Message #<?php echo htmlspecialchars($current_channel_name); ?>" autocomplete="off" rows="1"></textarea>
<?php endif; ?>
<button type="button" class="btn border-0 text-muted p-2" id="chat-emoji-btn" title="Emoji Picker" <?php echo (isset($active_thread) && $active_thread['is_locked']) ? 'disabled style="opacity: 0.5;"' : ''; ?>>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><path d="M8 14s1.5 2 4 2 4-2 4-2"></path><line x1="9" y1="9" x2="9.01" y2="9"></line><line x1="15" y1="9" x2="15.01" y2="9"></line></svg>
</button>
</div>

View File

@ -715,3 +715,70 @@
2026-02-18 20:58:54 - GET /index.php?server_id=1&channel_id=15 - POST: []
2026-02-18 21:00:09 - GET /?fl_project=38443 - POST: []
2026-02-18 21:08:02 - GET /?fl_project=38443 - POST: []
2026-02-18 22:31:51 - GET /index.php?server_id=1&channel_id=15 - POST: []
2026-02-18 22:32:17 - GET /index.php - POST: []
{"date":"2026-02-18 22:32:48","method":"POST","post":{"avatar_url":"","display_name":"swefpifh \u1d47\u02b0\u1da0\u02b3","theme":"dark","voice_input_device":"OPTIyYzx3bNI0gtW62vaTCb7SxzY5rNnwOw5G42w36M=","voice_output_device":"znHy1zh6U7iZkBs7ovKSXvb3r4k0jk0DBbg\/TtaWmwk=","voice_input_volume":"1","voice_output_volume":"1","voice_echo_cancellation":"1","voice_noise_suppression":"1","voice_mode":"vox","voice_ptt_key":"v","voice_vox_threshold":"0.17","dnd_mode":"1","sound_notifications":"1"},"session":{"user_id":2},"user_id":2,"db_success":true}
2026-02-19 00:21:00 - GET /index.php - POST: []
2026-02-19 11:31:34 - GET /index.php - POST: []
2026-02-19 11:33:16 - GET /?fl_project=38443 - POST: []
2026-02-19 11:45:34 - GET /index.php - POST: []
2026-02-19 11:45:58 - GET /index.php?server_id=3 - POST: []
2026-02-19 11:54:36 - GET /?fl_project=38443 - POST: []
2026-02-19 11:58:54 - GET /?fl_project=38443 - POST: []
2026-02-19 12:03:16 - GET / - POST: []
2026-02-19 12:03:36 - GET /?fl_project=38443 - POST: []
2026-02-19 12:03:56 - GET /index.php - POST: []
2026-02-19 12:03:58 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:04:13 - GET /index.php?server_id=1&channel_id=13&thread_id=1 - POST: []
2026-02-19 12:04:26 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:04:36 - GET /index.php?server_id=1&channel_id=13&thread_id=1 - POST: []
2026-02-19 12:04:45 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:05:21 - GET /index.php?server_id=1&channel_id=13&thread_id=1 - POST: []
2026-02-19 12:05:25 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:05:28 - GET /index.php?server_id=1&channel_id=13&thread_id=1 - POST: []
2026-02-19 12:05:33 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:05:47 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
2026-02-19 12:05:49 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:06:00 - GET /index.php?server_id=1&channel_id=13&thread_id=1 - POST: []
2026-02-19 12:06:08 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:06:31 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
2026-02-19 12:06:44 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:06:52 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
2026-02-19 12:07:05 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:07:19 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
2026-02-19 12:07:39 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:07:41 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
2026-02-19 12:13:43 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
2026-02-19 12:15:17 - GET / - POST: []
2026-02-19 12:15:50 - GET /?fl_project=38443 - POST: []
2026-02-19 12:15:53 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:15:57 - GET /index.php?server_id=1&channel_id=13&thread_id=1 - POST: []
2026-02-19 12:16:00 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:16:03 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
2026-02-19 12:16:05 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
2026-02-19 12:16:07 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:16:27 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
2026-02-19 12:16:30 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:16:44 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
2026-02-19 12:16:48 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
2026-02-19 12:16:49 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:16:55 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
2026-02-19 12:16:57 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
2026-02-19 12:16:58 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:17:01 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:17:05 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
2026-02-19 12:17:12 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:17:13 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
2026-02-19 12:17:38 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:17:49 - GET /index.php?server_id=1&channel_id=18 - POST: []
2026-02-19 12:17:50 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:18:00 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
2026-02-19 12:18:02 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:18:04 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
2026-02-19 12:18:09 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:18:11 - GET /index.php?server_id=1&channel_id=13&thread_id=4 - POST: []
2026-02-19 12:18:15 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:18:29 - GET /index.php?server_id=1&channel_id=13&thread_id=2 - POST: []
2026-02-19 12:18:33 - GET /index.php?server_id=1&channel_id=13 - POST: []
2026-02-19 12:18:58 - GET /index.php?server_id=1&channel_id=13&thread_id=3 - POST: []
2026-02-19 12:19:02 - GET /index.php?server_id=1&channel_id=13 - POST: []