Files
sts-avto/server.js
2026-05-13 01:31:13 +05:00

141 lines
4.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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}`);
});