import type { PushNotificationAction, PushNotificationPayload, } from "../types"; export interface SirrusDashboardPushCampaign { campaignId: string; templateId?: string; messageId?: string; title: string; body: string; subtitle?: string; imageUrl?: string; gifUrl?: string; videoUrl?: string; deeplinkUrl?: string; channelId?: string; categoryId?: string; sound?: string; actions?: PushNotificationAction[]; data?: Record; } export type SirrusPushDataPayload = Record; const firstValue = (...values: Array): string | undefined => { return values.find((value) => typeof value === "string" && value.trim().length > 0); }; const putString = ( target: SirrusPushDataPayload, key: string, value: string | number | boolean | null | undefined ): void => { if (value === undefined || value === null || value === "") { return; } target[key] = String(value); }; const normalizeAction = ( value: unknown, index: number ): PushNotificationAction | null => { if (!value || typeof value !== "object" || Array.isArray(value)) { return null; } const action = value as Record; const id = firstValue( action.id as string | undefined, action.actionId as string | undefined, action.action_id as string | undefined, action.identifier as string | undefined, action.postback as string | undefined, action.actionType as string | undefined ) ?? `action_${index + 1}`; const title = firstValue( action.title as string | undefined, action.label as string | undefined, action.name as string | undefined, action.text as string | undefined ) ?? "Open"; const label = firstValue( action.label as string | undefined, action.title as string | undefined, action.name as string | undefined, action.text as string | undefined ) ?? title; return { id, title, label, actionType: firstValue(action.actionType as string | undefined), postback: firstValue(action.postback as string | undefined), deeplinkUrl: firstValue( action.deeplinkUrl as string | undefined, action.deepLinkUrl as string | undefined, action.deep_link_url as string | undefined ), destructive: action.destructive as boolean | undefined, foreground: action.foreground as boolean | undefined, authenticationRequired: (action.authenticationRequired ?? action.authentication_required) as | boolean | undefined, }; }; const parseActions = (value?: string): PushNotificationAction[] | undefined => { if (!value) { return undefined; } try { const parsed = JSON.parse(value) as unknown; if (!Array.isArray(parsed)) { return undefined; } const actions = parsed .map((action, index) => normalizeAction(action, index)) .filter((action): action is PushNotificationAction => action !== null); return actions.length > 0 ? actions : undefined; } catch { return undefined; } }; export const isSirrusPushDataPayload = ( data: Record ): boolean => { const source = firstValue( data.source, data.sdk_source, data.vendor, data.provider )?.toLowerCase(); return ( source === "martech" || Boolean(data.sirrus_campaign_id || data.sirrusCampaignId) || Boolean(data.sirrus_template_id || data.sirrusTemplateId) ); }; export const buildSirrusPushDataPayload = ( campaign: SirrusDashboardPushCampaign ): SirrusPushDataPayload => { const payload: SirrusPushDataPayload = { source: "martech", sdk_source: "martech", sirrus_campaign_id: campaign.campaignId, }; putString(payload, "sirrus_template_id", campaign.templateId); putString(payload, "sirrus_message_id", campaign.messageId); putString(payload, "title", campaign.title); putString(payload, "body", campaign.body); putString(payload, "subtitle", campaign.subtitle); putString(payload, "sirrus_image_url", campaign.imageUrl); putString(payload, "sirrus_attachment_url", campaign.imageUrl); putString(payload, "sirrus_gif_url", campaign.gifUrl); putString(payload, "sirrus_video_url", campaign.videoUrl); putString(payload, "sirrus_deeplink_url", campaign.deeplinkUrl); putString(payload, "sirrus_channel_id", campaign.channelId); putString(payload, "sirrus_category_id", campaign.categoryId); putString(payload, "sirrus_sound", campaign.sound); if (campaign.actions && campaign.actions.length > 0) { const actions = campaign.actions .map((action, index) => normalizeAction(action, index)) .filter((action): action is PushNotificationAction => action !== null); if (actions.length > 0) { payload.sirrus_actions = JSON.stringify(actions); } } for (const [key, value] of Object.entries(campaign.data ?? {})) { putString(payload, key, value); } return payload; }; export const mapSirrusPushDataPayload = ( data: Record ): PushNotificationPayload => { return { title: firstValue(data.title, data.sirrus_title), body: firstValue(data.body, data.sirrus_body), subtitle: firstValue(data.subtitle, data.sirrus_subtitle), imageUrl: firstValue( data.sirrus_image_url, data.sirrusImageUrl, data.sirrus_attachment_url, data.sirrusAttachmentUrl, data.imageUrl, data.image_url, data.image, data.mediaUrl, data.media_url ), gifUrl: firstValue(data.sirrus_gif_url, data.gifUrl, data.gif_url), videoUrl: firstValue(data.sirrus_video_url, data.videoUrl, data.video_url), deeplinkUrl: firstValue( data.sirrus_deeplink_url, data.deeplinkUrl, data.deepLinkUrl, data.deepLinkUri, data.deep_link_url, data.deep_link_uri, data.link ), campaignId: firstValue(data.sirrus_campaign_id, data.sirrusCampaignId), templateId: firstValue(data.sirrus_template_id, data.sirrusTemplateId), messageId: firstValue( data.sirrus_message_id, data.sirrusMessageId, data.messageId, data.message_id, data["gcm.message_id"], data["google.message_id"] ), provider: "fcm", channelId: firstValue(data.sirrus_channel_id, data.channelId, data.channel_id), categoryId: firstValue(data.sirrus_category_id, data.categoryId, data.category_id), sound: firstValue(data.sirrus_sound, data.sound), actions: parseActions(firstValue(data.sirrus_actions, data.sirrusActions, data.actions)), rawPayload: Object.fromEntries( Object.entries(data).filter((entry): entry is [string, string] => { return typeof entry[1] === "string"; }) ), }; };