import { firestore } from 'firebase-admin' ; import { v4 as uuid } from 'uuid' ; import { FirebaseAdmin } from '../client/firebase-admin' ; import { Ping , PingResponse } from '../client/ping' ; import { MonitorModel , PingModel , PingType , ProjectModel } from './../models/index.model' ; type Document = FirebaseFirestore . DocumentSnapshot ; type QuerySnapshot = firestore . QuerySnapshot ; type WriteResult = firestore . WriteResult ; export interface MonitorInfoInput { projectUid : string ; monitorUid : string ; type : string ; } export const ping = async ( projectUid , monitorUid , type = 'scheduler' ) : Promise < WriteResult | boolean > => { const document = await FirebaseAdmin . firestore ( ) . collection ( 'projects' ) . doc ( projectUid ) . get ( ) ; const project = < ProjectModel > document . data ( ) ; const monitor = project . monitors . find ( ( item ) => item . uid === monitorUid ) ; const url = project . url + monitor . path ; const uid = uuid ( ) ; if ( project . url . length === 0 ) { return Promise . resolve ( false ) ; } const start = Date . now ( ) ; let response ; try { response = await Ping < PingResponse > ( url ) ; } catch ( error ) { response = { statusCode : error . statusCode || 404 , body : error . message || 'Invalid URL' , } ; } const end = Date . now ( ) ; const pingResult = { uid : uid , monitorUid : monitorUid , statusCode : response . statusCode , expectedCode : monitor . expectedCode , expectedText : monitor . expectedText , url : url , duration : end - start , codeMatched : monitor . expectedCode === response . statusCode , textMatched : monitor . expectedText ? response . body . includes ( monitor . expectedText ) : true , createdOn : firestore . Timestamp . fromDate ( new Date ( ) ) , type : type , } ; pingResult . isValid = ! ! ( pingResult . codeMatched && pingResult . textMatched ) ; monitor . latestPing = pingResult ; if ( pingResult . isValid ) { monitor . successfulPings = monitor . successfulPings ? monitor . successfulPings + 1 : 1 ; } else { monitor . unsuccessfulPings = monitor . unsuccessfulPings ? monitor . unsuccessfulPings + 1 : 1 ; } await FirebaseAdmin . firestore ( ) . collection ( 'projects' ) . doc ( projectUid ) . set ( { monitors : project . monitors , } , { merge : true } ) ; return FirebaseAdmin . firestore ( ) . collection ( `projects/${ projectUid }/pings` ) . doc ( uid ) . set ( pingResult ) ; } ; export const deleteMonitorPings = async ( projectUid , monitorUid , isExpiredPings ) : Promise < WriteResult [ ] > => { const snapshots = await FirebaseAdmin . firestore ( ) . collection ( `projects/${ projectUid }/pings` ) . where ( 'monitorUid' , '==' , monitorUid ) . get ( ) ; const promises = [ ] ; snapshots . docs . forEach ( ( doc ) => { if ( isExpiredPings ) { const currentPing = < PingModel > doc . data ( ) ; const timeDiff = firestore . Timestamp . fromDate ( new Date ( ) ) . toMillis ( ) - currentPing . createdOn . toMillis ( ) ; const days = timeDiff / ( 1000 * 60 * 60 * 24 ) ; if ( days > 30 ) { promises . push ( doc . ref . delete ( ) ) ; } } if ( ! isExpiredPings ) { promises . push ( doc . ref . delete ( ) ) ; } } ) ; return Promise . all ( promises ) ; } ;