This commit is contained in:
Lain Iwakura 2025-07-26 11:48:45 +03:00
parent d610bf7d7a
commit b99ec23bb5
No known key found for this signature in database
GPG Key ID: C7C18257F2ADC6F8
8 changed files with 578 additions and 1 deletions

View File

@ -16,6 +16,11 @@ COPY apache.conf /etc/apache2/sites-available/000-default.conf
RUN chown -R www-data:www-data /var/www/html \ RUN chown -R www-data:www-data /var/www/html \
&& chmod -R 755 /var/www/html/uploads && chmod -R 755 /var/www/html/uploads
COPY wait-for-db.php /usr/local/bin/
RUN chmod +x /usr/local/bin/wait-for-db.php
CMD ["sh", "-c", "php /usr/local/bin/wait-for-db.php && apache2-foreground"]
EXPOSE 65511 EXPOSE 65511
CMD ["apache2-foreground"] CMD ["apache2-foreground"]

View File

@ -168,8 +168,10 @@ function formatMessage($message) {
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>mkach - /<?= htmlspecialchars($boardId) ?>/</title> <title>mkach - /<?= htmlspecialchars($boardId) ?>/</title>
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
<script src="theme.js"></script>
</head> </head>
<body> <body>
<button class="theme-toggle" onclick="toggleTheme()">Включить темную тему</button>
<div class="container"> <div class="container">
<div class="header"> <div class="header">
<h1><a href="index.php" class="home-link">mkach</a> - /<?= htmlspecialchars($boardId) ?>/ - <?= htmlspecialchars($board['name']) ?></h1> <h1><a href="index.php" class="home-link">mkach</a> - /<?= htmlspecialchars($boardId) ?>/ - <?= htmlspecialchars($board['name']) ?></h1>

View File

@ -11,7 +11,7 @@ return [
'max_file_size' => 26214400, 'max_file_size' => 26214400,
'allowed_types' => ['jpg', 'jpeg', 'png', 'gif', 'webp','JPG','JPEG','PNG','GIF','WEBP'], 'allowed_types' => ['jpg', 'jpeg', 'png', 'gif', 'webp','JPG','JPEG','PNG','GIF','WEBP'],
'max_message_length' => 10000, 'max_message_length' => 10000,
'motd' => 'Добро пожаловать на mkach - анонимный имиджборд от МК', 'motd' => 'Добро пожаловать на mkach - анонимный имиджборд от МК. Темная тема в бета-тесте!',
'logo_enabled' => true, 'logo_enabled' => true,
'logo_text' => 'mkach', 'logo_text' => 'mkach',
'admin' => [ 'admin' => [

View File

@ -133,8 +133,10 @@ if (isset($_GET['logout'])) {
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>mkach - Доски</title> <title>mkach - Доски</title>
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
<script src="theme.js"></script>
</head> </head>
<body> <body>
<button class="theme-toggle" onclick="toggleTheme()">Включить темную тему</button>
<div class="container"> <div class="container">
<div class="header"> <div class="header">
<h1><?= $config['logo_enabled'] ? htmlspecialchars($config['logo_text']) : 'mkach' ?></h1> <h1><?= $config['logo_enabled'] ? htmlspecialchars($config['logo_text']) : 'mkach' ?></h1>

View File

@ -119,8 +119,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>mkach - Создать тред в /<?= htmlspecialchars($boardId) ?>/</title> <title>mkach - Создать тред в /<?= htmlspecialchars($boardId) ?>/</title>
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
<script src="theme.js"></script>
</head> </head>
<body> <body>
<button class="theme-toggle" onclick="toggleTheme()">Включить темную тему</button>
<div class="container"> <div class="container">
<div class="header"> <div class="header">
<h1><a href="index.php" class="home-link">mkach</a> - Создать тред в /<?= htmlspecialchars($boardId) ?>/</h1> <h1><a href="index.php" class="home-link">mkach</a> - Создать тред в /<?= htmlspecialchars($boardId) ?>/</h1>

View File

@ -507,3 +507,504 @@ body {
::-webkit-scrollbar-thumb:hover { ::-webkit-scrollbar-thumb:hover {
background: #c4a6a0; background: #c4a6a0;
} }
.post-message {
max-width: 300px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.theme-toggle {
position: fixed;
top: 20px;
right: 20px;
background: #f4d03f;
border: 2px solid #e67e22;
color: #8b4513;
padding: 8px 12px;
border-radius: 5px;
cursor: pointer;
font-weight: bold;
z-index: 1000;
transition: all 0.3s ease;
}
.theme-toggle:hover {
background: #f39c12;
transform: scale(1.05);
}
.dark-theme {
background: #1a1a1a;
color: #e0e0e0;
}
.dark-theme .header {
background: #2d2d2d;
border-bottom: 2px solid #444;
}
.dark-theme .header h1 {
color: #f4d03f;
}
.dark-theme .header a {
color: #f39c12;
}
.dark-theme .header a:hover {
color: #e67e22;
}
.dark-theme .container {
background: #2d2d2d;
border: 2px solid #444;
}
.dark-theme .board-list {
background: #333;
border: 1px solid #555;
}
.dark-theme .board-item {
background: #444;
border: 1px solid #666;
}
.dark-theme .board-item:hover {
background: #555;
}
.dark-theme .board-item a {
color: #f4d03f;
}
.dark-theme .threads-table {
background: #333;
border: 1px solid #555;
}
.dark-theme .threads-table th {
background: #444;
color: #f4d03f;
border-bottom: 2px solid #666;
}
.dark-theme .threads-table td {
border-bottom: 1px solid #555;
}
.dark-theme .thread-id {
color: #f39c12;
}
.dark-theme .thread-title {
color: #e0e0e0;
}
.dark-theme .thread-title a {
color: #f4d03f;
}
.dark-theme .thread-title a:hover {
color: #f39c12;
}
.dark-theme .posts-container {
background: #333;
border: 1px solid #555;
}
.dark-theme .post {
background: #444;
border: 1px solid #666;
}
.dark-theme .post-header {
background: #555;
border-bottom: 1px solid #777;
}
.dark-theme .post-id {
color: #f39c12;
}
.dark-theme .post-time {
color: #aaa;
}
.dark-theme .post-content {
color: #e0e0e0;
}
.dark-theme .post-image {
border: 1px solid #666;
}
.dark-theme .form-container {
background: #333;
border: 1px solid #555;
}
.dark-theme .form-row {
border-bottom: 1px solid #555;
}
.dark-theme .form-row:last-child {
border-bottom: none;
}
.dark-theme input[type="text"],
.dark-theme input[type="password"],
.dark-theme textarea {
background: #444;
border: 1px solid #666;
color: #e0e0e0;
}
.dark-theme input[type="text"]:focus,
.dark-theme input[type="password"]:focus,
.dark-theme textarea:focus {
border-color: #f39c12;
outline: none;
}
.dark-theme .btn {
background: #f4d03f;
border: 2px solid #e67e22;
color: #8b4513;
}
.dark-theme .btn:hover {
background: #f39c12;
}
.dark-theme .new-thread-btn {
background: #f4d03f;
border: 2px solid #e67e22;
color: #8b4513;
}
.dark-theme .new-thread-btn:hover {
background: #f39c12;
}
.dark-theme .error {
background: #4a2c2c;
border: 1px solid #8b4513;
color: #ff6b6b;
}
.dark-theme .success {
background: #2c4a2c;
border: 1px solid #4a8b4a;
color: #6bff6b;
}
.dark-theme .motd {
background: #333;
border: 1px solid #555;
color: #f4d03f;
}
.dark-theme .admin-panel {
background: #333;
border: 1px solid #555;
}
.dark-theme .admin-panel h1,
.dark-theme .admin-panel h2 {
color: #f4d03f;
}
.dark-theme .delete-btn {
background: #8b4513;
border: 2px solid #a0522d;
color: #fff;
}
.dark-theme .delete-btn:hover {
background: #a0522d;
}
.dark-theme .theme-toggle {
background: #f4d03f;
border: 2px solid #e67e22;
color: #8b4513;
}
.dark-theme .theme-toggle:hover {
background: #f39c12;
}
.dark-theme .boards-container {
background: #333;
border: 1px solid #555;
}
.dark-theme .boards-container h2 {
color: #f4d03f;
}
.dark-theme .board-item {
background: #444;
border: 1px solid #666;
}
.dark-theme .board-item:hover {
background: #555;
}
.dark-theme .board-link {
color: #e0e0e0;
}
.dark-theme .board-id {
color: #f39c12;
}
.dark-theme .board-name {
color: #f4d03f;
}
.dark-theme .board-desc {
color: #aaa;
}
.dark-theme .motd-container {
background: #333;
border: 1px solid #555;
}
.dark-theme .thread-container {
background: #333;
border: 1px solid #555;
}
.dark-theme .thread-header {
background: #444;
border-bottom: 1px solid #666;
}
.dark-theme .thread-header h2 {
color: #f4d03f;
}
.dark-theme .back-link {
color: #f39c12;
}
.dark-theme .back-link:hover {
color: #e67e22;
}
.dark-theme .threads-container {
background: #333;
border: 1px solid #555;
}
.dark-theme .threads-list {
background: #333;
}
.dark-theme .thread-item {
background: #444;
border: 1px solid #666;
}
.dark-theme .thread-item:hover {
background: #555;
}
.dark-theme .thread-link {
color: #f4d03f;
}
.dark-theme .thread-title {
color: #e0e0e0;
}
.dark-theme .thread-info {
color: #aaa;
}
.dark-theme .thread-file {
border: 1px solid #666;
}
.dark-theme .thread-image {
border: 1px solid #666;
}
.dark-theme .thread-description {
color: #e0e0e0;
background: #444;
border: 1px solid #666;
padding: 8px;
margin: 5px 0;
}
.dark-theme .anonymous-id {
color: #f39c12;
}
.dark-theme .new-thread-button {
background: #333;
border: 1px solid #555;
}
.dark-theme .new-thread-container {
background: #333;
border: 1px solid #555;
}
.dark-theme .thread-form {
background: #333;
border: 1px solid #555;
}
.dark-theme .thread-form h2 {
color: #f4d03f;
}
.dark-theme .markdown-help {
background: #444;
border: 1px solid #666;
}
.dark-theme .markdown-help h3 {
color: #f4d03f;
}
.dark-theme .markdown-help ul {
color: #e0e0e0;
}
.dark-theme .markdown-help li {
color: #e0e0e0;
}
.dark-theme .markdown-help code {
background: #555;
color: #f39c12;
}
.dark-theme .cancel-btn {
background: #8b4513;
border: 2px solid #a0522d;
color: #fff;
}
.dark-theme .cancel-btn:hover {
background: #a0522d;
}
.dark-theme .post-message strong {
color: #f4d03f;
}
.dark-theme .post-message em {
color: #f39c12;
}
.dark-theme .post-message u {
color: #e67e22;
}
.dark-theme .post-message del {
color: #ff6b6b;
}
.dark-theme .post-message code {
background: #555;
color: #f39c12;
}
.dark-theme .post-message ul {
color: #e0e0e0;
}
.dark-theme .post-message li {
color: #e0e0e0;
}
.dark-theme .post-form {
background: #333;
border: 1px solid #555;
}
.dark-theme .form-row {
border-bottom: 1px solid #555;
}
.dark-theme .form-row:last-child {
border-bottom: none;
}
.dark-theme .title-input,
.dark-theme .description-input,
.dark-theme .message-input,
.dark-theme .file-input {
background: #444;
border: 1px solid #666;
color: #e0e0e0;
}
.dark-theme .title-input:focus,
.dark-theme .description-input:focus,
.dark-theme .message-input:focus,
.dark-theme .file-input:focus {
border-color: #f39c12;
outline: none;
}
.dark-theme .description-input {
background: #444 !important;
border: 1px solid #666 !important;
color: #e0e0e0 !important;
}
.dark-theme .description-input:focus {
border-color: #f39c12 !important;
outline: none !important;
}
.dark-theme .send-btn {
background: #f4d03f;
border: 2px solid #e67e22;
color: #8b4513;
}
.dark-theme .send-btn:hover {
background: #f39c12;
}
.dark-theme .file-info {
color: #aaa;
}
.dark-theme .reply-link {
color: #f39c12;
}
.dark-theme .reply-link:hover {
color: #e67e22;
}
.dark-theme ::-webkit-scrollbar {
width: 8px;
}
.dark-theme ::-webkit-scrollbar-track {
background: #333;
}
.dark-theme ::-webkit-scrollbar-thumb {
background: #666;
border-radius: 4px;
}
.dark-theme ::-webkit-scrollbar-thumb:hover {
background: #888;
}

29
theme.js Normal file
View File

@ -0,0 +1,29 @@
function toggleTheme() {
const body = document.body;
const button = document.querySelector('.theme-toggle');
const isDark = body.classList.contains('dark-theme');
if (isDark) {
body.classList.remove('dark-theme');
button.textContent = 'Включить светлую тему';
localStorage.setItem('theme', 'light');
} else {
body.classList.add('dark-theme');
button.textContent = 'Включить темную тему';
localStorage.setItem('theme', 'dark');
}
}
function initTheme() {
const savedTheme = localStorage.getItem('theme') || 'light';
const button = document.querySelector('.theme-toggle');
if (savedTheme === 'dark') {
document.body.classList.add('dark-theme');
if (button) {
button.textContent = 'Включить темную тему';
}
}
}
document.addEventListener('DOMContentLoaded', initTheme);

36
wait-for-db.php Normal file
View File

@ -0,0 +1,36 @@
<?php
$host = $_ENV['DB_HOST'] ?? 'mysql';
$dbname = $_ENV['DB_NAME'] ?? 'mkach';
$user = $_ENV['DB_USER'] ?? 'mkach';
$pass = $_ENV['DB_PASS'] ?? 'mkach';
$maxAttempts = 30;
$attempt = 0;
while ($attempt < $maxAttempts) {
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo->query("SELECT COUNT(*) FROM boards");
$count = $stmt->fetchColumn();
if ($count > 0) {
echo "Database is ready with $count boards\n";
exit(0);
} else {
echo "Database connected but no boards found, initializing...\n";
$sql = file_get_contents('/var/www/html/sql/create.sql');
$pdo->exec($sql);
echo "Database initialized successfully\n";
exit(0);
}
} catch (PDOException $e) {
$attempt++;
echo "Attempt $attempt/$maxAttempts: Database not ready yet...\n";
sleep(2);
}
}
echo "Failed to connect to database after $maxAttempts attempts\n";
exit(1);