import { NativeEventEmitter, type EmitterSubscription } from 'react-native'; import { FreeraspReactNative } from '../nativeModules'; import { onInvalidCallback, removeListenerForEvent } from '../methods/native'; import { Threat } from '../../models/threat'; import type { NativeEvent, ThreatEventActions } from '../../types/types'; import { parseMalwareData } from '../../utils/malware'; import { getThreatChannelData, prepareThreatMapping, } from '../../channels/threat'; const eventEmitter = new NativeEventEmitter(FreeraspReactNative); let eventsListener: EmitterSubscription | null = null; let threatChannel: string | null = null; let threatKey: string | null = null; let threatMalwareKey: string | null = null; let isMappingPrepared = false; let isInitializing = false; export const setThreatListeners = async (config: ThreatEventActions) => { if (isInitializing) { return; } isInitializing = true; await removeThreatListener(); if (!threatChannel || !threatKey || !threatMalwareKey) { [threatChannel, threatKey, threatMalwareKey] = await getThreatChannelData(); } if (!isMappingPrepared) { await prepareThreatMapping(); isMappingPrepared = true; } const listener = async (event: NativeEvent) => { if (!threatKey || !threatMalwareKey) { onInvalidCallback(); return; } switch (event[threatKey]) { case Threat.PrivilegedAccess.value: config.privilegedAccess?.(); break; case Threat.Debug.value: config.debug?.(); break; case Threat.Simulator.value: config.simulator?.(); break; case Threat.AppIntegrity.value: config.appIntegrity?.(); break; case Threat.UnofficialStore.value: config.unofficialStore?.(); break; case Threat.Hooks.value: config.hooks?.(); break; case Threat.DeviceBinding.value: config.deviceBinding?.(); break; case Threat.Passcode.value: config.passcode?.(); break; case Threat.SecureHardwareNotAvailable.value: config.secureHardwareNotAvailable?.(); break; case Threat.ObfuscationIssues.value: config.obfuscationIssues?.(); break; case Threat.DeviceID.value: config.deviceID?.(); break; case Threat.DevMode.value: config.devMode?.(); break; case Threat.SystemVPN.value: config.systemVPN?.(); break; case Threat.Malware.value: const malwareData = event[threatMalwareKey]; config.malware?.( await parseMalwareData(Array.isArray(malwareData) ? malwareData : []) ); break; case Threat.ADBEnabled.value: config.adbEnabled?.(); break; case Threat.Screenshot.value: config.screenshot?.(); break; case Threat.ScreenRecording.value: config.screenRecording?.(); break; case Threat.MultiInstance.value: config.multiInstance?.(); break; case Threat.TimeSpoofing.value: config.timeSpoofing?.(); break; case Threat.LocationSpoofing.value: config.locationSpoofing?.(); break; case Threat.UnsecureWifi.value: config.unsecureWifi?.(); break; case Threat.Automation.value: config.automation?.(); break; default: onInvalidCallback(); break; } }; eventsListener = eventEmitter.addListener(threatChannel, listener); isInitializing = false; }; export const removeThreatListener = async (): Promise => { if (!eventsListener || !threatChannel) { return; } await removeListenerForEvent(threatChannel); eventsListener?.remove(); eventsListener = null; };