109 lines
4.0 KiB
JavaScript
109 lines
4.0 KiB
JavaScript
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}`);
|
||
});
|
||
}); |