With VT score and Clear History

This commit is contained in:
2024-06-08 12:05:22 +08:00
parent e70202b7e2
commit 283adbf07e
3 changed files with 150 additions and 21 deletions

122
App.tsx
View File

@@ -4,37 +4,97 @@ import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { CameraView, Camera } from 'expo-camera';
import { Ionicons } from '@expo/vector-icons';
import axios from 'axios'; // Import Axios for HTTP requests
// Create a Context for QR code data
const QRCodeContext = createContext();
const Tab = createBottomTabNavigator();
// Component for QR Scanner Screen
function QRScannerScreen() {
const { qrCodes, setQrCodes } = useContext(QRCodeContext); // Access context
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
const [showSplash, setShowSplash] = useState(true);
const [scannedData, setScannedData] = useState('');
const [hasPermission, setHasPermission] = useState(null); // State for camera permission
const [scanned, setScanned] = useState(false); // State for scanned status
const [showSplash, setShowSplash] = useState(true); // State for splash screen
const [scannedData, setScannedData] = useState(''); // State for scanned data
const [scanResult, setScanResult] = useState(null); // State for VirusTotal scan result
useEffect(() => {
const initializeApp = async () => {
const { status } = await Camera.requestCameraPermissionsAsync();
setHasPermission(status === 'granted');
setShowSplash(false); // Hide splash screen after initializing
const { status } = await Camera.requestCameraPermissionsAsync(); // Request camera permissions
setHasPermission(status === 'granted'); // Set permission status
setShowSplash(false); // Hide splash screen
};
initializeApp();
initializeApp(); // Initialize app
}, []);
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true); // Mark as scanned
const newScannedData = `Type: ${type}\nData: ${data}`;
setScannedData(newScannedData); // Save scanned data
setQrCodes([...qrCodes, newScannedData]); // Add scanned data to history
alert(`Bar code with type ${type} and data ${data} has been scanned!`); // Show an alert
// Function to handle barcode scanned event
const handleBarCodeScanned = async ({ type, data }) => {
setScanned(true); // Mark as scanned
// Determine the type of data (URL, text, or just numbers)
let dataType;
if (/^(http|https):\/\//.test(data)) {
dataType = 'URL';
} else if (/^[0-9]+$/.test(data)) {
dataType = 'Numbers';
} else {
dataType = 'Text';
}
// Construct the scanned data with the data type
let newScannedData = `Type: ${dataType}\nData: ${data}`; // Initialize with type and data
try {
const scanId = await scanWithVirusTotal(data); // Send data to VirusTotal and get scan ID
const positive = await getScanResult(scanId); // Get scan result and extract positive score
newScannedData += `\nScore: ${positive}`; // Append positive score to newScannedData
} catch (error) {
console.error('Error handling barcode scan:', error); // Handle error
}
setScannedData(newScannedData); // Save scanned data
setQrCodes([...qrCodes, newScannedData]); // Add scanned data to history
};
// Function to send data to VirusTotal and get the scan ID
const scanWithVirusTotal = async (data) => {
const apiKey = '3566a17933bb36dd97cb35e84d0446e5ab8ad623e6de968d34b655c79485251e'; // Replace with your VirusTotal API key
const url = 'https://www.virustotal.com/vtapi/v2/url/scan';
const params = {
apikey: apiKey,
url: data
};
try {
const response = await axios.post(url, null, { params }); // Send URL scan request
return response.data.scan_id; // Return scan ID
} catch (error) {
console.error('Error scanning with VirusTotal:', error); // Handle error
throw error; // Propagate error
}
};
// Function to get scan result from VirusTotal and return the positive score
const getScanResult = async (scanId) => {
const apiKey = '3566a17933bb36dd97cb35e84d0446e5ab8ad623e6de968d34b655c79485251e'; // Replace with your VirusTotal API key
const url = 'https://www.virustotal.com/vtapi/v2/url/report';
const params = {
apikey: apiKey,
resource: scanId
};
try {
const response = await axios.get(url, { params }); // Get scan result
return response.data.positives; // Return positive score
} catch (error) {
console.error('Error getting scan result:', error); // Handle error
throw error; // Propagate error
}
};
if (showSplash) {
return (
<View style={styles.splashContainer}>
@@ -67,21 +127,19 @@ function QRScannerScreen() {
style={styles.camera} // Apply styles
/>
</View>
{/* Display scanned data */}
{scannedData !== '' && (
{/* Display scanned data */}
{scannedData !== '' && (
<View style={styles.dataBox}>
<Text style={styles.dataText}>{scannedData}</Text>
{scanResult && <Text style={styles.dataText}>{JSON.stringify(scanResult)}</Text>}
</View>
)}
{/* Button to scan again */}
{scanned && (
<TouchableOpacity style={styles.button} onPress={() => setScanned(false)}>
<Text style={styles.buttonText}>Tap to Scan Again</Text>
</TouchableOpacity>
)}
{/* Menu (Placeholder for additional menu items) */}
<View style={styles.menu}>
{/* Your existing menu items */}
@@ -90,6 +148,7 @@ function QRScannerScreen() {
);
}
// Component for History Screen
function HistoryScreen() {
const { qrCodes } = useContext(QRCodeContext); // Access context
@@ -97,26 +156,38 @@ function HistoryScreen() {
<View style={styles.container}>
<Text style={styles.welcomeText}>History Screen</Text>
<FlatList
data={qrCodes}
data={qrCodes} // Data for FlatList
renderItem={({ item }) => (
<View style={styles.dataBox}>
<Text style={styles.dataText}>{item}</Text>
</View>
)}
keyExtractor={(item, index) => index.toString()}
keyExtractor={(item, index) => index.toString()} // Key extractor for FlatList
/>
</View>
);
}
// Component for Settings Screen
function SettingsScreen() {
const { setQrCodes } = useContext(QRCodeContext); // Access context
// Function to clear history
const clearHistory = () => {
setQrCodes([]);
};
return (
<View style={styles.container}>
<Text style={styles.welcomeText}>Settings Screen</Text>
<TouchableOpacity style={styles.button} onPress={clearHistory}>
<Text style={styles.buttonText}>Clear History</Text>
</TouchableOpacity>
</View>
);
}
// Component for Profile Screen
function ProfileScreen() {
return (
<View style={styles.container}>
@@ -235,4 +306,13 @@ const styles = StyleSheet.create({
backgroundColor: "#ff69b4", // pink background
paddingVertical: 10,
},
// Additional styles for green and red boxes
greenBox: {
backgroundColor: '#00FF00', // Green color
},
redBox: {
backgroundColor: '#FF0000', // Red color
},
});

48
package-lock.json generated
View File

@@ -11,6 +11,7 @@
"@expo/vector-icons": "^14.0.2",
"@react-navigation/bottom-tabs": "^6.5.20",
"@react-navigation/native": "^6.1.17",
"axios": "^1.7.2",
"expo": "~51.0.11",
"expo-camera": "~15.0.10",
"expo-status-bar": "~1.12.1",
@@ -5997,6 +5998,29 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/axios": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz",
"integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axios/node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/babel-core": {
"version": "7.0.0-bridge.0",
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz",
@@ -7853,6 +7877,25 @@
"node": ">=0.4.0"
}
},
"node_modules/follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/fontfaceobserver": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/fontfaceobserver/-/fontfaceobserver-2.3.0.tgz",
@@ -11549,6 +11592,11 @@
"react-is": "^16.13.1"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",

View File

@@ -12,6 +12,7 @@
"@expo/vector-icons": "^14.0.2",
"@react-navigation/bottom-tabs": "^6.5.20",
"@react-navigation/native": "^6.1.17",
"axios": "^1.7.2",
"expo": "~51.0.11",
"expo-camera": "~15.0.10",
"expo-status-bar": "~1.12.1",