2026-06-18 01:28:43 -05:00
"use strict" ;
var _ _createBinding = ( this && this . _ _createBinding ) || ( Object . create ? ( function ( o , m , k , k2 ) {
if ( k2 === undefined ) k2 = k ;
var desc = Object . getOwnPropertyDescriptor ( m , k ) ;
if ( ! desc || ( "get" in desc ? ! m . _ _esModule : desc . writable || desc . configurable ) ) {
desc = { enumerable : true , get : function ( ) { return m [ k ] ; } } ;
}
Object . defineProperty ( o , k2 , desc ) ;
} ) : ( function ( o , m , k , k2 ) {
if ( k2 === undefined ) k2 = k ;
o [ k2 ] = m [ k ] ;
} ) ) ;
var _ _setModuleDefault = ( this && this . _ _setModuleDefault ) || ( Object . create ? ( function ( o , v ) {
Object . defineProperty ( o , "default" , { enumerable : true , value : v } ) ;
} ) : function ( o , v ) {
o [ "default" ] = v ;
} ) ;
var _ _importStar = ( this && this . _ _importStar ) || ( function ( ) {
var ownKeys = function ( o ) {
ownKeys = Object . getOwnPropertyNames || function ( o ) {
var ar = [ ] ;
for ( var k in o ) if ( Object . prototype . hasOwnProperty . call ( o , k ) ) ar [ ar . length ] = k ;
return ar ;
} ;
return ownKeys ( o ) ;
} ;
return function ( mod ) {
if ( mod && mod . _ _esModule ) return mod ;
var result = { } ;
if ( mod != null ) for ( var k = ownKeys ( mod ) , i = 0 ; i < k . length ; i ++ ) if ( k [ i ] !== "default" ) _ _createBinding ( result , mod , k [ i ] ) ;
_ _setModuleDefault ( result , mod ) ;
return result ;
} ;
} ) ( ) ;
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
exports . onGameSessionUpdate = void 0 ;
const functions = _ _importStar ( require ( "firebase-functions" ) ) ;
const admin = _ _importStar ( require ( "firebase-admin" ) ) ;
/ * *
* Firestore trigger that notifies partners when a game session is created or completed .
*
* Path : couples / { coupleId } / sessions / { sessionId }
* Condition : onWrite ( create , update , delete )
* /
exports . onGameSessionUpdate = functions . firestore
. document ( 'couples/{coupleId}/sessions/{sessionId}' )
. onWrite ( async ( change , context ) => {
2026-06-22 08:53:23 -05:00
var _a , _b , _c , _d , _e , _f , _g , _h , _j , _k , _l , _m ;
2026-06-18 01:28:43 -05:00
const { coupleId , sessionId } = context . params ;
const db = admin . firestore ( ) ;
const messaging = admin . messaging ( ) ;
// Get the session document
const sessionDoc = await db . collection ( 'couples' ) . doc ( coupleId ) . collection ( 'sessions' ) . doc ( sessionId ) . get ( ) ;
const session = sessionDoc . data ( ) ;
if ( ! session ) {
console . log ( ` [onGameSessionUpdate] session ${ sessionId } not found, skipping ` ) ;
return ;
}
// Get couple info
const coupleDoc = await db . collection ( 'couples' ) . doc ( coupleId ) . get ( ) ;
if ( ! coupleDoc . exists ) {
console . warn ( ` [onGameSessionUpdate] couple ${ coupleId } not found ` ) ;
return ;
}
const coupleData = ( _a = coupleDoc . data ( ) ) !== null && _a !== void 0 ? _a : { } ;
const userIds = ( ( _b = coupleData . userIds ) !== null && _b !== void 0 ? _b : [ ] ) ;
if ( userIds . length !== 2 ) {
console . warn ( ` [onGameSessionUpdate] invalid couple ${ coupleId } : expected 2 users, got ${ userIds . length } ` ) ;
return ;
}
const partnerA = userIds [ 0 ] ;
const partnerB = userIds [ 1 ] ;
// Get user display names for notifications
const userA = await db . collection ( 'users' ) . doc ( partnerA ) . get ( ) ;
const userB = await db . collection ( 'users' ) . doc ( partnerB ) . get ( ) ;
const partnerAName = ( _d = ( _c = userA . data ( ) ) === null || _c === void 0 ? void 0 : _c . displayName ) !== null && _d !== void 0 ? _d : 'Partner A' ;
const partnerBName = ( _f = ( _e = userB . data ( ) ) === null || _e === void 0 ? void 0 : _e . displayName ) !== null && _f !== void 0 ? _f : 'Partner B' ;
// Check if session was just created (status = "active")
const previousData = ( _g = change . before . data ( ) ) !== null && _g !== void 0 ? _g : { } ;
const currentData = ( _h = change . after . data ( ) ) !== null && _h !== void 0 ? _h : { } ;
const wasInactive = ( ( _j = previousData . status ) !== null && _j !== void 0 ? _j : '' ) !== 'active' ;
const isActiveNow = currentData . status === 'active' ;
if ( wasInactive && isActiveNow ) {
// New session started - notify the other partner
const startedBy = currentData . startedByUserId ;
const gameType = ( _k = currentData . gameType ) !== null && _k !== void 0 ? _k : 'wheel' ;
const partnerId = startedBy === partnerA ? partnerB : partnerA ;
const partnerName = startedBy === partnerA ? partnerBName : partnerAName ;
2026-06-22 08:53:23 -05:00
await notifyPartner ( db , messaging , partnerId , partnerName , gameType , 'partner_started_game' , ` ${ partnerName } has started a game. Tap to join! ` , coupleId ) ;
2026-06-18 01:28:43 -05:00
return ;
}
// Check if session was completed
const wasActive = ( ( _l = previousData . status ) !== null && _l !== void 0 ? _l : '' ) === 'active' ;
const isCompletedNow = currentData . status === 'completed' ;
if ( wasActive && isCompletedNow ) {
const completedBy = currentData . startedByUserId ;
const partnerId = completedBy === partnerA ? partnerB : partnerA ;
const completingPartnerName = completedBy === partnerA ? partnerAName : partnerBName ;
2026-06-22 08:53:23 -05:00
const gt = ( _m = currentData . gameType ) !== null && _m !== void 0 ? _m : 'wheel' ;
2026-06-18 01:28:43 -05:00
const partnerCompletedAt = currentData . partnerCompletedAt ;
if ( partnerCompletedAt ) {
2026-06-22 08:53:23 -05:00
await notifyPartner ( db , messaging , partnerA , partnerAName , gt , 'partner_finished_game' , ` ${ partnerBName } has finished the game. Tap to see the results! ` , coupleId ) ;
await notifyPartner ( db , messaging , partnerB , partnerBName , gt , 'partner_finished_game' , ` ${ partnerAName } has finished the game. Tap to see the results! ` , coupleId ) ;
2026-06-18 01:28:43 -05:00
}
else {
2026-06-22 08:53:23 -05:00
await notifyPartner ( db , messaging , partnerId , completingPartnerName , gt , 'partner_finished_game' , ` ${ completingPartnerName } has finished. Tap to continue playing! ` , coupleId ) ;
2026-06-18 01:28:43 -05:00
}
return ;
}
} ) ;
/ * *
* Send notification to partner via FCM and write to notification _queue .
* /
2026-06-22 08:53:23 -05:00
async function notifyPartner ( db , messaging , partnerId , partnerName , gameType , notificationType , body , coupleId ) {
2026-06-18 01:28:43 -05:00
var _a ;
const notificationPayload = {
type : notificationType ,
title : ` ${ partnerName } is playing ` ,
body : body ,
} ;
// Write an in-app notification record for the partner
await db
. collection ( 'users' )
. doc ( partnerId )
. collection ( 'notification_queue' )
. add ( Object . assign ( Object . assign ( { } , notificationPayload ) , { read : false , createdAt : admin . firestore . FieldValue . serverTimestamp ( ) } ) ) ;
// Collect the partner's FCM tokens
const tokens = [ ] ;
const partnerUserDoc = await db . collection ( 'users' ) . doc ( partnerId ) . get ( ) ;
if ( partnerUserDoc . exists ) {
const legacyToken = ( _a = partnerUserDoc . data ( ) ) === null || _a === void 0 ? void 0 : _a . fcmToken ;
if ( typeof legacyToken === 'string' && legacyToken . length > 0 ) {
tokens . push ( legacyToken ) ;
}
}
const tokenSnapshot = await db
. collection ( 'users' )
. doc ( partnerId )
. collection ( 'fcmTokens' )
. get ( ) ;
tokenSnapshot . docs . forEach ( ( doc ) => {
var _a ;
const t = ( _a = doc . data ( ) ) === null || _a === void 0 ? void 0 : _a . token ;
if ( typeof t === 'string' && t . length > 0 && ! tokens . includes ( t ) ) {
tokens . push ( t ) ;
}
} ) ;
if ( tokens . length === 0 ) {
console . log ( ` [notifyPartner] no FCM tokens for ${ partnerId } ` ) ;
return ;
}
const fcmMessage = {
token : tokens [ 0 ] ,
notification : {
title : notificationPayload . title ,
body : notificationPayload . body ,
} ,
data : {
type : notificationPayload . type ,
2026-06-22 08:53:23 -05:00
couple _id : coupleId ,
game _type : gameType ,
2026-06-18 01:28:43 -05:00
} ,
} ;
const sendResults = await Promise . allSettled ( tokens . map ( ( token ) => messaging . send ( Object . assign ( Object . assign ( { } , fcmMessage ) , { token } ) ) ) ) ;
const failures = [ ] ;
sendResults . forEach ( ( result , index ) => {
if ( result . status === 'rejected' ) {
failures . push ( ` ${ tokens [ index ] } : ${ String ( result . reason ) } ` ) ;
}
} ) ;
if ( failures . length > 0 ) {
console . error ( ` [notifyPartner] some notifications failed: ` , failures ) ;
}
else {
console . log ( ` [notifyPartner] notified ${ partnerId } ( ${ notificationType } ) ` ) ;
}
}
//# sourceMappingURL=onGameSessionUpdate.js.map