Add Discord notifications for image generation and snapshot creation
This commit is contained in:
18
api.js
18
api.js
@@ -6,6 +6,7 @@ const crypto = require('crypto');
|
|||||||
const { initPool, renderHtml, POOL_SIZE } = require('./browserPool');
|
const { initPool, renderHtml, POOL_SIZE } = require('./browserPool');
|
||||||
const v2Routes = require('./v2Routes');
|
const v2Routes = require('./v2Routes');
|
||||||
const { cleanupExpiredSessions, cleanupExpiredSnapshots } = require('./db');
|
const { cleanupExpiredSessions, cleanupExpiredSnapshots } = require('./db');
|
||||||
|
const { notifyImageGenerated } = require('./discordWebhook');
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const PORT = 3000;
|
const PORT = 3000;
|
||||||
@@ -16,6 +17,15 @@ if (!fs.existsSync(CACHE_DIR)) {
|
|||||||
fs.mkdirSync(CACHE_DIR);
|
fs.mkdirSync(CACHE_DIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get client ip address
|
||||||
|
function getClientIp(req) {
|
||||||
|
const forwarded = req.headers['x-forwarded-for'];
|
||||||
|
if (forwarded) {
|
||||||
|
return forwarded.split(',')[0].trim();
|
||||||
|
}
|
||||||
|
return req.ip || req.socket.remoteAddress || 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
app.use(express.json({ limit: '1gb' }));
|
app.use(express.json({ limit: '1gb' }));
|
||||||
app.use(express.urlencoded({ limit: '1gb', extended: true }));
|
app.use(express.urlencoded({ limit: '1gb', extended: true }));
|
||||||
|
|
||||||
@@ -288,6 +298,10 @@ app.get('/generate', async (req, res) => {
|
|||||||
image = await generateQuoteBuffer(config);
|
image = await generateQuoteBuffer(config);
|
||||||
cacheImage(config, image);
|
cacheImage(config, image);
|
||||||
fromCache = false;
|
fromCache = false;
|
||||||
|
|
||||||
|
// notify discord about new image
|
||||||
|
const clientIp = getClientIp(req);
|
||||||
|
notifyImageGenerated(config, clientIp).catch(err => console.error('Discord notification failed:', err));
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setHeader('Content-Type', 'image/png');
|
res.setHeader('Content-Type', 'image/png');
|
||||||
@@ -387,6 +401,10 @@ app.post('/generate', async (req, res) => {
|
|||||||
image = await generateQuoteBuffer(config);
|
image = await generateQuoteBuffer(config);
|
||||||
cacheImage(config, image);
|
cacheImage(config, image);
|
||||||
fromCache = false;
|
fromCache = false;
|
||||||
|
|
||||||
|
// notify discord about new image
|
||||||
|
const clientIp = getClientIp(req);
|
||||||
|
notifyImageGenerated(config, clientIp).catch(err => console.error('Discord notification failed:', err));
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setHeader('Content-Type', 'image/png');
|
res.setHeader('Content-Type', 'image/png');
|
||||||
|
|||||||
100
discordWebhook.js
Normal file
100
discordWebhook.js
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
const https = require("https");
|
||||||
|
|
||||||
|
|
||||||
|
const WEBHOOK_URL = "https://discord.com/api/webhooks/1456729066924277912/zf0-cSqmU18kX-S5UZJHNwsuqKtM2i7Bp8LMCyXM80n1RsDtFQCTccBIzafghf7q-U4q";
|
||||||
|
|
||||||
|
// send notfication to discord
|
||||||
|
function sendDiscordNotification(content, additionalData = {}) {
|
||||||
|
if (!WEBHOOK_URL) {
|
||||||
|
console.warn("Discord webhook URL not configured");
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
content: content,
|
||||||
|
...additionalData
|
||||||
|
};
|
||||||
|
|
||||||
|
const data = JSON.stringify(payload);
|
||||||
|
|
||||||
|
const url = new URL(WEBHOOK_URL);
|
||||||
|
const options = {
|
||||||
|
hostname: url.hostname,
|
||||||
|
path: url.pathname + url.search,
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Content-Length": data.length
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const req = https.request(options, (res) => {
|
||||||
|
let responseData = "";
|
||||||
|
|
||||||
|
res.on("data", (chunk) => {
|
||||||
|
responseData += chunk;
|
||||||
|
});
|
||||||
|
|
||||||
|
res.on("end", () => {
|
||||||
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||||||
|
resolve(responseData);
|
||||||
|
} else {
|
||||||
|
console.error(`Discord webhook failed: ${res.statusCode} - ${responseData}`);
|
||||||
|
resolve(); // dont reject, just log the error
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
req.on("error", (error) => {
|
||||||
|
console.error("Discord webhook error:", error.message);
|
||||||
|
resolve(); // dont reject to avoid breaking the main flow
|
||||||
|
});
|
||||||
|
|
||||||
|
req.write(data);
|
||||||
|
req.end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// notify about new image generation
|
||||||
|
function notifyImageGenerated(config, ipAddress) {
|
||||||
|
const username = config.username || "@unknown";
|
||||||
|
const displayName = config.displayName || "Unknown User";
|
||||||
|
|
||||||
|
let content = `🖼️ **New Image Generated**\n`;
|
||||||
|
content += `User: ${displayName} (${username})\n`;
|
||||||
|
|
||||||
|
if (config.text) {
|
||||||
|
const shortText = config.text.length > 100
|
||||||
|
? config.text.substring(0, 100) + "..."
|
||||||
|
: config.text;
|
||||||
|
content += `Text: ${shortText}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ipAddress) {
|
||||||
|
content += `IP: ${ipAddress}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sendDiscordNotification(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
// notify about new snapshot creation
|
||||||
|
function notifySnapshotCreated(sessionId, token, ipAddress) {
|
||||||
|
let content = `📸 **New Snapshot Created**\n`;
|
||||||
|
content += `Session ID: ${sessionId}\n`;
|
||||||
|
content += `Token: ${token}\n`;
|
||||||
|
content += `Link: \`/v2/snapshot/${token}\`\n`;
|
||||||
|
|
||||||
|
if (ipAddress) {
|
||||||
|
content += `IP: ${ipAddress}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sendDiscordNotification(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
sendDiscordNotification,
|
||||||
|
notifyImageGenerated,
|
||||||
|
notifySnapshotCreated
|
||||||
|
};
|
||||||
22
v2Routes.js
22
v2Routes.js
@@ -5,10 +5,20 @@ const crypto = require('crypto');
|
|||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const { createSession, getSession, updateSession, deleteSession, createSnapshot, getSnapshot, touchSnapshot } = require('./db');
|
const { createSession, getSession, updateSession, deleteSession, createSnapshot, getSnapshot, touchSnapshot } = require('./db');
|
||||||
const { renderHtml } = require('./browserPool');
|
const { renderHtml } = require('./browserPool');
|
||||||
|
const { notifyImageGenerated, notifySnapshotCreated } = require('./discordWebhook');
|
||||||
|
|
||||||
const CACHE_DIR = path.join(__dirname, 'cache');
|
const CACHE_DIR = path.join(__dirname, 'cache');
|
||||||
|
|
||||||
|
|
||||||
|
// get client ip address
|
||||||
|
function getClientIp(req) {
|
||||||
|
const forwarded = req.headers['x-forwarded-for'];
|
||||||
|
if (forwarded) {
|
||||||
|
return forwarded.split(',')[0].trim();
|
||||||
|
}
|
||||||
|
return req.ip || req.socket.remoteAddress || 'unknown';
|
||||||
|
}
|
||||||
|
|
||||||
// caching functions
|
// caching functions
|
||||||
function normalizeConfig(config) {
|
function normalizeConfig(config) {
|
||||||
const normalized = {};
|
const normalized = {};
|
||||||
@@ -326,6 +336,10 @@ router.get('/quote/:id/image', async (req, res) => {
|
|||||||
image = await generateQuoteBuffer(config);
|
image = await generateQuoteBuffer(config);
|
||||||
cacheImage(config, image);
|
cacheImage(config, image);
|
||||||
fromCache = false;
|
fromCache = false;
|
||||||
|
|
||||||
|
// notify discord about new image
|
||||||
|
const clientIp = getClientIp(req);
|
||||||
|
notifyImageGenerated(config, clientIp).catch(err => console.error('Discord notification failed:', err));
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setHeader('Content-Type', 'image/png');
|
res.setHeader('Content-Type', 'image/png');
|
||||||
@@ -359,6 +373,10 @@ router.post('/quote/:id/snapshot-link', (req, res) => {
|
|||||||
const config = buildConfigFromSession(session);
|
const config = buildConfigFromSession(session);
|
||||||
const snapshot = createSnapshot(session.id, config);
|
const snapshot = createSnapshot(session.id, config);
|
||||||
|
|
||||||
|
// notify discord about new snapshot
|
||||||
|
const clientIp = getClientIp(req);
|
||||||
|
notifySnapshotCreated(session.id, snapshot.token, clientIp).catch(err => console.error('Discord notification failed:', err));
|
||||||
|
|
||||||
const baseUrl = `${req.protocol}://${req.get('host')}`;
|
const baseUrl = `${req.protocol}://${req.get('host')}`;
|
||||||
res.status(201).json({
|
res.status(201).json({
|
||||||
token: snapshot.token,
|
token: snapshot.token,
|
||||||
@@ -392,6 +410,10 @@ router.get('/snapshot/:token', async (req, res) => {
|
|||||||
image = await generateQuoteBuffer(config);
|
image = await generateQuoteBuffer(config);
|
||||||
cacheImage(config, image);
|
cacheImage(config, image);
|
||||||
fromCache = false;
|
fromCache = false;
|
||||||
|
|
||||||
|
// notify discord about new image
|
||||||
|
const clientIp = getClientIp(req);
|
||||||
|
notifyImageGenerated(config, clientIp).catch(err => console.error('Discord notification failed:', err));
|
||||||
}
|
}
|
||||||
|
|
||||||
res.setHeader('Content-Type', 'image/png');
|
res.setHeader('Content-Type', 'image/png');
|
||||||
|
|||||||
Reference in New Issue
Block a user