import type { FastifyReply, FastifyRequest } from 'fastify'; import { generateDeviceId, parseUserAgent } from '@openpanel/common/server'; import { getSalts } from '@openpanel/db'; import { getEventsGroupQueueShard } from '@openpanel/queue'; import type { PostEventPayload } from '@openpanel/sdk'; import { generateId, slug } from '@openpanel/common'; import { getGeoLocation } from '@openpanel/geo'; import { getStringHeaders, getTimestamp } from './track.controller'; export async function postEvent( request: FastifyRequest<{ Body: PostEventPayload; }>, reply: FastifyReply, ) { const { timestamp, isTimestampFromThePast } = getTimestamp( request.timestamp, request.body, ); const ip = request.clientIp; const ua = request.headers['user-agent']; const projectId = request.client?.projectId; const headers = getStringHeaders(request.headers); if (!projectId) { reply.status(400).send('missing origin'); return; } const [salts, geo] = await Promise.all([getSalts(), getGeoLocation(ip)]); const currentDeviceId = ua ? generateDeviceId({ salt: salts.current, origin: projectId, ip, ua, }) : ''; const previousDeviceId = ua ? generateDeviceId({ salt: salts.previous, origin: projectId, ip, ua, }) : ''; const uaInfo = parseUserAgent(ua, request.body?.properties); const groupId = uaInfo.isServer ? request.body?.profileId ? `${projectId}:${request.body?.profileId}` : `${projectId}:${generateId()}` : currentDeviceId; const jobId = [ slug(request.body.name), timestamp, projectId, currentDeviceId, groupId, ] .filter(Boolean) .join('-'); await getEventsGroupQueueShard(groupId).add({ orderMs: new Date(timestamp).getTime(), data: { projectId, headers, event: { ...request.body, timestamp, isTimestampFromThePast, }, uaInfo, geo, currentDeviceId, previousDeviceId, }, groupId, jobId, }); reply.status(202).send('ok'); }