Files
hotell777_260507/modules/visitors/index.js
kalugin66 137a04f8c4
All checks were successful
Deploy hotel / deploy-kdo (push) Successful in 51s
127.0.0.1
2026-07-27 01:38:27 +05:00

148 lines
7.0 KiB
JavaScript

let db;
const LH = "ip NOT IN ('127.0.0.1', '::1', '::ffff:127.0.0.1')";
function init(database) {
db = database;
}
function getStats(req, res) {
db.get(`SELECT COUNT(DISTINCT session_id) as total FROM visitor_log WHERE ${LH}`, [], (err, totalRow) => {
if (err) return res.status(500).json({ error: err.message });
db.get(`SELECT COUNT(DISTINCT session_id) as today FROM visitor_log WHERE visit_date = date('now') AND ${LH}`, [], (err, todayRow) => {
if (err) return res.status(500).json({ error: err.message });
db.get(`SELECT COUNT(DISTINCT session_id) as week FROM visitor_log WHERE visit_date >= date('now', '-6 days') AND ${LH}`, [], (err, weekRow) => {
if (err) return res.status(500).json({ error: err.message });
db.get(`SELECT COUNT(DISTINCT session_id) as month FROM visitor_log WHERE visit_date >= date('now', 'start of month') AND ${LH}`, [], (err, monthRow) => {
if (err) return res.status(500).json({ error: err.message });
db.get(`SELECT COUNT(*) as page_views FROM visitor_log WHERE ${LH}`, [], (err, pvRow) => {
if (err) return res.status(500).json({ error: err.message });
db.get(`SELECT COUNT(DISTINCT ip) as unique_ips FROM visitor_log WHERE ${LH}`, [], (err, ipRow) => {
if (err) return res.status(500).json({ error: err.message });
res.json({
total: totalRow ? totalRow.total : 0,
today: todayRow ? todayRow.today : 0,
week: weekRow ? weekRow.week : 0,
month: monthRow ? monthRow.month : 0,
pageViews: pvRow ? pvRow.page_views : 0,
uniqueIps: ipRow ? ipRow.unique_ips : 0
});
});
});
});
});
});
});
}
function getCountries(req, res) {
db.all(`SELECT COALESCE(NULLIF(country, ''), 'Другое') as country,
COALESCE(NULLIF(country_code, ''), '--') as country_code,
COUNT(DISTINCT session_id) as count
FROM visitor_log
WHERE ${LH}
GROUP BY COALESCE(NULLIF(country_code, ''), '--')
ORDER BY count DESC LIMIT 30`, [], (err, rows) => {
if (err) return res.status(500).json({ error: err.message });
res.json(rows || []);
});
}
function getLanguages(req, res) {
db.all(`SELECT accept_language, COUNT(DISTINCT session_id) as count
FROM visitor_log
WHERE accept_language IS NOT NULL AND accept_language != '' AND ${LH}
GROUP BY accept_language
ORDER BY count DESC`, [], (err, rows) => {
if (err) return res.status(500).json({ error: err.message });
const parsed = (rows || []).map(r => {
const primary = (r.accept_language || '').split(',')[0].split(';')[0].trim();
const lang = primary.split('-')[0];
return { lang, raw: primary, count: r.count };
});
res.json(parsed);
});
}
function getDaily(req, res) {
db.all(`SELECT visit_date, COUNT(DISTINCT session_id) as count, COUNT(*) as page_views
FROM visitor_log
WHERE visit_date >= date('now', '-29 days') AND ${LH}
GROUP BY visit_date
ORDER BY visit_date ASC`, [], (err, rows) => {
if (err) return res.status(500).json({ error: err.message });
res.json(rows || []);
});
}
function getIPs(req, res) {
const limit = Math.min(parseInt(req.query.limit) || 50, 200);
const offset = parseInt(req.query.offset) || 0;
const { id, ip, country, lang, date_from, date_to, page } = req.query;
const whereClauses = [LH];
const params = [];
if (id) { whereClauses.push('id = ?'); params.push(parseInt(id)); }
if (ip) { whereClauses.push('ip LIKE ?'); params.push('%' + ip + '%'); }
if (country) { whereClauses.push('(country LIKE ? OR country_code LIKE ?)'); params.push('%' + country + '%'); params.push('%' + country + '%'); }
if (lang) { whereClauses.push('accept_language LIKE ?'); params.push('%' + lang + '%'); }
if (date_from) { whereClauses.push('visit_date >= ?'); params.push(date_from); }
if (date_to) { whereClauses.push('visit_date <= ?'); params.push(date_to); }
if (page) { whereClauses.push('page_path LIKE ?'); params.push('%' + page + '%'); }
const whereSQL = whereClauses.length > 0 ? 'WHERE ' + whereClauses.join(' AND ') : '';
db.get(`SELECT COUNT(*) as total FROM visitor_log ${whereSQL}`, params, (err, countRow) => {
if (err) return res.status(500).json({ error: err.message });
const allParams = [...params, limit, offset];
db.all(`SELECT id, ip, COALESCE(NULLIF(country, ''), 'Другое') as country,
country_code, session_id, visit_date, page_path,
COALESCE(NULLIF(accept_language, ''), '-') as accept_language,
created_at
FROM visitor_log
${whereSQL}
ORDER BY created_at DESC
LIMIT ? OFFSET ?`, allParams, (err, rows) => {
if (err) return res.status(500).json({ error: err.message });
res.json({
entries: rows || [],
total: countRow ? countRow.total : 0,
limit,
offset
});
});
});
}
function getFilterOptions(req, res) {
db.all(`SELECT DISTINCT COALESCE(NULLIF(country, ''), 'Другое') as country
FROM visitor_log ORDER BY country`, [], (err, countries) => {
if (err) return res.status(500).json({ error: err.message });
db.all(`SELECT DISTINCT accept_language FROM visitor_log
WHERE accept_language IS NOT NULL AND accept_language != ''
ORDER BY accept_language`, [], (err, langs) => {
if (err) return res.status(500).json({ error: err.message });
db.all(`SELECT DISTINCT page_path FROM visitor_log ORDER BY page_path`, [], (err, pages) => {
if (err) return res.status(500).json({ error: err.message });
res.json({
countries: (countries || []).map(c => c.country),
languages: (langs || []).map(l => l.accept_language),
pages: (pages || []).map(p => p.page_path)
});
});
});
});
}
function setupRoutes(app, authenticateToken) {
app.get('/api/admin/visitors/stats', authenticateToken, getStats);
app.get('/api/admin/visitors/countries', authenticateToken, getCountries);
app.get('/api/admin/visitors/languages', authenticateToken, getLanguages);
app.get('/api/admin/visitors/daily', authenticateToken, getDaily);
app.get('/api/admin/visitors/ips', authenticateToken, getIPs);
app.get('/api/admin/visitors/filters', authenticateToken, getFilterOptions);
}
module.exports = { init, setupRoutes };