fix(track): alias event tracking to /api/pulse to avoid adblocker filters

This commit is contained in:
2026-10-17 11:37:55 +07:00
parent 388af7a413
commit 194a89f89a
3 changed files with 6 additions and 4 deletions
+4 -2
View File
@@ -494,7 +494,7 @@ app.post('/api/open-explorer', async (req, reply) => {
// a beacon from every page, so it must never be a way to probe who is signed in
// — it answers 204 whatever happens and echoes nothing back.
const allowTrack = limiter(300, 60_000);
app.post('/api/events', async (req, reply) => {
const handleEventTrack = async (req: Parameters<typeof app.post>[1] extends (req: infer R, ...args: any[]) => any ? R : any, reply: any) => {
const b = bodyOf(req);
const ip = clientIp(req);
if (!b || !isEventKind(b.kind) || !allowTrack(ip || 'unknown')) return reply.status(204).send();
@@ -519,7 +519,9 @@ app.post('/api/events', async (req, reply) => {
device: ua.device,
});
return reply.status(204).send();
});
};
app.post('/api/events', handleEventTrack);
app.post('/api/pulse', handleEventTrack);
// The film strip's ratings. Public and unauthenticated for the same reason the
// counter is: any visitor may score a frame once, and the vote is held against
+1 -1
View File
@@ -3,7 +3,7 @@
// control, so it doubles as the feature's name. Nothing here may break the app:
// every path is wrapped, a refused beacon is simply not counted, and a visitor
// who asked not to be tracked is left alone.
const ENDPOINT = '/api/events';
const ENDPOINT = '/api/pulse';
type Kind = 'view' | 'click';
+1 -1
View File
@@ -1 +1 @@
f258217d804e6ee5c0720730b284e1c8045a6692758aeb0570723239e2974617 recipescam-images.tar.gz
b00e823e83ef29a57ba7f479edcc89de34fc2dd9bec7d796ba95cbfa680da7a2 recipescam-images.tar.gz