MIneLine / index.html
Tokipo's picture
Update index.html
45ea1eb verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bot Manager</title>
<script src="/socket.io/socket.io.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
background: #1a1a1a;
color: #e0e0e0;
padding: 10px;
}
.header {
background: #2a2a2a;
padding: 15px;
margin-bottom: 10px;
border: 1px solid #333;
}
h1 {
font-size: 20px;
margin-bottom: 10px;
color: #fff;
}
.stats {
display: flex;
gap: 15px;
flex-wrap: wrap;
}
.stat {
background: #333;
padding: 8px 12px;
border: 1px solid #444;
color: #ccc;
}
.stat strong {
color: #fff;
}
.controls {
background: #2a2a2a;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #333;
}
.btn {
background: #4CAF50;
color: white;
border: none;
padding: 8px 16px;
cursor: pointer;
}
.btn:hover {
background: #45a049;
}
.btn:disabled {
background: #555;
color: #999;
cursor: not-allowed;
}
.bot-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 10px;
}
.bot-card {
background: #2a2a2a;
border: 1px solid #333;
padding: 10px;
}
.bot-header {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
align-items: center;
}
.bot-name {
font-weight: bold;
font-size: 14px;
color: #fff;
}
.status {
font-size: 12px;
padding: 2px 6px;
border: 1px solid;
}
.status-connected {
background: #1b4332;
color: #4ade80;
border-color: #16a34a;
}
.status-disconnected, .status-dead {
background: #450a0a;
color: #f87171;
border-color: #dc2626;
}
.bot-info {
font-size: 12px;
color: #aaa;
margin-bottom: 8px;
}
.bot-info div {
margin: 2px 0;
}
.info-highlight {
color: #4ade80;
}
.btn-rejoin {
background: #2196F3;
color: white;
border: none;
padding: 6px 12px;
cursor: pointer;
font-size: 12px;
width: 100%;
}
.btn-rejoin:hover {
background: #1976D2;
}
.btn-rejoin:disabled {
background: #555;
color: #999;
cursor: not-allowed;
}
.timer {
font-size: 11px;
color: #888;
text-align: center;
margin-top: 4px;
}
.loading {
padding: 20px;
color: #888;
text-align: center;
}
@media (max-width: 600px) {
.bot-grid {
grid-template-columns: 1fr;
}
h1 {
font-size: 18px;
}
.stats {
font-size: 12px;
}
}
</style>
</head>
<body>
<div class="header">
<h1>🤖 Bot Manager</h1>
<div class="stats">
<div class="stat">Total: <strong id="totalBots">0</strong></div>
<div class="stat">Connected: <strong id="connectedBots">0</strong></div>
<div class="stat">Disconnected: <strong id="disconnectedBots">0</strong></div>
<div class="stat">Deaths: <strong id="totalDeaths">0</strong></div>
</div>
</div>
<div class="controls">
<button class="btn" onclick="refreshSheet()">Refresh Sheet</button>
</div>
<div id="botContainer" class="bot-grid">
<div class="loading">Loading...</div>
</div>
<script>
const socket = io();
let botsData = [];
socket.on('connect', () => {
console.log('Connected to server');
});
socket.on('botUpdate', (data) => {
botsData = data;
updateUI();
});
socket.on('reconnectResult', (result) => {
if (!result.success) {
alert(`Cannot reconnect ${result.botName} yet. Wait 1 hour between reconnects.`);
}
});
function updateUI() {
const container = document.getElementById('botContainer');
// Filter out bots not in sheet
const validBots = botsData.filter(bot => bot.inSheet);
if (validBots.length === 0) {
container.innerHTML = '<div class="loading">No bots configured in sheet.</div>';
updateStats(0, 0, 0, 0);
return;
}
let html = '';
let totalBots = 0;
let connectedBots = 0;
let disconnectedBots = 0;
let totalDeaths = 0;
validBots.forEach(bot => {
totalBots++;
if (bot.status === 'Connected') {
connectedBots++;
} else {
disconnectedBots++;
}
totalDeaths += bot.deathCount;
const statusClass = bot.status === 'Connected' ? 'status-connected' :
bot.status === 'Connecting...' ? 'status-connected' :
'status-disconnected';
const showRejoinButton = (bot.status === 'Disconnected' || bot.status === 'Dead' ||
bot.status === 'Connection Failed' || bot.status === 'Server already has a bot') &&
bot.inSheet;
const canRejoinNow = bot.canReconnect;
const timeRemaining = bot.timeUntilReconnect;
html += `
<div class="bot-card">
<div class="bot-header">
<div class="bot-name">${bot.botName}</div>
<div class="status ${statusClass}">${bot.status}</div>
</div>
<div class="bot-info">
<div>Deaths: ${bot.deathCount}</div>
${bot.status === 'Connected' && bot.connectedDuration > 0 ?
`<div class="info-highlight">Connected: ${formatUptime(bot.connectedDuration)}</div>` : ''}
</div>
${showRejoinButton ? `
<button class="btn-rejoin"
onclick="reconnectBot('${bot.botName}')"
${!canRejoinNow ? 'disabled' : ''}>
${canRejoinNow ? 'Rejoin' : 'Wait to Rejoin'}
</button>
${!canRejoinNow && timeRemaining > 0 ?
`<div class="timer">Can rejoin in: ${formatUptime(timeRemaining)}</div>` : ''}
` : ''}
</div>
`;
});
container.innerHTML = html;
updateStats(totalBots, connectedBots, disconnectedBots, totalDeaths);
}
function updateStats(total, connected, disconnected, deaths) {
document.getElementById('totalBots').textContent = total;
document.getElementById('connectedBots').textContent = connected;
document.getElementById('disconnectedBots').textContent = disconnected;
document.getElementById('totalDeaths').textContent = deaths;
}
function formatUptime(seconds) {
if (seconds === 0) return '0s';
const days = Math.floor(seconds / 86400);
const hours = Math.floor((seconds % 86400) / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = seconds % 60;
if (days > 0) {
return `${days}d ${hours}h ${minutes}m`;
} else if (hours > 0) {
return `${hours}h ${minutes}m`;
} else if (minutes > 0) {
return `${minutes}m ${secs}s`;
} else {
return `${secs}s`;
}
}
function reconnectBot(botName) {
socket.emit('reconnectBot', botName);
}
function refreshSheet() {
socket.emit('refreshSheet');
}
// Update UI every 2 seconds to show timer countdown and connection duration
setInterval(() => {
if (botsData.length > 0) {
botsData.forEach(bot => {
if (bot.timeUntilReconnect > 0) {
bot.timeUntilReconnect = Math.max(0, bot.timeUntilReconnect - 2);
}
if (bot.status === 'Connected' && bot.connectedDuration >= 0) {
bot.connectedDuration += 2;
}
bot.canReconnect = bot.timeUntilReconnect === 0 &&
(bot.status === 'Disconnected' || bot.status === 'Dead' ||
bot.status === 'Connection Failed' || bot.status === 'Server already has a bot') &&
bot.inSheet;
});
updateUI();
}
}, 2000);
</script>
</body>
</html>