spam-sdk
v1.2.0
Published
A simple Redux SDK for device ID management
Readme
Spam Detection SDK
A comprehensive React Native SDK for detecting and preventing spam behavior including API abuse, rapid screen switching, network manipulation, and emulator usage.
Features
🛡️ Multi-layered Spam Detection
- API call rate limiting and abuse detection
- Rapid screen switching detection
- Network switching/manipulation detection
- Emulator usage detection
⚙️ Intelligent Configuration
- Server-based configuration with local fallbacks
- Real-time config updates without app restart
- Configurable thresholds and blocking behavior
🔄 Advanced State Management
- Redux-based architecture with persistence
- Automatic reset mechanisms (time-based)
- Historical tracking with
maxEverpersistence
🚨 Smart Blocking System
- Configurable blocking UI with custom messages
- Automatic unblocking when limits are adjusted
- Multiple blocking reasons with detailed descriptions
🧪 Comprehensive Testing
- Built-in test utilities for all spam detection components
- Debug logging and state inspection tools
- Manual testing functions for development
Installation
npm install ../spam-sdkDependencies
Required peer dependencies:
react-native-device-info>= 10.0.0@react-native-async-storage/async-storage@react-native-netinfo/netinfo@react-navigation/native(for screen tracking)
Quick Start
1. Redux Store Setup
// store/index.js
import { createStore, combineReducers } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { spamReducer, spamPersistConfig } from 'spam-sdk';
const rootReducer = combineReducers({
// your app reducers
spam: spamReducer,
});
const persistConfig = {
key: 'root',
storage: AsyncStorage,
blacklist: ['spam'] // spam has its own persistence
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = createStore(persistedReducer);
export const persistor = persistStore(store);2. App Integration
// App.js
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { NavigationContainer } from '@react-navigation/native';
import { initSpamSDK, BlockingScreen, screenTracker } from 'spam-sdk';
const App = () => {
const dispatch = useDispatch();
const spamState = useSelector(state => state.spam);
const [blockingState, setBlockingState] = useState({ isBlocked: false });
useEffect(() => {
initializeSpamSDK();
}, []);
const initializeSpamSDK = async () => {
const onBlockingStateChange = (blockingData) => {
setBlockingState(blockingData);
};
const result = await initSpamSDK(dispatch, {
baseUrl: 'https://your-api.com',
onBlockingStateChange,
getState: () => store.getState().spam,
});
if (result.success) {
console.log('✅ Spam SDK initialized');
}
};
// Screen tracking integration
const handleNavigationStateChange = (state) => {
const getCurrentRoute = (state) => {
if (!state?.routes?.length) return null;
const route = state.routes[state.index];
return route.state ? getCurrentRoute(route.state) : route.name;
};
const currentScreen = getCurrentRoute(state);
if (currentScreen) {
screenTracker.trackScreenChange(currentScreen);
}
};
return (
<View style={{ flex: 1 }}>
<NavigationContainer onStateChange={handleNavigationStateChange}>
{/* Your app navigation */}
</NavigationContainer>
{/* Spam Detection Blocking Screen */}
<BlockingScreen
isBlocked={blockingState.isBlocked}
reason={blockingState.reason}
description={blockingState.description}
/>
</View>
);
};Spam Detection Components
1. API Call Rate Limiting
Detects and blocks excessive API usage.
Configuration:
{
apiCalls: {
enabled: true,
maxCountBeforeBlock: 100, // Max API calls before blocking
resetType: "per_min", // Reset interval
trackMaxHits: true // Track historical maximum
}
}Behavior:
- Tracks
maxHitsEver(persists across app restarts) - Once exceeded,
apiCallsSpam: trueuntil config limit increases - Automatic blocking when limit exceeded
2. Screen Switching Detection
Prevents rapid navigation abuse and bot-like behavior.
Configuration:
{
screenSwitching: {
enabled: true,
maxSwitches: 10, // Max switches per minute
timeWindowMinutes: 1, // Time window for counting
minTimeThreshold: 500, // Rapid switching threshold (ms)
blockSuspicious: true, // Enable blocking
trackHistory: true // Track switch history
}
}Features:
- Automatic screen change detection via React Navigation
- Time-based reset every minute
- Persistent
maxSwitchesEvertracking - Blocks rapid navigation patterns
3. Network Switching Detection
Detects network manipulation and VPN switching.
Configuration:
{
networkSwitching: {
enabled: true,
maxChanges: 3, // Max network changes
maxRapidChanges: 100, // Max rapid changes
timeWindowMinutes: 10, // Time window
blockSuspicious: true, // Enable blocking
trackHistory: true // Track network history
}
}Detection:
- Monitors network changes via NetInfo
- Tracks unique networks and change patterns
- Detects suspicious switching behavior
4. Emulator Detection
Identifies and optionally blocks emulator usage.
Configuration:
{
emulator: {
enabled: true,
blockEmulator: false, // Block emulator usage
allowDevelopment: false, // Allow in development
showWarning: true // Show warning messages
}
}Detection Methods:
- Hardware characteristics analysis
- OS-level emulator indicators
- Development environment detection
Configuration System
Server Configuration
The SDK now accepts server configuration as an object instead of making API calls. This gives you full control over how you fetch the config from your server.
Basic Usage
import { initSpamSDK } from 'spam-sdk';
const initializeSDK = async () => {
// Fetch config from your server however you want
const serverConfig = await fetchConfigFromYourServer();
// Initialize SDK with the config
const result = await initSpamSDK(dispatch, {
serverConfig,
onBlockingStateChange: (blockingData) => {
console.log('App blocked:', blockingData);
},
});
};Server Config Format
Your server should return a config object with this structure:
const serverConfig = {
"apiCalls": {
"enabled": true,
"maxCountBeforeBlock": 100,
"resetType": "per_min",
"trackMaxHits": true
},
"blocking": {
"enabled": false,
"showReason": false,
"customMessage": null
},
"emulator": {
"enabled": true,
"blockEmulator": false,
"showWarning": true,
"allowDevelopment": false
},
// ... other config sections
};Supported Config Formats
The SDK automatically handles different response formats:
- Direct config object:
const serverConfig = { apiCalls: {...}, blocking: {...} };- API response wrapper:
const serverConfig = {
"success": true,
"data": { apiCalls: {...}, blocking: {...} }
};- Config wrapper:
const serverConfig = {
"config": { apiCalls: {...}, blocking: {...} }
};Example Implementation
const fetchConfigFromYourServer = async () => {
try {
const response = await fetch('https://your-api.com/spam-config', {
method: 'GET',
headers: {
'Authorization': 'Bearer your-token',
'version': '90',
},
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Failed to fetch config:', error);
return null; // SDK will use defaults
}
};Local Configuration
Fallback configuration when server is unavailable:
// spam-sdk/src/config/spamConfig.js
export const DEFAULT_SPAM_CONFIG = {
apiCalls: {
enabled: true,
maxCountBeforeBlock: 100,
resetType: "per_min",
trackMaxHits: true
},
screenSwitching: {
enabled: true,
maxSwitches: 10,
timeWindowMinutes: 1,
minTimeThreshold: 500,
blockSuspicious: true,
trackHistory: true
},
// ... other components
};State Structure
{
// Core SDK state
isInitialized: false,
deviceIds: {
appInstanceId: "uuid-v4",
osDeviceId: "android-id-or-idfv",
hardwareId: "hardware-fingerprint"
},
deviceInfo: {
model: "iPhone 14",
brand: "Apple",
systemName: "iOS",
systemVersion: "16.0"
},
isEmulator: false,
// Spam detection state
spamScore: {
apiCallsSpam: false,
emulatorSpam: false,
networkSpam: false,
screenSpam: false,
overallScore: 0.0,
lastUpdated: 1640995200000
},
// API call tracking
apiCallsCount: {
total: 45,
maxHitsEver: 87, // Persists across resets
lastReset: 1640995200000,
resetType: "per_min"
},
// Screen switching tracking
screenSwitching: {
currentScreen: "Home",
previousScreen: "Profile",
switchCount: 3,
maxSwitchesEver: 15, // Persists across resets
uniqueScreensCount: 8,
sessionScreenHistory: ["Home", "Profile", "Settings"],
switchHistory: [/* switch records */],
isTracking: true
},
// Network tracking
networkTracking: {
currentNetworkId: "wifi_home",
changeCount: 1,
uniqueNetworkCount: 3,
sessionNetworkIds: ["wifi_home", "4g_cellular"],
networkChangeHistory: [/* change records */],
isTracking: true
},
// Configuration
spamConfig: {
// Server configuration merged with defaults
},
// Blocking state
blockedStatus: {
isBlocked: false,
reason: null, // 'api_calls', 'screen_switching', etc.
description: null,
timestamp: null
}
}API Reference
Initialization
initSpamSDK(dispatch, options)State Selectors
getSpamScore(state) // Get spam detection scores
getApiCallsCount(state) // Get API call statistics
getScreenSwitching(state) // Get screen switching data
getNetworkTracking(state) // Get network tracking data
getBlockedStatus(state) // Get blocking status
isSDKInitialized(state) // Check initializationActions
setSpamScore(data) // Update spam scores
setApiCallsCount(data) // Update API call count
updateScreenSwitching(data) // Update screen switching
updateNetworkState(data) // Update network state
setBlockedStatus(data) // Set blocking status
setSpamConfig(config) // Update configurationUtilities
performSpamCheck(state) // Manual spam check
resetScreenSession() // Reset screen tracking
resetNetworkSession() // Reset network trackingTesting & Debugging
Built-in Test Functions
import {
testApiCalls,
testScreenSwitching,
testNetworkSwitching,
forceUnblockApp
} from 'spam-sdk';
// Test API call detection
testApiCalls(dispatch, 50);
// Test screen switching
testScreenSwitching(dispatch, 15);
// Test network switching
testNetworkSwitching(dispatch, 5);
// Emergency unblock
forceUnblockApp(dispatch);Debug Logging
Enable detailed logging:
// All spam detection actions log detailed information
console.log('[SpamSDK] 🚨 API calls spam detected: 105/100');
console.log('[SpamSDK] 📱 Screen switch: Home → Profile (3/10)');
console.log('[SpamSDK] 🌐 Network change: wifi → cellular (2/3)');State Inspection
// Check current spam detection status
const spamState = useSelector(state => state.spam);
console.log('API Calls Spam:', spamState.spamScore.apiCallsSpam);
console.log('Screen Spam:', spamState.spamScore.screenSpam);
console.log('Is Blocked:', spamState.blockedStatus.isBlocked);Blocking System
Custom Blocking UI
import { BlockingScreen } from 'spam-sdk';
<BlockingScreen
isBlocked={blockingState.isBlocked}
reason={blockingState.reason}
description={blockingState.description}
showReason={false} // Show/hide technical details
customMessage="Access temporarily restricted"
/>Blocking Reasons
api_calls- Excessive API usagescreen_switching- Rapid screen navigationnetwork_switching- Network manipulationemulator- Emulator usage detected
Automatic Unblocking
The SDK automatically unblocks users when:
- Configuration limits are increased
- Blocking is disabled in config
- Manual unblock functions are called
Advanced Usage
Custom Configuration
// Override default configuration
const customConfig = {
apiCalls: { maxCountBeforeBlock: 200 },
screenSwitching: { maxSwitches: 20 },
blocking: { enabled: false }
};
spamConfigManager.updateConfig(customConfig);Manual Spam Detection
// Trigger manual spam check
const currentState = store.getState().spam;
const result = performSpamCheck(currentState);
console.log('Spam detected:', result.isSpam);Integration with Analytics
// Track spam events
useEffect(() => {
if (spamState.spamScore.apiCallsSpam) {
analytics.track('spam_detected', { type: 'api_calls' });
}
}, [spamState.spamScore]);Best Practices
1. Configuration Management
- Use server-based configuration for production
- Test configuration changes in development
- Monitor spam detection metrics
2. User Experience
- Provide clear blocking messages
- Implement appeal/contact mechanisms
- Use graduated responses (warnings before blocks)
3. Development
- Use test functions during development
- Monitor console logs for debugging
- Test edge cases and false positives
4. Performance
- SDK is optimized for minimal performance impact
- Uses efficient Redux state management
- Automatic cleanup and memory management
Troubleshooting
Common Issues
SDK not initializing:
// Check Redux store setup
console.log('Store state:', store.getState());
// Verify dependencies
import DeviceInfo from 'react-native-device-info';Screen tracking not working:
// Ensure navigation state listener is set up
<NavigationContainer onStateChange={handleNavigationStateChange}>False positives:
// Adjust configuration thresholds
const config = { screenSwitching: { maxSwitches: 20 } };Emergency unblock:
import { forceUnblockApp } from 'spam-sdk';
forceUnblockApp(dispatch);License
MIT License - see LICENSE file for details.
Support
For issues and questions:
- Check the troubleshooting section
- Review console logs for detailed error information
- Use built-in test functions to isolate issues
- Contact development team with specific error details
