react-native-vision-camera-spoof-detector 1.0.17 → 1.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,220 +1,443 @@
1
- # React Native Vision Camera Face Anti-Spoofing Detector
2
-
3
- [![npm version](https://img.shields.io/npm/v/react-native-vision-camera-spoof-detector.svg)](https://www.npmjs.com/package/react-native-vision-camera-spoof-detector)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
-
6
- High-performance **face anti-spoofing and liveness detection** module for React Native with Vision Camera integration. Uses TensorFlow Lite with GPU acceleration for real-time detection.
7
-
8
- ## Features
9
-
10
- ✅ **Real-time Face Liveness Detection** - Distinguish between live faces and spoofed images/videos
11
- **GPU Acceleration** - TensorFlow Lite GPU delegate support
12
- **NNAPI Support** - Hardware acceleration fallback for older devices
13
- ✅ **Multi-Threading** - Non-blocking background processing
14
- **Optimized YUV Processing** - Direct frame processing without Bitmap conversion
15
- **TypeScript Support** - Full type definitions included
16
- **Lightweight** - Only 20.92 MB (optimized build)
17
- **Production Ready** - Tested and stable
18
-
19
- ## Installation
20
-
21
- ```bash
22
- npm install react-native-vision-camera-spoof-detector
23
- # or
24
- yarn add react-native-vision-camera-spoof-detector
25
- ```
26
-
27
- ### Peer Dependencies
28
-
29
- This module requires the following peer dependencies:
30
-
31
- ```bash
32
- npm install react-native-vision-camera react-native-reanimated react-native-worklets-core
33
- ```
34
-
35
- ## Quick Start
36
-
37
- ### 1. Initialize the Module
38
-
39
- ```javascript
40
- import { initializeFaceAntiSpoof } from 'react-native-vision-camera-spoof-detector';
41
-
42
- // In your app initialization
43
- useEffect(() => {
44
- initializeFaceAntiSpoof()
45
- .then(() => console.log('Face anti-spoof initialized'))
46
- .catch(err => console.error('Init failed:', err));
47
- }, []);
48
- ```
49
-
50
- ### 2. Use in Frame Processor
51
-
52
- ```javascript
53
- import { useFrameProcessor } from 'react-native-vision-camera';
54
- import { faceAntiSpoofFrameProcessor } from 'react-native-vision-camera-spoof-detector';
55
-
56
- export function CameraScreen() {
57
- const frameProcessor = useFrameProcessor((frame) => {
58
- 'worklet';
59
-
60
- const result = runAsync(frame, () => {
61
- 'worklet';
62
- return faceAntiSpoofFrameProcessor(frame);
63
- });
64
-
65
- // Use the result
66
- if (result?.isLive) {
67
- console.log('Live face detected:', result.label);
68
- }
69
- }, []);
70
-
71
- return (
72
- <Camera
73
- device={device}
74
- frameProcessor={frameProcessor}
75
- // ... other props
76
- />
77
- );
78
- }
79
- ```
80
-
81
- ## API Reference
82
-
83
- ### `initializeFaceAntiSpoof(): Promise<boolean>`
84
-
85
- Initializes the face anti-spoofing module. Must be called before using the frame processor.
86
-
87
- **Returns:** `Promise<boolean>` - true if initialization was successful
88
-
89
- ```javascript
90
- const isInitialized = await initializeFaceAntiSpoof();
91
- ```
92
-
93
- ### `faceAntiSpoofFrameProcessor(frame): FaceAntiSpoofingResult | null`
94
-
95
- Process a camera frame for face anti-spoofing detection.
96
-
97
- **Parameters:**
98
- - `frame` (Frame) - Vision Camera frame object
99
-
100
- **Returns:**
101
- ```typescript
102
- {
103
- isLive: boolean; // true if face is live
104
- label: string; // "Live Face" or "Spoof Face"
105
- neuralNetworkScore: number; // 0.0-1.0 (lower = more likely live)
106
- laplacianScore: number; // Image quality metric
107
- combinedScore: number; // 0.0-1.0 weighted score
108
- error?: string; // Error message if any
109
- }
110
- ```
111
-
112
- ### `isFaceAntiSpoofAvailable(): boolean`
113
-
114
- Check if the native module is available.
115
-
116
- ```javascript
117
- const available = isFaceAntiSpoofAvailable();
118
- ```
119
-
120
- ## Performance
121
-
122
- ### Optimization Techniques
123
-
124
- - **Multi-Threading**: Heavy processing runs on a dedicated background thread, keeping camera smooth
125
- - **GPU Acceleration**: Uses TensorFlow Lite GPU delegate when available
126
- - **NNAPI Support**: Falls back to NNAPI for hardware acceleration on older devices
127
- - **YUV Direct Processing**: No Bitmap conversion - works directly with camera frame data
128
- - **Reusable Buffers**: Allocates buffers once, reuses for each frame
129
- - **Single-Frame Processing**: Only processes one frame at a time to prevent queue overflow
130
-
131
- ### Benchmark
132
-
133
- | Metric | Value |
134
- |--------|-------|
135
- | Processing Time | ~50-100ms per frame |
136
- | Memory Usage | <30 MB (runtime) |
137
- | Package Size | 20.92 MB |
138
- | Support | Android 21+ |
139
-
140
- ## Architecture
141
-
142
- ```
143
- VisionCamera (30fps callback)
144
-
145
- faceAntiSpoofFrameProcessor()
146
-
147
- Submit to background executor
148
-
149
- Non-blocking return
150
-
151
- Latest result available
152
- ```
153
-
154
- Processing happens on:
155
- - Single-threaded `Executors.newSingleThreadExecutor()`
156
- - Daemon thread for proper lifecycle
157
- - Non-blocking callback returns immediately
158
-
159
- ## Configuration
160
-
161
- ### Accelerator Types
162
-
163
- The module automatically selects the best available accelerator:
164
-
165
- 1. **GPU** - TensorFlow Lite GPU delegate (fastest)
166
- 2. **NNAPI** - Android Neural Networks API
167
- 3. **CPU** - Fallback for older devices
168
-
169
- Check which accelerator is in use:
170
-
171
- ```javascript
172
- import FaceAntiSpoof from 'react-native-vision-camera-spoof-detector';
173
-
174
- FaceAntiSpoof.checkModelStatus()
175
- .then(status => console.log('Accelerator:', status.accelerator));
176
- ```
177
-
178
- ## Troubleshooting
179
-
180
- ### Module Not Available
181
-
182
- ```javascript
183
- if (!isFaceAntiSpoofAvailable()) {
184
- console.error('Face anti-spoof not available on this device');
185
- }
186
- ```
187
-
188
- ### Initialization Fails
189
-
190
- ```javascript
191
- try {
192
- await initializeFaceAntiSpoof();
193
- } catch (error) {
194
- console.error('Init error:', error.message);
195
- }
196
- ```
197
-
198
- ### Frame Processing Too Slow
199
-
200
- - Ensure you're using a physical device (emulators are slow)
201
- - Check if GPU acceleration is working
202
- - Reduce frame processor workload
203
- - Consider skipping some frames
204
-
205
- ## License
206
-
207
- MIT © JESCON TECHNOLOGIES PVT LTD
208
-
209
- ## Support
210
-
211
- For issues and feature requests, visit: [GitHub Issues](https://github.com/jescon-tech/react-native-vision-camera-spoof-detector/issues)
212
-
213
- ## Changelog
214
-
215
- See [CHANGELOG.md](./CHANGELOG.md) for version history and updates.
216
-
217
- ---
218
-
219
- **Package Version:** 1.0.0
220
- **Last Updated:** November 18, 2025
1
+ # react-native-vision-camera-spoof-detector
2
+
3
+ [![npm version](https://badge.fury.io/js/react-native-vision-camera-spoof-detector.svg)](https://badge.fury.io/js/react-native-vision-camera-spoof-detector)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![GitHub](https://img.shields.io/badge/GitHub-Repository-blue)](https://github.com/jescon-tech/react-native-vision-camera-spoof-detector)
6
+
7
+ High-performance face anti-spoofing and liveness detection module for React Native Vision Camera. Features TensorFlow Lite with GPU acceleration, optimized YUV processing, and real-time blink detection for robust liveness verification.
8
+
9
+ ## 🎯 Features
10
+
11
+ - **🚀 Real-time Performance**: GPU-accelerated TensorFlow Lite processing for smooth 60fps detection
12
+ - **🎯 High Accuracy**: Advanced ML models for distinguishing live faces from spoofing attempts
13
+ - **👁️ Blink Detection**: Native blink detection for enhanced liveness verification
14
+ - **📱 Optimized YUV Processing**: Efficient image data handling for React Native
15
+ - **🔧 Easy Integration**: Seamlessly integrates with `react-native-vision-camera`
16
+ - **⚡ Face Stability Tracking**: Automatic stable face detection with customizable thresholds
17
+ - **🛡️ Face Centering**: Intelligent face positioning validation in frame
18
+ - **📊 Anti-spoofing Confidence**: Detailed confidence scores with multiple detection models
19
+ - **🔄 Batched Updates**: Optimized state management with minimal re-renders
20
+
21
+ ## 📋 Requirements
22
+
23
+ - React Native >= 0.60.0
24
+ - react-native-vision-camera >= 4.6.4
25
+ - react-native-reanimated >= 3.0.0
26
+ - react-native-worklets-core >= 1.0.0
27
+ - react-native-vision-camera-face-detector (optional, for enhanced features)
28
+
29
+ ## 📦 Installation
30
+
31
+ ### Step 1: Install the package
32
+
33
+ ```bash
34
+ npm install react-native-vision-camera-spoof-detector
35
+ # or
36
+ yarn add react-native-vision-camera-spoof-detector
37
+ ```
38
+
39
+ ### Step 2: Install peer dependencies
40
+
41
+ ```bash
42
+ npm install react-native-vision-camera react-native-reanimated react-native-worklets-core
43
+ # or
44
+ yarn add react-native-vision-camera react-native-reanimated react-native-worklets-core
45
+ ```
46
+
47
+ ### Step 3: Configure Android (if not auto-linked)
48
+
49
+ Add to `android/app/build.gradle`:
50
+
51
+ ```gradle
52
+ dependencies {
53
+ implementation project(':react-native-vision-camera-spoof-detector')
54
+ }
55
+ ```
56
+
57
+ ### Step 4: Link native module (for React Native < 0.60)
58
+
59
+ ```bash
60
+ react-native link react-native-vision-camera-spoof-detector
61
+ ```
62
+
63
+ ## 🚀 Quick Start
64
+
65
+ ### Simple Usage
66
+
67
+ ```javascript
68
+ import React, { useEffect, useState } from 'react';
69
+ import { StyleSheet, Text, View } from 'react-native';
70
+ import { Camera, useCameraDevices, useFrameProcessor } from 'react-native-vision-camera';
71
+ import { faceAntiSpoofFrameProcessor, initializeFaceAntiSpoof } from 'react-native-vision-camera-spoof-detector';
72
+ import { runOnJS } from 'react-native-reanimated';
73
+
74
+ export default function App() {
75
+ const devices = useCameraDevices();
76
+ const device = devices.front;
77
+ const [spoofResult, setSpoofResult] = useState(null);
78
+
79
+ useEffect(() => {
80
+ initializeFaceAntiSpoof().then((success) => {
81
+ console.log('FaceAntiSpoof initialized:', success);
82
+ });
83
+ }, []);
84
+
85
+ const frameProcessor = useFrameProcessor((frame) => {
86
+ 'worklet';
87
+ const result = faceAntiSpoofFrameProcessor(frame);
88
+ if (result) {
89
+ runOnJS(setSpoofResult)(result);
90
+ }
91
+ }, []);
92
+
93
+ if (device == null) return <Text>Loading...</Text>;
94
+
95
+ return (
96
+ <View style={styles.container}>
97
+ <Camera
98
+ style={StyleSheet.absoluteFill}
99
+ device={device}
100
+ isActive={true}
101
+ frameProcessor={frameProcessor}
102
+ frameProcessorFps={5}
103
+ />
104
+ {spoofResult && (
105
+ <View style={styles.resultContainer}>
106
+ <Text style={styles.resultText}>
107
+ Is Live: {spoofResult.isLive ? 'Yes' : 'No'}
108
+ </Text>
109
+ <Text style={styles.resultText}>
110
+ Score: {spoofResult.neuralNetworkScore?.toFixed(2)}
111
+ </Text>
112
+ <Text style={styles.resultText}>
113
+ Label: {spoofResult.label}
114
+ </Text>
115
+ </View>
116
+ )}
117
+ </View>
118
+ );
119
+ }
120
+
121
+ const styles = StyleSheet.create({
122
+ container: { flex: 1 },
123
+ resultContainer: {
124
+ position: 'absolute',
125
+ bottom: 50,
126
+ left: 0,
127
+ right: 0,
128
+ alignItems: 'center',
129
+ backgroundColor: 'rgba(0,0,0,0.5)',
130
+ padding: 10,
131
+ },
132
+ resultText: {
133
+ color: 'white',
134
+ fontSize: 20,
135
+ fontWeight: 'bold',
136
+ },
137
+ });
138
+ ```
139
+
140
+ ### Advanced Usage with Full Feature Set
141
+
142
+ ```javascript
143
+ import { useCallback, useMemo, useEffect, useRef } from 'react';
144
+ import { Worklets } from 'react-native-worklets-core';
145
+ import { useFrameProcessor } from 'react-native-vision-camera';
146
+ import { useFaceDetector } from 'react-native-vision-camera-face-detector';
147
+ import {
148
+ faceAntiSpoofFrameProcessor,
149
+ initializeFaceAntiSpoof,
150
+ isFaceAntiSpoofAvailable,
151
+ } from 'react-native-vision-camera-spoof-detector';
152
+
153
+ const useFaceDetectionFrameProcessor = ({
154
+ onStableFaceDetected = () => { },
155
+ onFacesUpdate = () => { },
156
+ onLivenessUpdate = () => { },
157
+ onAntiSpoofUpdate = () => { },
158
+ showCodeScanner = false,
159
+ isLoading = false,
160
+ isActive = true,
161
+ livenessLevel = 0,
162
+ antispooflevel = 0.35,
163
+ }) => {
164
+ const { detectFaces } = useFaceDetector({
165
+ performanceMode: 'fast',
166
+ landmarkMode: 'none',
167
+ contourMode: 'none',
168
+ classificationMode: livenessLevel === 1 ? 'all' : 'none',
169
+ minFaceSize: 0.2,
170
+ });
171
+
172
+ const isMounted = useRef(true);
173
+ const antiSpoofInitialized = useRef(false);
174
+
175
+ const initializeAntiSpoof = useCallback(async () => {
176
+ if (antiSpoofInitialized.current) return true;
177
+ try {
178
+ const available = isFaceAntiSpoofAvailable?.();
179
+ if (!available) return false;
180
+ await initializeFaceAntiSpoof();
181
+ antiSpoofInitialized.current = true;
182
+ return true;
183
+ } catch (err) {
184
+ console.error('Anti-spoof initialization error:', err);
185
+ return false;
186
+ }
187
+ }, []);
188
+
189
+ useEffect(() => {
190
+ initializeAntiSpoof();
191
+ }, [initializeAntiSpoof]);
192
+
193
+ // Shared state for face tracking
194
+ const sharedState = useMemo(
195
+ () =>
196
+ Worklets.createSharedValue({
197
+ flags: {
198
+ captured: false,
199
+ showCodeScanner: showCodeScanner,
200
+ isActive: isActive,
201
+ hasSingleFace: false,
202
+ isFaceCentered: false,
203
+ },
204
+ antiSpoof: {
205
+ isLive: false,
206
+ confidence: 0,
207
+ consecutiveLiveFrames: 0,
208
+ },
209
+ }),
210
+ []
211
+ );
212
+
213
+ const frameProcessor = useFrameProcessor(
214
+ (frame) => {
215
+ 'worklet';
216
+
217
+ try {
218
+ const detected = detectFaces?.(frame);
219
+
220
+ if (!detected || detected.length === 0) {
221
+ onFacesUpdate?.({ count: 0, progress: 0 });
222
+ return;
223
+ }
224
+
225
+ if (detected.length === 1 && !sharedState.value.flags.captured) {
226
+ const antiSpoofResult = faceAntiSpoofFrameProcessor?.(frame);
227
+
228
+ if (antiSpoofResult?.isLive) {
229
+ sharedState.value.antiSpoof.isLive = true;
230
+ sharedState.value.antiSpoof.confidence = antiSpoofResult.combinedScore;
231
+ onAntiSpoofUpdate?.({
232
+ isLive: true,
233
+ confidence: antiSpoofResult.combinedScore,
234
+ });
235
+ }
236
+
237
+ onFacesUpdate?.({ count: 1, progress: 50 });
238
+ } else {
239
+ onFacesUpdate?.({ count: detected.length, progress: 0 });
240
+ }
241
+ } catch (err) {
242
+ console.error('Frame processing error:', err);
243
+ } finally {
244
+ frame.release?.();
245
+ }
246
+ },
247
+ [detectFaces, isLoading]
248
+ );
249
+
250
+ return {
251
+ frameProcessor,
252
+ sharedState,
253
+ initializeAntiSpoof,
254
+ };
255
+ };
256
+
257
+ export default useFaceDetectionFrameProcessor;
258
+ ```
259
+
260
+ ## 📚 API Reference
261
+
262
+ ### `initializeFaceAntiSpoof()`
263
+
264
+ Initializes the face anti-spoofing module. Must be called before using the frame processor.
265
+
266
+ ```javascript
267
+ const success = await initializeFaceAntiSpoof();
268
+ ```
269
+
270
+ **Returns**: `Promise<boolean>` - True if successful
271
+
272
+ ---
273
+
274
+ ### `isFaceAntiSpoofAvailable()`
275
+
276
+ Checks if the module is available on the device.
277
+
278
+ ```javascript
279
+ const available = isFaceAntiSpoofAvailable();
280
+ ```
281
+
282
+ **Returns**: `boolean`
283
+
284
+ ---
285
+
286
+ ### `faceAntiSpoofFrameProcessor(frame)`
287
+
288
+ Process frame and get anti-spoofing result.
289
+
290
+ ```javascript
291
+ const result = faceAntiSpoofFrameProcessor(frame);
292
+ ```
293
+
294
+ **Parameters**: `frame` (Vision Camera Frame)
295
+
296
+ **Returns**: `FaceAntiSpoofingResult | null`
297
+
298
+ ### `FaceAntiSpoofingResult`
299
+
300
+ ```typescript
301
+ interface FaceAntiSpoofingResult {
302
+ isLive: boolean; // Real face (true) or spoof (false)
303
+ label: string; // "Live Face" or "Spoof Face"
304
+ neuralNetworkScore: number; // 0.0-1.0 confidence
305
+ laplacianScore: number; // Image quality score
306
+ combinedScore: number; // Weighted average
307
+ error?: string; // Error message if any
308
+ }
309
+ ```
310
+
311
+ ## 🔧 Configuration
312
+
313
+ ```javascript
314
+ // Anti-spoofing sensitivity (0.0-1.0, lower = more lenient)
315
+ const antispooflevel = 0.35;
316
+
317
+ // Liveness verification mode
318
+ // 0: Anti-spoofing only
319
+ // 1: Anti-spoofing + blink detection
320
+ const livenessLevel = 1;
321
+
322
+ // Customizable thresholds
323
+ const FACE_STABILITY_THRESHOLD = 3; // Frames for stable face
324
+ const FACE_MOVEMENT_THRESHOLD = 15; // Max pixel movement
325
+ const BLINK_THRESHOLD = 0.3; // Eye closure probability
326
+ const REQUIRED_BLINKS = 3; // Blinks for liveness
327
+ const REQUIRED_CONSECUTIVE_LIVE_FRAMES = 3; // Consecutive live frames
328
+ const REAL_LAPLACIAN_THRESHOLD = 3500; // Image quality threshold
329
+ const FACE_CENTER_THRESHOLD_X = 0.2; // X-axis tolerance
330
+ const FACE_CENTER_THRESHOLD_Y = 0.15; // Y-axis tolerance
331
+ ```
332
+
333
+ ## 🎮 Complete Examples
334
+
335
+ Check the [examples](./examples) folder for:
336
+ - Basic anti-spoofing detection
337
+ - Face detection with liveness
338
+ - Complete capture flow
339
+ - UI components and feedback
340
+
341
+ ## 🔍 Attack Detection Capabilities
342
+
343
+ The module detects and prevents:
344
+ - ✅ Print attacks (photos)
345
+ - ✅ Display attacks (screens/tablets)
346
+ - ✅ Mask attacks (with blink detection)
347
+ - ✅ Replay attacks (videos)
348
+
349
+ Performance depends on:
350
+ - Image quality
351
+ - Lighting conditions
352
+ - Face angle and positioning
353
+ - Device camera specs
354
+
355
+ ## ⚙️ Performance Tips
356
+
357
+ 1. Use `performanceMode: 'fast'` in Face Detector
358
+ 2. Module automatically batches state updates
359
+ 3. Adjust `FRAME_PROCESSOR_MIN_INTERVAL_MS` as needed
360
+ 4. GPU acceleration is used automatically when available
361
+ 5. Proper frame release prevents memory leaks
362
+
363
+ ## 📱 Platform Support
364
+
365
+ | Platform | Status | GPU | Notes |
366
+ |----------|--------|-----|-------|
367
+ | Android | ✅ Supported | Yes | Fully optimized |
368
+ | iOS | ⏳ In Progress | Yes | Coming soon |
369
+ | Web | ❌ No | N/A | Not applicable |
370
+
371
+ ## 🐛 Troubleshooting
372
+
373
+ **Module won't initialize**
374
+ ```javascript
375
+ const available = isFaceAntiSpoofAvailable();
376
+ if (!available) {
377
+ console.log('Not available on this device');
378
+ }
379
+ ```
380
+
381
+ **Low accuracy**
382
+ - Check lighting conditions
383
+ - Ensure face is centered
384
+ - Adjust `antispooflevel` parameter
385
+ - Verify TensorFlow Lite models are bundled
386
+
387
+ **Performance issues**
388
+ - Reduce frame processing frequency
389
+ - Use lower camera resolution
390
+ - Enable fast performance mode
391
+ - Check device temperature
392
+
393
+ **Face detection fails**
394
+ - Ensure clear face visibility
395
+ - Check camera permissions
396
+ - Verify sufficient lighting
397
+ - Check minimum face size threshold
398
+
399
+ ## 📖 Documentation
400
+
401
+ - [Complete API Documentation](./.docs/API.md)
402
+ - [Migration Guide](./.docs/MIGRATION.md)
403
+ - [Best Practices](./.docs/BEST_PRACTICES.md)
404
+ - [Comprehensive Example](./examples/CompleteExampleApp.tsx)
405
+
406
+ ## 🤝 Contributing
407
+
408
+ Contributions welcome! See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
409
+
410
+ ## 📄 License
411
+
412
+ MIT License - see [LICENSE](./LICENSE) file for details.
413
+
414
+ ## 👨‍💼 Author
415
+
416
+ **PRAFULDAS M M**
417
+ - Company: JESCON TECHNOLOGIES PVT LTD
418
+ - Location: Thrissur, Kerala, India
419
+ - Email: jescontechnologies@gmail.com
420
+
421
+ ## 🔗 Quick Links
422
+
423
+ - [NPM Package](https://www.npmjs.com/package/react-native-vision-camera-spoof-detector)
424
+ - [GitHub Repository](https://github.com/jescon-tech/react-native-vision-camera-spoof-detector)
425
+ - [React Native Vision Camera](https://react-native-vision-camera.com)
426
+ - [TensorFlow Lite](https://www.tensorflow.org/lite)
427
+
428
+ ## 📞 Support & Community
429
+
430
+ - 🐛 [Report Issues](https://github.com/jescon-tech/react-native-vision-camera-spoof-detector/issues)
431
+ - 💬 [GitHub Discussions](https://github.com/jescon-tech/react-native-vision-camera-spoof-detector/discussions)
432
+ - 📧 Email: jescontechnologies@gmail.com
433
+
434
+ ## 🙏 Acknowledgments
435
+
436
+ Built with:
437
+ - [TensorFlow Lite](https://www.tensorflow.org/lite)
438
+ - [React Native Vision Camera](https://react-native-vision-camera.com)
439
+ - [React Native Worklets](https://docs.swmansion.com/react-native-worklets/)
440
+
441
+ ---
442
+
443
+ Made with ❤️ by JESCON TECHNOLOGIES PVT LTD