Tokipo commited on
Commit
14db4db
·
verified ·
1 Parent(s): 6b93999

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +118 -225
index.html CHANGED
@@ -3,7 +3,7 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Mineflayer Bot Manager</title>
7
  <script src="/socket.io/socket.io.js"></script>
8
  <style>
9
  * {
@@ -13,76 +13,52 @@
13
  }
14
 
15
  body {
16
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
17
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
18
- min-height: 100vh;
19
- padding: 20px;
20
- }
21
-
22
- .container {
23
- max-width: 1400px;
24
- margin: 0 auto;
25
  }
26
 
27
  .header {
28
  background: white;
29
- border-radius: 10px;
30
- padding: 20px;
31
- margin-bottom: 20px;
32
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
33
  }
34
 
35
- .header h1 {
36
- color: #333;
37
  margin-bottom: 10px;
38
  }
39
 
40
  .stats {
41
  display: flex;
42
- gap: 20px;
43
  flex-wrap: wrap;
44
  }
45
 
46
- .stat-card {
47
- background: #f8f9fa;
48
- padding: 10px 20px;
49
- border-radius: 5px;
50
- border-left: 4px solid #667eea;
51
- }
52
-
53
- .stat-card .label {
54
- font-size: 12px;
55
- color: #666;
56
- text-transform: uppercase;
57
- }
58
-
59
- .stat-card .value {
60
- font-size: 24px;
61
- font-weight: bold;
62
- color: #333;
63
  }
64
 
65
  .controls {
66
  background: white;
67
- border-radius: 10px;
68
- padding: 15px;
69
- margin-bottom: 20px;
70
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
71
  }
72
 
73
  .btn {
74
- background: #667eea;
75
  color: white;
76
  border: none;
77
- padding: 10px 20px;
78
- border-radius: 5px;
79
  cursor: pointer;
80
- font-size: 14px;
81
- transition: background 0.3s;
82
  }
83
 
84
  .btn:hover {
85
- background: #5a67d8;
86
  }
87
 
