Auto commit: 2026-02-18T21:12:19.741Z
This commit is contained in:
parent
d30c75493b
commit
730a39f56b
@ -6,18 +6,34 @@ $db = db();
|
||||
// Active in the last 15 minutes, has username and phone
|
||||
// Use GROUP BY to avoid duplicates if same session/user has multiple entries (though session_id should be unique-ish)
|
||||
$stmt = $db->prepare("
|
||||
SELECT username, phone_number, country_code, last_activity
|
||||
FROM visitor_logs
|
||||
WHERE last_activity > DATE_SUB(NOW(), INTERVAL 15 MINUTE)
|
||||
AND username IS NOT NULL
|
||||
AND phone_number IS NOT NULL
|
||||
AND username != ''
|
||||
AND phone_number != ''
|
||||
GROUP BY username, phone_number
|
||||
ORDER BY last_activity DESC
|
||||
SELECT
|
||||
v.username,
|
||||
v.phone_number,
|
||||
v.country_code,
|
||||
v.last_activity,
|
||||
f.points,
|
||||
f.is_fan_of_month
|
||||
FROM visitor_logs v
|
||||
LEFT JOIN fans f ON v.username = f.name
|
||||
WHERE v.last_activity > DATE_SUB(NOW(), INTERVAL 15 MINUTE)
|
||||
AND v.username IS NOT NULL
|
||||
AND v.phone_number IS NOT NULL
|
||||
AND v.username != ''
|
||||
AND v.phone_number != ''
|
||||
GROUP BY v.username, v.phone_number
|
||||
ORDER BY v.last_activity DESC
|
||||
LIMIT 20
|
||||
");
|
||||
$stmt->execute();
|
||||
$users = $stmt->fetchAll();
|
||||
|
||||
echo json_encode(['success' => true, 'users' => $users]);
|
||||
// Get total active sessions (last 5 minutes) for a live counter
|
||||
$stmtTotal = $db->prepare("SELECT COUNT(DISTINCT session_id) as total FROM visitor_logs WHERE last_activity > DATE_SUB(NOW(), INTERVAL 5 MINUTE)");
|
||||
$stmtTotal->execute();
|
||||
$totalActive = $stmtTotal->fetch()['total'] ?? 0;
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'users' => $users,
|
||||
'total_active' => $totalActive
|
||||
]);
|
||||
|
||||
64
index.php
64
index.php
@ -2296,33 +2296,73 @@ $twitter_link = "https://twitter.com/";
|
||||
});
|
||||
}
|
||||
|
||||
function getUserColor(str) {
|
||||
let hash = 0;
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
||||
}
|
||||
const h = Math.abs(hash) % 360;
|
||||
// Usamos colores vibrantes con buena saturación y luminosidad media
|
||||
return `hsl(${h}, 65%, 55%)`;
|
||||
}
|
||||
|
||||
function timeAgo(dateString) {
|
||||
const now = new Date();
|
||||
const past = new Date(dateString);
|
||||
const diffInSeconds = Math.floor((now - past) / 1000);
|
||||
|
||||
if (diffInSeconds < 60) return 'Hace un momento';
|
||||
if (diffInSeconds < 3600) return `Hace ${Math.floor(diffInSeconds / 60)} min`;
|
||||
return 'Hace más de 1 hora';
|
||||
}
|
||||
|
||||
async function fetchOnlineUsers() {
|
||||
try {
|
||||
const response = await fetch('api/get_online_users.php');
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
const list = document.getElementById('online-users-list');
|
||||
const widgetTitle = document.querySelector('#online-users-list').previousElementSibling.previousElementSibling;
|
||||
|
||||
if (widgetTitle && data.total_active !== undefined) {
|
||||
widgetTitle.innerHTML = `<i class="bi bi-people-fill"></i> CLIENTES CONECTADOS <span style="font-size: 0.7rem; background: rgba(37, 211, 102, 0.2); padding: 2px 8px; border-radius: 20px; vertical-align: middle; margin-left: 5px;">${data.total_active} OYENTES</span>`;
|
||||
}
|
||||
|
||||
if (data.users.length === 0) {
|
||||
list.innerHTML = '<div style="opacity: 0.5; font-size: 0.85rem; text-align: center; padding: 1rem;">No hay otros usuarios con móvil registrado ahora.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
list.innerHTML = data.users.map(user => `
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; background: rgba(255,255,255,0.03); padding: 10px 15px; border-radius: 12px; border: 1px solid rgba(255,255,255,0.05); transition: all 0.3s;">
|
||||
list.innerHTML = data.users.map(user => {
|
||||
const isVeryActive = (new Date() - new Date(user.last_activity)) < 60000;
|
||||
const flagUrl = user.country_code ? `https://flagcdn.com/w20/${user.country_code.toLowerCase()}.png` : null;
|
||||
const isTopFan = user.points > 10 || user.is_fan_of_month == 1;
|
||||
const userColor = getUserColor(user.username);
|
||||
|
||||
return `
|
||||
<div style="display: flex; align-items: center; justify-content: space-between; background: rgba(255,255,255,0.03); padding: 10px 15px; border-radius: 12px; border: 1px solid rgba(255,255,255,0.05); transition: all 0.3s; position: relative;">
|
||||
<div style="display: flex; align-items: center; gap: 10px;">
|
||||
<div style="width: 35px; height: 35px; background: var(--primary-color); border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 0.9rem; color: #000;">
|
||||
<div style="width: 38px; height: 38px; background: ${userColor}; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 1rem; color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,0.3); position: relative; ${isVeryActive ? `box-shadow: 0 0 0 2px rgba(255,255,255,0.1), 0 0 12px ${userColor};` : ''}">
|
||||
${user.username.charAt(0).toUpperCase()}
|
||||
${isVeryActive ? '<span style="position: absolute; bottom: 0; right: 0; width: 10px; height: 10px; background: #25D366; border: 2px solid #000; border-radius: 50%;"></span>' : ''}
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-weight: 700; font-size: 0.9rem;">${user.username}</div>
|
||||
<div style="font-size: 0.7rem; opacity: 0.6;"><i class="bi bi-geo-alt-fill"></i> Conectado</div>
|
||||
<div style="font-weight: 700; font-size: 0.95rem; display: flex; align-items: center; gap: 6px;">
|
||||
${user.username}
|
||||
${flagUrl ? `<img src="${flagUrl}" style="width: 16px; height: auto; border-radius: 2px; vertical-align: middle;" title="${user.country_code}">` : ''}
|
||||
${isTopFan ? `<span style="background: #FFD700; color: #000; font-size: 0.6rem; padding: 2px 6px; border-radius: 10px; font-weight: 800; text-transform: uppercase;">TOP</span>` : ''}
|
||||
</div>
|
||||
<div style="font-size: 0.7rem; opacity: 0.6;">
|
||||
<i class="bi bi-clock"></i> ${timeAgo(user.last_activity)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://wa.me/${user.phone_number.replace(/\D/g, '')}" target="_blank" style="background: #25D366; color: white; width: 32px; height: 32px; border-radius: 50%; display: flex; align-items: center; justify-content: center; text-decoration: none; box-shadow: 0 4px 10px rgba(37, 211, 102, 0.3); transition: transform 0.2s;" onmouseover="this.style.transform='scale(1.1)'" onmouseout="this.style.transform='scale(1)'">
|
||||
<a href="https://wa.me/${user.phone_number.replace(/\D/g, '')}?text=Hola,%20te%20vi%20en%20Lili%20Records" target="_blank" style="background: #25D366; color: white; width: 34px; height: 34px; border-radius: 50%; display: flex; align-items: center; justify-content: center; text-decoration: none; box-shadow: 0 4px 10px rgba(37, 211, 102, 0.3); transition: all 0.2s;" onmouseover="this.style.transform='scale(1.15)'" onmouseout="this.style.transform='scale(1)'">
|
||||
<i class="bi bi-whatsapp"></i>
|
||||
</a>
|
||||
</div>
|
||||
`).join('');
|
||||
`;
|
||||
}).join('');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching online users:', error);
|
||||
@ -2454,7 +2494,8 @@ $twitter_link = "https://twitter.com/";
|
||||
const div = document.createElement('div');
|
||||
const isLike = msg.message.includes('❤️');
|
||||
|
||||
const nameColor = msg.level_color || (msg.is_fan_of_month ? '#facc15' : 'var(--primary-color)');
|
||||
// Si el color es el gris por defecto (#94a3b8) o no tiene, usamos el color dinámico por nombre
|
||||
const nameColor = (msg.level_color && msg.level_color !== '#94a3b8') ? msg.level_color : getUserColor(msg.username);
|
||||
const levelEmoji = msg.level_emoji || '';
|
||||
|
||||
div.style.background = isLike ? 'rgba(255, 68, 68, 0.15)' : 'rgba(255,255,255,0.05)';
|
||||
@ -3000,7 +3041,12 @@ $twitter_link = "https://twitter.com/";
|
||||
container.innerHTML = topFans.map((fan, index) => `
|
||||
<div class="leaderboard-item">
|
||||
<div class="leaderboard-rank">${index + 1}</div>
|
||||
<img src="${fan.photo || 'assets/pasted-20260215-163754-def41f49.png'}" alt="${fan.username}" class="leaderboard-avatar">
|
||||
${fan.photo ?
|
||||
`<img src="${fan.photo}" alt="${fan.username}" class="leaderboard-avatar">` :
|
||||
`<div class="leaderboard-avatar" style="display: flex; align-items: center; justify-content: center; background: ${getUserColor(fan.username)}; color: #fff; font-weight: 800; border: none; font-size: 1.2rem; text-shadow: 0 1px 2px rgba(0,0,0,0.3);">
|
||||
${fan.username.charAt(0).toUpperCase()}
|
||||
</div>`
|
||||
}
|
||||
<div class="leaderboard-info">
|
||||
<div class="leaderboard-name">
|
||||
<span style="color: ${fan.level_color};">${fan.username}</span>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user