This commit is contained in:
2026-05-13 02:16:02 +05:00
commit f0eb7fb1ea
21 changed files with 1487 additions and 0 deletions

141
server.js Normal file
View File

@@ -0,0 +1,141 @@
const express = require('express');
const path = require('path');
const fs = require('fs');
const sqlite3 = require('sqlite3').verbose();
const sharp = require('sharp');
require('dotenv').config();
const app = express();
const PORT = process.env.PORT || 3000;
const API_KEY = process.env.HOTEL777KEY;
if (!API_KEY) {
console.error('FATAL: HOTEL777KEY environment variable not set');
process.exit(1);
}
const imgDir = path.join(__dirname, 'public', 'img');
const supportedFormats = ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.tiff'];
async function convertImagesToWebp() {
if (!fs.existsSync(imgDir)) {
console.log('📁 Папка img не найдена, пропускаем конвертацию');
return;
}
const files = fs.readdirSync(imgDir);
const toConvert = files.filter(f => {
const ext = path.extname(f).toLowerCase();
return supportedFormats.includes(ext) && !f.endsWith('.webp');
});
if (toConvert.length === 0) {
console.log('✅ Все изображения уже в формате WebP');
return;
}
console.log(`🔄 Конвертация ${toConvert.length} изображений в WebP...`);
for (const file of toConvert) {
const inputPath = path.join(imgDir, file);
const outputPath = path.join(imgDir, path.basename(file, path.extname(file)) + '.webp');
try {
await sharp(inputPath)
.webp({ quality: 85 })
.toFile(outputPath);
fs.unlinkSync(inputPath);
console.log(`${file}${path.basename(outputPath)}`);
} catch (err) {
console.error(` ❌ Ошибка конвертации ${file}:`, err.message);
}
}
console.log('✅ Конвертация завершена');
}
// Middleware
app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));
// Ensure data directory and database
const dataDir = path.join(__dirname, 'data');
if (!fs.existsSync(dataDir)) fs.mkdirSync(dataDir);
const dbPath = path.join(dataDir, 'bookings.db');
const db = new sqlite3.Database(dbPath);
db.run(`CREATE TABLE IF NOT EXISTS leads (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
phone TEXT NOT NULL,
message TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)`);
// API: POST /api/leads сохранить новую заявку (публичный)
app.post('/api/leads', (req, res) => {
const { name, phone, message } = req.body;
if (!name || !phone) {
return res.status(400).json({ error: 'Missing required fields: name, phone' });
}
const stmt = db.prepare(`INSERT INTO leads (name, phone, message) VALUES (?, ?, ?)`);
stmt.run(name.trim(), phone.trim(), (message || '').trim(), function(err) {
if (err) {
console.error(err);
return res.status(500).json({ error: 'Database error' });
}
console.log(`✅ Новая заявка #${this.lastID}: ${name} | ${phone}`);
res.status(201).json({ id: this.lastID, message: 'Lead saved' });
});
stmt.finalize();
});
// API: GET /api/leads получить список всех заявок (требуется API-ключ)
app.get('/api/leads', (req, res) => {
const providedKey = req.headers['x-api-key'];
if (!providedKey || providedKey !== API_KEY) {
return res.status(401).json({ error: 'Invalid or missing API key' });
}
db.all(`SELECT id, name, phone, message, created_at FROM leads ORDER BY created_at DESC`, (err, rows) => {
if (err) {
console.error(err);
return res.status(500).json({ error: 'Database error' });
}
res.json(rows);
});
});
// API: DELETE /api/leads/:id удалить заявку (требуется API-ключ)
app.delete('/api/leads/:id', (req, res) => {
const providedKey = req.headers['x-api-key'];
if (!providedKey || providedKey !== API_KEY) {
return res.status(401).json({ error: 'Invalid or missing API key' });
}
const id = parseInt(req.params.id);
if (isNaN(id)) {
return res.status(400).json({ error: 'Invalid ID' });
}
const stmt = db.prepare(`DELETE FROM leads WHERE id = ?`);
stmt.run(id, function(err) {
if (err) {
console.error(err);
return res.status(500).json({ error: 'Database error' });
}
if (this.changes === 0) {
return res.status(404).json({ error: 'Lead not found' });
}
console.log(`🗑️ Удалена заявка #${id}`);
res.json({ message: 'Lead deleted' });
});
stmt.finalize();
});
// Serve frontend
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
app.listen(PORT, async () => {
await convertImagesToWebp();
console.log(`✅ server running on http://localhost:${PORT}`);
console.log(`🔑 API Key: ${API_KEY}`);
});