Add engagement metrics and health check logging to API

This commit is contained in:
ImBenji
2026-01-01 08:12:53 +00:00
parent 635f8b2001
commit 48fce1564a
2 changed files with 85 additions and 2 deletions

86
api.js
View File

@@ -18,6 +18,11 @@ app.use(express.urlencoded({ limit: '1gb', extended: true }));
// Request logging middleware
app.use((req, res, next) => {
// skip logging health checks
if (req.url === '/health') {
return next();
}
const timestamp = new Date().toISOString();
console.log(`\n[${timestamp}] ${req.method} ${req.url}`);
@@ -134,6 +139,23 @@ function cleanupOldCache() {
}
}
function formatCount(num) {
if (num === null || num === undefined) return '0';
num = parseInt(num);
if (num >= 1000000000) {
return (num / 1000000000).toFixed(1).replace(/\.0$/, '') + 'B';
}
if (num >= 1000000) {
return (num / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
}
if (num >= 1000) {
return (num / 1000).toFixed(1).replace(/\.0$/, '') + 'K';
}
return num.toString();
}
function formatTimestamp(epoch) {
const date = new Date(epoch * 1000);
@@ -160,6 +182,28 @@ async function generateQuoteBuffer(config) {
? `<div class="tweet-image-container" style="margin-bottom:12px;border-radius:16px;overflow:hidden;border:1px solid rgb(47,51,54);"><img src="${config.imageUrl}" style="width:100%;display:block;" /></div>`
: '';
// Only show engagement bar if all fields provided
const engagementHtml = config.engagement ? `
<div class="engagement-bar">
<div class="engagement-item">
<span class="engagement-count">${config.engagement.replies}</span>
<span class="engagement-label">Replies</span>
</div>
<div class="engagement-item">
<span class="engagement-count">${config.engagement.retweets}</span>
<span class="engagement-label">Reposts</span>
</div>
<div class="engagement-item">
<span class="engagement-count">${config.engagement.likes}</span>
<span class="engagement-label">Likes</span>
</div>
<div class="engagement-item">
<span class="engagement-count">${config.engagement.views}</span>
<span class="engagement-label">Views</span>
</div>
</div>
` : '';
const html = `<!DOCTYPE html>
<html>
<head>
@@ -231,6 +275,28 @@ async function generateQuoteBuffer(config) {
font-size: 15px;
color: rgb(113, 118, 123);
}
.engagement-bar {
display: flex;
gap: 24px;
padding: 12px 0;
margin-top: 12px;
border-top: 1px solid rgb(47, 51, 54);
}
.engagement-item {
display: flex;
gap: 4px;
}
.engagement-count {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 14px;
font-weight: 700;
color: rgb(231, 233, 234);
}
.engagement-label {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
font-size: 14px;
color: rgb(113, 118, 123);
}
</style>
</head>
<body>
@@ -246,6 +312,7 @@ async function generateQuoteBuffer(config) {
<div class="tweet-text">${config.text}</div>
${imageHtml}
<div class="tweet-time">${config.timestamp}</div>
${engagementHtml}
</div>
</div>
<script>
@@ -278,7 +345,7 @@ app.get('/generate', async (req, res) => {
text: req.query.text || "No text provided",
imageUrl: fixDataUri(req.query.imageUrl) || null,
timestamp: timestamp,
viewsCount: req.query.viewsCount || "0"
engagement: null
};
// Check cache first
@@ -344,6 +411,21 @@ app.post('/generate', async (req, res) => {
const username = req.body.username?.trim();
// Only include engagement if all fields are provded
let engagement = null;
if (req.body.engagement &&
req.body.engagement.likes !== undefined &&
req.body.engagement.retweets !== undefined &&
req.body.engagement.replies !== undefined &&
req.body.engagement.views !== undefined) {
engagement = {
likes: formatCount(req.body.engagement.likes),
retweets: formatCount(req.body.engagement.retweets),
replies: formatCount(req.body.engagement.replies),
views: formatCount(req.body.engagement.views)
};
}
const config = {
displayName: req.body.displayName || "Anonymous",
username: (username && username !== "@") ? username : "@anonymous",
@@ -351,7 +433,7 @@ app.post('/generate', async (req, res) => {
text: req.body.text || "No text provided",
imageUrl: fixDataUri(req.body.imageUrl) || null,
timestamp: timestamp,
viewsCount: req.body.viewsCount || "0"
engagement: engagement
};
// Check cache first