88
  .btn:disabled {
@@ -92,175 +68,115 @@
92
 
93
  .bot-grid {
94
  display: grid;
95
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
96
- gap: 15px;
97
  }
98
 
99
  .bot-card {
100
  background: white;
101
- border-radius: 10px;
102
- padding: 15px;
103
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
104
- transition: transform 0.3s;
105
- }
106
-
107
- .bot-card:hover {
108
- transform: translateY(-2px);
109
- box-shadow: 0 6px 12px rgba(0, 0, 0, 0.15);
110
  }
111
 
112
  .bot-header {
113
  display: flex;
114
  justify-content: space-between;
 
115
  align-items: center;
116
- margin-bottom: 10px;
117
  }
118
 
119
  .bot-name {
120
  font-weight: bold;
121
- font-size: 16px;
122
- color: #333;
123
  }
124
 
125
- .bot-status {
126
- padding: 4px 8px;
127
- border-radius: 12px;
128
  font-size: 12px;
129
- font-weight: bold;
 
130
  }
131
 
132
  .status-connected {
133
- background: #d4edda;
134
- color: #155724;
135
- }
136
-
137
- .status-disconnected {
138
- background: #f8d7da;
139
- color: #721c24;
140
  }
141
 
142
- .status-connecting {
143
- background: #fff3cd;
144
- color: #856404;
 
145
  }
146
 
147
  .bot-info {
148
- display: grid;
149
- grid-template-columns: repeat(2, 1fr);
150
- gap: 10px;
151
- margin-bottom: 10px;
152
- }
153
-
154
- .info-item {
155
- display: flex;
156
- flex-direction: column;
157
- }
158
-
159
- .info-label {
160
- font-size: 11px;
161
  color: #666;
162
- text-transform: uppercase;
163
  }
164
 
165
- .info-value {
166
- font-size: 14px;
167
- color: #333;
168
- font-weight: 500;
169
  }
170
 
171
- .bot-actions {
172
- display: flex;
173
- gap: 10px;
174
- }
175
-
176
- .btn-small {
177
  padding: 6px 12px;
 
178
  font-size: 12px;
 
179
  }
180
 
181
- .btn-reconnect {
182
- background: #28a745;
183
- }
184
-
185
- .btn-reconnect:hover {
186
- background: #218838;
187
  }
188
 
189
- .notification {
190
- position: fixed;
191
- top: 20px;
192
- right: 20px;
193
- padding: 15px 20px;
194
- border-radius: 5px;
195
- background: white;
196
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
197
- display: none;
198
- animation: slideIn 0.3s;
199
- }
200
-
201
- .notification.success {
202
- border-left: 4px solid #28a745;
203
  }
204
 
205
- .notification.error {
206
- border-left: 4px solid #dc3545;
 
 
 
207
  }
208
 
209
- @keyframes slideIn {
210
- from {
211
- transform: translateX(100%);
212
- opacity: 0;
213
  }
214
- to {
215
- transform: translateX(0);
216
- opacity: 1;
 
 
 
 
217
  }
218
- }
219
-
220
- .loading {
221
- text-align: center;
222
- padding: 40px;
223
- color: white;
224
  }
225
  </style>
226
  </head>
227
  <body>
228
- <div class="container">
229
- <div class="header">
230
- <h1>🤖 Mineflayer Bot Manager</h1>
231
- <div class="stats">
232
- <div class="stat-card">
233
- <div class="label">Total Bots</div>
234
- <div class="value" id="totalBots">0</div>
235
- </div>
236
- <div class="stat-card">
237
- <div class="label">Connected</div>
238
- <div class="value" id="connectedBots">0</div>
239
- </div>
240
- <div class="stat-card">
241
- <div class="label">Disconnected</div>
242
- <div class="value" id="disconnectedBots">0</div>
243
- </div>
244
- <div class="stat-card">
245
- <div class="label">Total Deaths</div>
246
- <div class="value" id="totalDeaths">0</div>
247
- </div>
248
- </div>
249
- </div>
250
-
251
- <div class="controls">
252
- <button class="btn" onclick="refreshSheet()">🔄 Refresh from Sheet</button>
253
- <span style="margin-left: 10px; color: #666; font-size: 14px;">
254
- Auto-refresh every 30 seconds
255
- </span>
256
- </div>
257
-
258
- <div id="botContainer" class="bot-grid">
259
- <div class="loading">Loading bots...</div>
260
  </div>
261
  </div>
262
 
263
- <div id="notification" class="notification"></div>
 
 
 
 
 
 
264
 
265
  <script>
266
  const socket = io();
@@ -268,12 +184,6 @@
268
 
269
  socket.on('connect', () => {
270
  console.log('Connected to server');
271
- showNotification('Connected to server', 'success');
272
- });
273
-
274
- socket.on('disconnect', () => {
275
- console.log('Disconnected from server');
276
- showNotification('Disconnected from server', 'error');
277
  });
278
 
279
  socket.on('botUpdate', (data) => {
@@ -282,18 +192,19 @@
282
  });
283
 
284
  socket.on('reconnectResult', (result) => {
285
- if (result.success) {
286
- showNotification(`Bot ${result.botName} is reconnecting...`, 'success');
287
- } else {
288
- showNotification(`Cannot reconnect ${result.botName} yet. Wait 1 hour between reconnects.`, 'error');
289
  }
290
  });
291
 
292
  function updateUI() {
293
  const container = document.getElementById('botContainer');
294
 
295
- if (botsData.length === 0) {
296
- container.innerHTML = '<div class="loading">No bots configured. Add bots to the Google Sheet.</div>';
 
 
 
297
  updateStats(0, 0, 0, 0);
298
  return;
299
  }
@@ -304,7 +215,7 @@
304
  let disconnectedBots = 0;
305
  let totalDeaths = 0;
306
 
307
- botsData.forEach(bot => {
308
  totalBots++;
309
  if (bot.status === 'Connected') {
310
  connectedBots++;
@@ -314,47 +225,32 @@
314
  totalDeaths += bot.deathCount;
315
 
316
  const statusClass = bot.status === 'Connected' ? 'status-connected' :
317
- bot.status === 'Connecting...' ? 'status-connecting' :
318
  'status-disconnected';
319
 
320
- const uptime = formatUptime(bot.uptime);
321
- const disconnectTime = bot.disconnectTime ?
322
- formatTimeSince(bot.disconnectTime) : 'N/A';
323
 
324
  html += `
325
  <div class="bot-card">
326
  <div class="bot-header">
327
  <div class="bot-name">${bot.botName}</div>
328
- <div class="bot-status ${statusClass}">${bot.status}</div>
329
  </div>
330
  <div class="bot-info">
331
- <div class="info-item">
332
- <span class="info-label">Uptime</span>
333
- <span class="info-value">${uptime}</span>
334
- </div>
335
- <div class="info-item">
336
- <span class="info-label">Deaths</span>
337
- <span class="info-value">${bot.deathCount}</span>
338
- </div>
339
- ${bot.status === 'Disconnected' ? `
340
- <div class="info-item">
341
- <span class="info-label">Disconnected</span>
342
- <span class="info-value">${disconnectTime}</span>
343
- </div>
344
- ` : ''}
345
- </div>
346
- <div class="bot-actions">
347
- ${bot.canReconnect && bot.status === 'Disconnected' ? `
348
- <button class="btn btn-small btn-reconnect" onclick="reconnectBot('${bot.botName}')">
349
- 🔌 Reconnect
350
- </button>
351
- ` : ''}
352
- ${!bot.canReconnect && bot.status === 'Disconnected' ? `
353
- <button class="btn btn-small" disabled>
354
- ⏰ Wait to reconnect
355
- </button>
356
- ` : ''}
357
  </div>
 
 
 
 
 
 
 
 
 
358
  </div>
359
  `;
360
  });
@@ -372,7 +268,6 @@
372
 
373
  function formatUptime(seconds) {
374
  if (seconds === 0) return '0s';
375
-
376
  const hours = Math.floor(seconds / 3600);
377
  const minutes = Math.floor((seconds % 3600) / 60);
378
  const secs = seconds % 60;
@@ -386,30 +281,28 @@
386
  }
387
  }
388
 
389
- function formatTimeSince(timestamp) {
390
- const seconds = Math.floor((Date.now() - timestamp) / 1000);
391
- return formatUptime(seconds) + ' ago';
392
- }
393
-
394
  function reconnectBot(botName) {
395
  socket.emit('reconnectBot', botName);
396
  }
397
 
398
  function refreshSheet() {
399
  socket.emit('refreshSheet');
400
- showNotification('Refreshing from Google Sheet...', 'success');
401
  }
402
 
403
- function showNotification(message, type) {
404
- const notification = document.getElementById('notification');
405
- notification.textContent = message;
406
- notification.className = `notification ${type}`;
407
- notification.style.display = 'block';
408
-
409
- setTimeout(() => {
410
- notification.style.display = 'none';
411
- }, 3000);
412
- }
 
 
 
 
413
  </script>
414
  </body>
415
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Bot Manager</title>
7
  <script src="/socket.io/socket.io.js"></script>
8
  <style>
9
  * {
 
13
  }
14
 
15
  body {
16
+ font-family: Arial, sans-serif;
17
+ background: #f0f0f0;
18
+ padding: 10px;
 
 
 
 
 
 
19
  }
20
 
21
  .header {
22
  background: white;
23
+ padding: 15px;
24
+ margin-bottom: 10px;
25
+ border: 1px solid #ddd;
 
26
  }
27
 
28
+ h1 {
29
+ font-size: 20px;
30
  margin-bottom: 10px;
31
  }
32
 
33
  .stats {
34
  display: flex;
35
+ gap: 15px;
36
  flex-wrap: wrap;
37
  }
38
 
39
+ .stat {
40
+ background: #f8f8f8;
41
+ padding: 8px 12px;
42
+ border: 1px solid #e0e0e0;
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  }
44
 
45
  .controls {
46
  background: white;
47
+ padding: 10px;
48
+ margin-bottom: 10px;
49
+ border: 1px solid #ddd;
 
50
  }
51
 
52
  .btn {
53
+ background: #4CAF50;
54
  color: white;
55
  border: none;
56
+ padding: 8px 16px;
 
57
  cursor: pointer;
 
 
58
  }
59
 
60
  .btn:hover {
61
+ background: #45a049;
62
  }
63
 
64
  .btn:disabled {
 
68
 
69
  .bot-grid {
70
  display: grid;
71
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
72
+ gap: 10px;
73
  }
74
 
75
  .bot-card {
76
  background: white;
77
+ border: 1px solid #ddd;
78
+ padding: 10px;
 
 
 
 
 
 
 
79
  }
80
 
81
  .bot-header {
82
  display: flex;
83
  justify-content: space-between;
84
+ margin-bottom: 8px;
85
  align-items: center;
 
86
  }
87
 
88
  .bot-name {
89
  font-weight: bold;
90
+ font-size: 14px;
 
91
  }
92
 
93
+ .status {
 
 
94
  font-size: 12px;
95
+ padding: 2px 6px;
96
+ border: 1px solid;
97
  }
98
 
99
  .status-connected {
100
+ background: #e8f5e9;
101
+ color: #2e7d32;
102
+ border-color: #4caf50;
 
 
 
 
103
  }
104
 
105
+ .status-disconnected, .status-dead {
106
+ background: #ffebee;
107
+ color: #c62828;
108
+ border-color: #f44336;
109
  }
110
 
111
  .bot-info {
112
+ font-size: 12px;
 
 
 
 
 
 
 
 
 
 
 
 
113
  color: #666;
114
+ margin-bottom: 8px;
115
  }
116
 
117
+ .bot-info div {
118
+ margin: 2px 0;
 
 
119
  }
120
 
121
+ .btn-rejoin {
122
+ background: #2196F3;
123
+ color: white;
124
+ border: none;
 
 
125
  padding: 6px 12px;
126
+ cursor: pointer;
127
  font-size: 12px;
128
+ width: 100%;
129
  }
130
 
131
+ .btn-rejoin:hover {
132
+ background: #1976D2;
 
 
 
 
133
  }
134
 
135
+ .btn-rejoin:disabled {
136
+ background: #ccc;
137
+ cursor: not-allowed;
 
 
 
 
 
 
 
 
 
 
 
138
  }
139
 
140
+ .timer {
141
+ font-size: 11px;
142
+ color: #999;
143
+ text-align: center;
144
+ margin-top: 4px;
145
  }
146
 
147
+ @media (max-width: 600px) {
148
+ .bot-grid {
149
+ grid-template-columns: 1fr;
 
150
  }
151
+
152
+ h1 {
153
+ font-size: 18px;
154
+ }
155
+
156
+ .stats {
157
+ font-size: 12px;
158
  }
 
 
 
 
 
 
159
  }
160
  </style>
161
  </head>
162
  <body>
163
+ <div class="header">
164
+ <h1>Bot Manager</h1>
165
+ <div class="stats">
166
+ <div class="stat">Total: <strong id="totalBots">0</strong></div>
167
+ <div class="stat">Connected: <strong id="connectedBots">0</strong></div>
168
+ <div class="stat">Disconnected: <strong id="disconnectedBots">0</strong></div>
169
+ <div class="stat">Deaths: <strong id="totalDeaths">0</strong></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  </div>
171
  </div>
172
 
173
+ <div class="controls">
174
+ <button class="btn" onclick="refreshSheet()">Refresh Sheet</button>
175
+ </div>
176
+
177
+ <div id="botContainer" class="bot-grid">
178
+ <div style="padding: 20px; color: #666;">Loading...</div>
179
+ </div>
180
 
181
  <script>
182
  const socket = io();
 
184
 
185
  socket.on('connect', () => {
186
  console.log('Connected to server');
 
 
 
 
 
 
187
  });
188
 
189
  socket.on('botUpdate', (data) => {
 
192
  });
193
 
194
  socket.on('reconnectResult', (result) => {
195
+ if (!result.success) {
196
+ alert(`Cannot reconnect ${result.botName} yet. Wait 1 hour between reconnects.`);
 
 
197
  }
198
  });
199
 
200
  function updateUI() {
201
  const container = document.getElementById('botContainer');
202
 
203
+ // Filter out bots not in sheet
204
+ const validBots = botsData.filter(bot => bot.inSheet);
205
+
206
+ if (validBots.length === 0) {
207
+ container.innerHTML = '<div style="padding: 20px; color: #666;">No bots configured in sheet.</div>';
208
  updateStats(0, 0, 0, 0);
209
  return;
210
  }
 
215
  let disconnectedBots = 0;
216
  let totalDeaths = 0;
217
 
218
+ validBots.forEach(bot => {
219
  totalBots++;
220
  if (bot.status === 'Connected') {
221
  connectedBots++;
 
225
  totalDeaths += bot.deathCount;
226
 
227
  const statusClass = bot.status === 'Connected' ? 'status-connected' :
228
+ bot.status === 'Connecting...' ? 'status-connected' :
229
  'status-disconnected';
230
 
231
+ const showRejoinButton = (bot.status === 'Disconnected' || bot.status === 'Dead') && bot.inSheet;
232
+ const canRejoinNow = bot.canReconnect;
233
+ const timeRemaining = bot.timeUntilReconnect;
234
 
235
  html += `
236
  <div class="bot-card">
237
  <div class="bot-header">
238
  <div class="bot-name">${bot.botName}</div>
239
+ <div class="status ${statusClass}">${bot.status}</div>
240
  </div>
241
  <div class="bot-info">
242
+ <div>Deaths: ${bot.deathCount}</div>
243
+ ${bot.status === 'Connected' ? `<div>Uptime: ${formatUptime(bot.uptime)}</div>` : ''}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  </div>
245
+ ${showRejoinButton ? `
246
+ <button class="btn-rejoin"
247
+ onclick="reconnectBot('${bot.botName}')"
248
+ ${!canRejoinNow ? 'disabled' : ''}>
249
+ ${canRejoinNow ? 'Rejoin' : 'Wait to Rejoin'}
250
+ </button>
251
+ ${!canRejoinNow && timeRemaining > 0 ?
252
+ `<div class="timer">Can rejoin in: ${formatUptime(timeRemaining)}</div>` : ''}
253
+ ` : ''}
254
  </div>
255
  `;
256
  });
 
268
 
269
  function formatUptime(seconds) {
270
  if (seconds === 0) return '0s';
 
271
  const hours = Math.floor(seconds / 3600);
272
  const minutes = Math.floor((seconds % 3600) / 60);
273
  const secs = seconds % 60;
 
281
  }
282
  }
283
 
 
 
 
 
 
284
  function reconnectBot(botName) {
285
  socket.emit('reconnectBot', botName);
286
  }
287
 
288
  function refreshSheet() {
289
  socket.emit('refreshSheet');
 
290
  }
291
 
292
+ // Update UI every 2 seconds to show timer countdown
293
+ setInterval(() => {
294
+ if (botsData.length > 0) {
295
+ botsData.forEach(bot => {
296
+ if (bot.timeUntilReconnect > 0) {
297
+ bot.timeUntilReconnect = Math.max(0, bot.timeUntilReconnect - 2);
298
+ }
299
+ bot.canReconnect = bot.timeUntilReconnect === 0 &&
300
+ (bot.status === 'Disconnected' || bot.status === 'Dead') &&
301
+ bot.inSheet;
302
+ });
303
+ updateUI();
304
+ }
305
+ }, 2000);
306
  </script>
307
  </body>
308
  </html>