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); } // 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 bookings ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, phone TEXT NOT NULL, adults INTEGER NOT NULL, children INTEGER NOT NULL, checkin_date TEXT NOT NULL, checkout_date TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )`); // Image conversion (automatically convert JPEG/PNG to WebP) async function convertImages() { const imgDir = path.join(__dirname, 'public', 'img'); if (!fs.existsSync(imgDir)) { console.log('Папка img не найдена, пропускаем конвертацию.'); return; } const files = fs.readdirSync(imgDir); for (const file of files) { const ext = path.extname(file).toLowerCase(); if (ext === '.jpg' || ext === '.jpeg' || ext === '.png') { const name = path.parse(file).name; const webpPath = path.join(imgDir, `${name}.webp`); if (!fs.existsSync(webpPath)) { try { await sharp(path.join(imgDir, file)) .webp({ quality: 85 }) .toFile(webpPath); console.log(`✅ Сконвертировано: ${file} -> ${name}.webp`); } catch (err) { console.error(`❌ Ошибка при конвертации ${file}:`, err); } } } } } // API: POST /api/bookings – сохранить новую заявку app.post('/api/bookings', (req, res) => { const { name, phone, adults, children, checkin, checkout } = req.body; if (!name || !phone || !adults || !checkin || !checkout) { return res.status(400).json({ error: 'Missing required fields' }); } const stmt = db.prepare(`INSERT INTO bookings (name, phone, adults, children, checkin_date, checkout_date) VALUES (?, ?, ?, ?, ?, ?)`); stmt.run(name, phone, adults, children || 0, checkin, checkout, function(err) { if (err) { console.error(err); return res.status(500).json({ error: 'Database error' }); } res.status(201).json({ id: this.lastID, message: 'Booking saved' }); }); stmt.finalize(); }); // API: GET /api/bookings – получить список всех заявок (требуется API-ключ) app.get('/api/bookings', (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, adults, children, checkin_date, checkout_date, created_at FROM bookings ORDER BY created_at DESC`, (err, rows) => { if (err) { console.error(err); return res.status(500).json({ error: 'Database error' }); } res.json(rows); }); }); // Serve frontend app.get('/', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'index.html')); }); // Start server after image conversion convertImages().then(() => { app.listen(PORT, () => { console.log('✅ HOTEL777KEY is', API_KEY); console.log(`✅ Hotel 777 server running on http://localhost:${PORT}`); }); });