import { getClientIp } from '@/utils/get-client-ip'; import type { FastifyReply, FastifyRequest } from 'fastify'; import { generateDeviceId, parseUserAgent } from '@openpanel/common/server'; import { getSalts } from '@openpanel/db'; import { eventsGroupQueue } from '@openpanel/queue'; import type { PostEventPayload } from '@openpanel/sdk'; import { checkDuplicatedEvent } from '@/utils/deduplicate'; import { generateId } 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 = getClientIp(request)!; 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 = generateDeviceId({ salt: salts.current, origin: projectId, ip, ua, }); const previousDeviceId = generateDeviceId({ salt: salts.previous, origin: projectId, ip, ua, }); if ( await checkDuplicatedEvent({ reply, payload: { ...request.body, timestamp, previousDeviceId, currentDeviceId, }, projectId, }) ) { return; } const uaInfo = parseUserAgent(ua, request.body?.properties); const groupId = uaInfo.isServer ? request.body?.profileId ? `${projectId}:${request.body?.profileId}` : `${projectId}:${generateId()}` : currentDeviceId; await eventsGroupQueue.add({ orderMs: new Date(timestamp).getTime(), data: { projectId, headers, event: { ...request.body, timestamp, isTimestampFromThePast, }, geo, currentDeviceId, previousDeviceId, }, groupId, }); reply.status(202).send('ok'); }