feat: Add billing routes in server.js for retrieving and updating billing data, and integrate BillingManager in App.jsx for navigation
Publish Fast Tabler Docker image / build-and-push-fast (push) Failing after 6m7s

This commit is contained in:
2025-07-30 04:16:05 +07:00
parent 093d3e07db
commit c6fbfee2b3
4 changed files with 1169 additions and 0 deletions
+69
View File
@@ -295,6 +295,75 @@ app.post('/api/servers', async (req, res) => {
}
});
// --- Billing Routes ---
// Get billing data from S3
app.get('/api/billing', async (req, res) => {
const params = {
Bucket: BUCKET_NAME,
Key: 'servers-billing.json',
};
try {
const data = await s3.getObject(params).promise();
const fileContent = data.Body.toString('utf-8');
let billingData = [];
try {
billingData = JSON.parse(fileContent);
// Ensure it's an array
if (!Array.isArray(billingData)) {
billingData = [];
}
} catch (parseError) {
console.error('Error parsing servers-billing.json:', parseError);
billingData = [];
}
res.json(billingData);
} 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 billing data in S3
app.post('/api/billing', async (req, res) => {
const { domains: billingData } = req.body; // Keep name 'domains' for consistency
// Validate billing data structure
if (!Array.isArray(billingData)) {
return res.status(400).send('Billing data must be an array');
}
// Validate each billing item has required fields
for (let i = 0; i < billingData.length; i++) {
const item = billingData[i];
if (!item.hostName || !item.nodeName || !item.country || !item.provider) {
return res.status(400).send(`Billing item at index ${i} is missing required fields`);
}
}
const params = {
Bucket: BUCKET_NAME,
Key: 'servers-billing.json',
Body: JSON.stringify(billingData, 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');
}
});
// --- Filters Routes (JSON format) ---
// Get filters from S3