feat: Add server management functionality with new API endpoints and update UI to include server statistics
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 14m34s

This commit is contained in:
2025-07-10 08:21:52 +07:00
parent 2738455c1a
commit 86f6304382
6 changed files with 705 additions and 13 deletions
+74 -3
View File
@@ -126,16 +126,87 @@ app.post('/api/asns', async (req, res) => {
}
});
// --- Servers Routes (JSON format) ---
// Get servers from S3
app.get('/api/servers', async (req, res) => {
const params = {
Bucket: BUCKET_NAME,
Key: 'servers.json',
};
try {
const data = await s3.getObject(params).promise();
const fileContent = data.Body.toString('utf-8');
let servers = [];
try {
servers = JSON.parse(fileContent);
// Ensure it's an array
if (!Array.isArray(servers)) {
servers = [];
}
} catch (parseError) {
console.error('Error parsing servers.json:', parseError);
servers = [];
}
res.json(servers);
} catch (error) {
if (error.code === 'NoSuchKey') {
res.json([]); // Return empty array if file does not exist
} else {
console.error(error);
res.status(500).send('Error reading from S3');
}
}
});
// Update servers in S3
app.post('/api/servers', async (req, res) => {
const { domains: servers } = req.body; // Keep name 'domains' for consistency
// Validate servers structure
if (!Array.isArray(servers)) {
return res.status(400).send('Servers must be an array');
}
// Validate each server has required fields
for (let i = 0; i < servers.length; i++) {
const server = servers[i];
if (!server.ip || !server.dns || !server.country || !server.provider || !server.tunnel) {
return res.status(400).send(`Server at index ${i} is missing required fields`);
}
}
const params = {
Bucket: BUCKET_NAME,
Key: 'servers.json',
Body: JSON.stringify(servers, null, 2), // Pretty print JSON
ContentType: 'application/json',
};
try {
await s3.putObject(params).promise();
res.send('File updated successfully');
} catch (error) {
console.error(error);
res.status(500).send('Error writing to S3');
}
});
// Новый эндпоинт для получения дат последнего изменения файлов S3
app.get('/api/s3/last-modified', async (req, res) => {
try {
const [domainsHead, asnsHead] = await Promise.all([
const [domainsHead, asnsHead, serversHead] = await Promise.all([
s3.headObject({ Bucket: BUCKET_NAME, Key: 'domains.txt' }).promise(),
s3.headObject({ Bucket: BUCKET_NAME, Key: 'asns.txt' }).promise()
s3.headObject({ Bucket: BUCKET_NAME, Key: 'asns.txt' }).promise(),
s3.headObject({ Bucket: BUCKET_NAME, Key: 'servers.json' }).promise()
]);
res.json({
domainsLastModified: domainsHead.LastModified ? domainsHead.LastModified.toISOString() : null,
asnsLastModified: asnsHead.LastModified ? asnsHead.LastModified.toISOString() : null
asnsLastModified: asnsHead.LastModified ? asnsHead.LastModified.toISOString() : null,
serversLastModified: serversHead.LastModified ? serversHead.LastModified.toISOString() : null
});
} catch (error) {
console.error(error);