VATSAL5555 commited on
Commit
b29c4e2
·
verified ·
1 Parent(s): 1fb14e2

Upload 3 files

Browse files
Files changed (3) hide show
  1. app.py +148 -0
  2. index.html +552 -0
  3. requirements.txt +4 -0
app.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ from flask import Flask, request, jsonify, render_template
4
+ import requests
5
+ from PIL import Image
6
+ import pytesseract
7
+
8
+ app = Flask(__name__)
9
+
10
+ GEMINI_API_KEY = os.environ.get("AIzaSyCBdtueezDUl47nhMTPNK5r6G3q46Jnsa4")
11
+ GEMINI_URL = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key={GEMINI_API_KEY}"
12
+
13
+ BLACKLISTED_UPIS = ["fraudster@upi", "scam123@okaxis", "fake_pay@ybl", "urgent_pay@okhdfcbank", "win_cash@sbi"]
14
+ SUSPICIOUS_KEYWORDS = ["collect", "request", "urgent", "win", "lottery", "cashback", "claim", "reward", "fee"]
15
+
16
+ def call_gemini(prompt, system_instruction=""):
17
+ if not GEMINI_API_KEY:
18
+ return "Gemini API key is missing. Please set the GEMINI_API_KEY environment variable."
19
+
20
+ payload = {
21
+ "contents": [{"parts": [{"text": prompt}]}],
22
+ }
23
+ if system_instruction:
24
+ payload["systemInstruction"] = {"parts": [{"text": system_instruction}]}
25
+
26
+ headers = {"Content-Type": "application/json"}
27
+ try:
28
+ response = requests.post(GEMINI_URL, headers=headers, json=payload)
29
+ response.raise_for_status()
30
+ data = response.json()
31
+ return data["candidates"][0]["content"]["parts"][0]["text"]
32
+ except Exception as e:
33
+ return f"Error contacting Gemini: {str(e)}"
34
+
35
+ @app.route("/")
36
+ def index():
37
+ return render_template("index.html")
38
+
39
+ @app.route("/upload", methods=["POST"])
40
+ def upload():
41
+ if "image" not in request.files:
42
+ return jsonify({"error": "No image uploaded"}), 400
43
+
44
+ file = request.files["image"]
45
+ if file.filename == "":
46
+ return jsonify({"error": "No file selected"}), 400
47
+
48
+ try:
49
+ img = Image.open(file.stream)
50
+ text = pytesseract.image_to_string(img).lower()
51
+
52
+ # Extract features
53
+ amount_match = re.search(r'(?:rs\.?|inr|₹|amount)\s*(\d+(?:,\d+)*(?:\.\d{1,2})?)', text)
54
+ amount_str = amount_match.group(1).replace(",", "") if amount_match else "0"
55
+ amount = float(amount_str) if amount_str else 0.0
56
+
57
+ upi_match = re.search(r'[\w.-]+@[\w.-]+', text)
58
+ upi_id = upi_match.group(0) if upi_match else "Not found"
59
+
60
+ found_keywords = [kw for kw in SUSPICIOUS_KEYWORDS if kw in text]
61
+
62
+ # Risk Analysis
63
+ risk_level = "Safe"
64
+ reasons = []
65
+
66
+ if "request" in text and "success" in text:
67
+ reasons.append("Conflicting terms: 'request' and 'success' found together.")
68
+ risk_level = "High Risk"
69
+ elif "received" in text and "pay" in text:
70
+ reasons.append("Conflicting terms: 'received' and 'pay' found together.")
71
+ risk_level = "High Risk"
72
+
73
+ if found_keywords:
74
+ reasons.append(f"Suspicious keywords detected: {', '.join(found_keywords)}.")
75
+ if risk_level != "High Risk":
76
+ risk_level = "Suspicious"
77
+
78
+ if amount > 5000:
79
+ reasons.append(f"High transaction amount (₹{amount}).")
80
+ if risk_level == "Safe":
81
+ risk_level = "Suspicious"
82
+
83
+ if not amount_match and not upi_match:
84
+ reasons.append("Missing critical details like Amount or UPI ID.")
85
+ risk_level = "Suspicious"
86
+
87
+ if not reasons:
88
+ reasons.append("No obvious anomalies detected.")
89
+
90
+ # Gemini Explanation
91
+ prompt = f"Analyze this UPI transaction context. Extracted text: {text[:200]}. Found keywords: {found_keywords}. Amount: {amount}. UPI ID: {upi_id}. Explain briefly why this might be risky or safe in Hinglish."
92
+ gemini_explanation = call_gemini(prompt, "You are a UPI fraud detection assistant. Give short, simple Hinglish advice.")
93
+
94
+ return jsonify({
95
+ "risk_level": risk_level,
96
+ "reasons": reasons,
97
+ "extracted_text": text[:500],
98
+ "explanation": gemini_explanation,
99
+ "amount": amount,
100
+ "upi_id": upi_id
101
+ })
102
+ except Exception as e:
103
+ return jsonify({"error": str(e)}), 500
104
+
105
+ @app.route("/check_upi", methods=["POST"])
106
+ def check_upi():
107
+ data = request.json
108
+ upi_id = data.get("upi_id", "").strip().lower()
109
+
110
+ if not upi_id or "@" not in upi_id:
111
+ return jsonify({"error": "Invalid UPI ID format"}), 400
112
+
113
+ risk_level = "Safe"
114
+ reason = "UPI ID format looks valid."
115
+
116
+ if upi_id in BLACKLISTED_UPIS:
117
+ risk_level = "High Risk"
118
+ reason = "This UPI ID is blacklisted."
119
+ else:
120
+ # Check patterns
121
+ if any(kw in upi_id for kw in ["cashback", "offer", "win", "reward", "urgent"]):
122
+ risk_level = "Suspicious"
123
+ reason = "UPI ID contains suspicious promotional keywords."
124
+
125
+ prompt = f"A user wants to send money to UPI ID '{upi_id}'. Risk assessment is: {risk_level} because {reason}. Should they trust this? Explain in short Hinglish."
126
+ gemini_explanation = call_gemini(prompt, "You are a UPI fraud detection assistant. Give short, simple Hinglish advice.")
127
+
128
+ return jsonify({
129
+ "risk_level": risk_level,
130
+ "reason": reason,
131
+ "explanation": gemini_explanation
132
+ })
133
+
134
+ @app.route("/ask", methods=["POST"])
135
+ def ask():
136
+ data = request.json
137
+ message = data.get("message", "")
138
+
139
+ if not message:
140
+ return jsonify({"error": "Empty message"}), 400
141
+
142
+ system_instruction = "You are a UPI Fraud Detection Assistant. Help users avoid fraud. Give short, simple Hinglish answers. Warn about risky transactions. Never ask for OTP or PIN."
143
+ response = call_gemini(message, system_instruction)
144
+
145
+ return jsonify({"response": response})
146
+
147
+ if __name__ == "__main__":
148
+ app.run(host="0.0.0.0", port=7860)
index.html ADDED
@@ -0,0 +1,552 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>UPI Fraud Detection System</title>
8
+ <style>
9
+ :root {
10
+ --bg-color: #0b1120;
11
+ --container-bg: #1e293b;
12
+ --primary: #3b82f6;
13
+ --text: #f8fafc;
14
+ --safe: #22c55e;
15
+ --suspicious: #eab308;
16
+ --high-risk: #ef4444;
17
+ }
18
+
19
+ body {
20
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
21
+ background-color: var(--bg-color);
22
+ color: var(--text);
23
+ margin: 0;
24
+ padding: 20px;
25
+ }
26
+
27
+ .header {
28
+ text-align: center;
29
+ margin-bottom: 30px;
30
+ }
31
+
32
+ .header h1 {
33
+ color: var(--primary);
34
+ }
35
+
36
+ .tabs {
37
+ display: flex;
38
+ justify-content: center;
39
+ gap: 10px;
40
+ margin-bottom: 20px;
41
+ flex-wrap: wrap;
42
+ }
43
+
44
+ .tab-btn {
45
+ background: var(--container-bg);
46
+ color: var(--text);
47
+ border: 1px solid #334155;
48
+ padding: 10px 20px;
49
+ cursor: pointer;
50
+ border-radius: 5px;
51
+ font-size: 16px;
52
+ transition: 0.3s;
53
+ }
54
+
55
+ .tab-btn.active,
56
+ .tab-btn:hover {
57
+ background: var(--primary);
58
+ border-color: var(--primary);
59
+ }
60
+
61
+ .tab-content {
62
+ display: none;
63
+ background: var(--container-bg);
64
+ padding: 20px;
65
+ border-radius: 10px;
66
+ max-width: 800px;
67
+ margin: 0 auto;
68
+ border: 1px solid #334155;
69
+ }
70
+
71
+ .tab-content.active {
72
+ display: block;
73
+ animation: fadeIn 0.5s;
74
+ }
75
+
76
+ @keyframes fadeIn {
77
+ from {
78
+ opacity: 0;
79
+ transform: translateY(10px);
80
+ }
81
+
82
+ to {
83
+ opacity: 1;
84
+ transform: translateY(0);
85
+ }
86
+ }
87
+
88
+ .form-group {
89
+ margin-bottom: 15px;
90
+ }
91
+
92
+ input[type="file"],
93
+ input[type="text"] {
94
+ width: 100%;
95
+ padding: 10px;
96
+ background: #0f172a;
97
+ border: 1px solid #334155;
98
+ color: white;
99
+ border-radius: 5px;
100
+ box-sizing: border-box;
101
+ }
102
+
103
+ button.action-btn {
104
+ background: var(--primary);
105
+ color: white;
106
+ border: none;
107
+ padding: 10px 20px;
108
+ cursor: pointer;
109
+ border-radius: 5px;
110
+ font-size: 16px;
111
+ width: 100%;
112
+ }
113
+
114
+ button.action-btn:hover {
115
+ background: #2563eb;
116
+ }
117
+
118
+ .result-box {
119
+ margin-top: 20px;
120
+ padding: 15px;
121
+ border-radius: 5px;
122
+ background: #0f172a;
123
+ display: none;
124
+ }
125
+
126
+ .safe {
127
+ border-left: 5px solid var(--safe);
128
+ }
129
+
130
+ .suspicious {
131
+ border-left: 5px solid var(--suspicious);
132
+ }
133
+
134
+ .high-risk {
135
+ border-left: 5px solid var(--high-risk);
136
+ }
137
+
138
+ .action-cards {
139
+ display: grid;
140
+ gap: 15px;
141
+ grid-template-columns: 1fr;
142
+ }
143
+
144
+ .card {
145
+ background: #0f172a;
146
+ padding: 20px;
147
+ border-radius: 8px;
148
+ border-left: 4px solid var(--primary);
149
+ }
150
+
151
+ .chat-btn {
152
+ position: fixed;
153
+ bottom: 30px;
154
+ right: 30px;
155
+ background: var(--primary);
156
+ color: white;
157
+ border: none;
158
+ border-radius: 50%;
159
+ width: 60px;
160
+ height: 60px;
161
+ font-size: 30px;
162
+ cursor: pointer;
163
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.5);
164
+ z-index: 1000;
165
+ }
166
+
167
+ .chat-popup {
168
+ display: none;
169
+ position: fixed;
170
+ bottom: 100px;
171
+ right: 30px;
172
+ width: 300px;
173
+ height: 400px;
174
+ background: var(--container-bg);
175
+ border-radius: 10px;
176
+ border: 1px solid #334155;
177
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.5);
178
+ flex-direction: column;
179
+ z-index: 1000;
180
+ overflow: hidden;
181
+ }
182
+
183
+ .chat-header {
184
+ background: var(--primary);
185
+ padding: 15px;
186
+ text-align: center;
187
+ font-weight: bold;
188
+ }
189
+
190
+ .chat-body {
191
+ flex: 1;
192
+ padding: 15px;
193
+ overflow-y: auto;
194
+ display: flex;
195
+ flex-direction: column;
196
+ gap: 10px;
197
+ }
198
+
199
+ .chat-footer {
200
+ padding: 10px;
201
+ display: flex;
202
+ border-top: 1px solid #334155;
203
+ }
204
+
205
+ .chat-input {
206
+ flex: 1;
207
+ padding: 8px;
208
+ background: #0f172a;
209
+ border: 1px solid #334155;
210
+ color: white;
211
+ border-radius: 5px 0 0 5px;
212
+ outline: none;
213
+ }
214
+
215
+ .chat-send {
216
+ padding: 8px 15px;
217
+ background: var(--primary);
218
+ border: none;
219
+ color: white;
220
+ border-radius: 0 5px 5px 0;
221
+ cursor: pointer;
222
+ }
223
+
224
+ .msg {
225
+ max-width: 80%;
226
+ padding: 10px;
227
+ border-radius: 10px;
228
+ font-size: 14px;
229
+ }
230
+
231
+ .msg.user {
232
+ align-self: flex-end;
233
+ background: var(--primary);
234
+ }
235
+
236
+ .msg.ai {
237
+ align-self: flex-start;
238
+ background: #334155;
239
+ }
240
+
241
+ .loader {
242
+ border: 3px solid #f3f3f3;
243
+ border-radius: 50%;
244
+ border-top: 3px solid var(--primary);
245
+ width: 20px;
246
+ height: 20px;
247
+ animation: spin 1s linear infinite;
248
+ margin: 10px auto;
249
+ display: none;
250
+ }
251
+
252
+ @keyframes spin {
253
+ 0% {
254
+ transform: rotate(0deg);
255
+ }
256
+
257
+ 100% {
258
+ transform: rotate(360deg);
259
+ }
260
+ }
261
+
262
+ .quiz-option {
263
+ display: block;
264
+ background: #0f172a;
265
+ padding: 10px;
266
+ margin-bottom: 8px;
267
+ border-radius: 5px;
268
+ cursor: pointer;
269
+ border: 1px solid #334155;
270
+ }
271
+
272
+ .quiz-option:hover {
273
+ background: #1e293b;
274
+ }
275
+
276
+ .quiz-option input {
277
+ margin-right: 10px;
278
+ }
279
+ </style>
280
+ </head>
281
+
282
+ <body>
283
+
284
+ <div class="header">
285
+ <h1>🛡️ UPI Fraud Detection</h1>
286
+ <p>AI-Powered Secure Transactions</p>
287
+ </div>
288
+
289
+ <div class="tabs">
290
+ <button class="tab-btn active" onclick="openTab('tab1')">Screenshot Scan</button>
291
+ <button class="tab-btn" onclick="openTab('tab2')">UPI ID Checker</button>
292
+ <button class="tab-btn" onclick="openTab('tab3')">Action Engine</button>
293
+ <button class="tab-btn" onclick="openTab('tab4')">Fraud Quiz</button>
294
+ </div>
295
+
296
+ <div id="tab1" class="tab-content active">
297
+ <h2>Upload Payment Screenshot</h2>
298
+ <p>Check if a payment request or screenshot is fraudulent.</p>
299
+ <div class="form-group">
300
+ <input type="file" id="imageInput" accept="image/*">
301
+ </div>
302
+ <button class="action-btn" onclick="scanImage()">Scan Image</button>
303
+ <div class="loader" id="loader1"></div>
304
+
305
+ <div id="result1" class="result-box">
306
+ <h3 id="risk1"></h3>
307
+ <p><strong>Reasons:</strong> <span id="reason1"></span></p>
308
+ <p><strong>Extracted Amount:</strong> ₹<span id="amt1"></span> | <strong>UPI ID:</strong> <span
309
+ id="upi1"></span></p>
310
+ <div style="background: #1e293b; padding: 10px; border-radius: 5px; margin-top: 10px;">
311
+ <p><strong>🤖 AI Explanation:</strong></p>
312
+ <p id="gemini1" style="color: #cbd5e1;"></p>
313
+ </div>
314
+ </div>
315
+ </div>
316
+
317
+ <div id="tab2" class="tab-content">
318
+ <h2>UPI ID Risk Checker</h2>
319
+ <div class="form-group">
320
+ <input type="text" id="upiInput" placeholder="Enter UPI ID (e.g., user@bank)">
321
+ </div>
322
+ <button class="action-btn" onclick="checkUPI()">Verify UPI ID</button>
323
+ <div class="loader" id="loader2"></div>
324
+
325
+ <div id="result2" class="result-box">
326
+ <h3 id="risk2"></h3>
327
+ <p><strong>Reason:</strong> <span id="reason2"></span></p>
328
+ <div style="background: #1e293b; padding: 10px; border-radius: 5px; margin-top: 10px;">
329
+ <p><strong>🤖 AI Explanation:</strong></p>
330
+ <p id="gemini2" style="color: #cbd5e1;"></p>
331
+ </div>
332
+ </div>
333
+ </div>
334
+
335
+ <div id="tab3" class="tab-content">
336
+ <h2>What Should I Do?</h2>
337
+ <p>Select your suspected risk level to see immediate actions.</p>
338
+ <div class="form-group" style="display:flex; gap:10px;">
339
+ <button class="action-btn" style="background: var(--safe)" onclick="showAction('Safe')">Safe</button>
340
+ <button class="action-btn" style="background: var(--suspicious)"
341
+ onclick="showAction('Suspicious')">Suspicious</button>
342
+ <button class="action-btn" style="background: var(--high-risk)" onclick="showAction('High Risk')">High
343
+ Risk</button>
344
+ </div>
345
+ <div class="action-cards" id="actionContainer" style="display:none; margin-top: 20px;">
346
+ <div class="card">
347
+ <h3 id="actionTitle"></h3>
348
+ <ul id="actionList" style="padding-left: 20px;"></ul>
349
+ <div style="background: #0b1120; padding: 10px; border-radius: 5px; margin-top: 10px;">
350
+ <p><strong>🤖 AI Advice:</strong> <span id="actionAI"></span></p>
351
+ </div>
352
+ </div>
353
+ </div>
354
+ </div>
355
+
356
+ <div id="tab4" class="tab-content">
357
+ <h2>Fraud Awareness Quiz</h2>
358
+ <div id="quiz-container">
359
+ </div>
360
+ <button class="action-btn" onclick="submitQuiz()" style="margin-top: 15px;">Submit Quiz</button>
361
+ <div id="quiz-result" class="result-box">
362
+ <h3 id="quizScore"></h3>
363
+ <p id="quizLevel"></p>
364
+ </div>
365
+ </div>
366
+
367
+ <button class="chat-btn" onclick="toggleChat()">🤖</button>
368
+ <div class="chat-popup" id="chatPopup">
369
+ <div class="chat-header">Fraud Assistant</div>
370
+ <div class="chat-body" id="chatBody">
371
+ <div class="msg ai">Hello! Any questions about UPI fraud?</div>
372
+ </div>
373
+ <div class="chat-footer">
374
+ <input type="text" id="chatInput" class="chat-input" placeholder="Ask something..."
375
+ onkeypress="if(event.key === 'Enter') sendMessage()">
376
+ <button class="chat-send" onclick="sendMessage()">Send</button>
377
+ </div>
378
+ </div>
379
+
380
+ <script>
381
+ function openTab(tabId) {
382
+ document.querySelectorAll('.tab-content').forEach(el => el.classList.remove('active'));
383
+ document.querySelectorAll('.tab-btn').forEach(el => el.classList.remove('active'));
384
+ document.getElementById(tabId).classList.add('active');
385
+ event.target.classList.add('active');
386
+ }
387
+
388
+ function getRiskClass(risk) {
389
+ if (risk === "High Risk") return "high-risk";
390
+ if (risk === "Suspicious") return "suspicious";
391
+ return "safe";
392
+ }
393
+
394
+ async function scanImage() {
395
+ const file = document.getElementById('imageInput').files[0];
396
+ if (!file) return alert("Please select an image first.");
397
+
398
+ document.getElementById('loader1').style.display = "block";
399
+ document.getElementById('result1').style.display = "none";
400
+
401
+ const formData = new FormData();
402
+ formData.append("image", file);
403
+
404
+ try {
405
+ const res = await fetch('/upload', { method: 'POST', body: formData });
406
+ const data = await res.json();
407
+
408
+ document.getElementById('loader1').style.display = "none";
409
+ const resBox = document.getElementById('result1');
410
+ resBox.style.display = "block";
411
+
412
+ resBox.className = `result-box ${getRiskClass(data.risk_level)}`;
413
+ document.getElementById('risk1').innerText = `Risk Level: ${data.risk_level}`;
414
+ document.getElementById('reason1').innerText = data.reasons.join(" | ");
415
+ document.getElementById('amt1').innerText = data.amount;
416
+ document.getElementById('upi1').innerText = data.upi_id;
417
+ document.getElementById('gemini1').innerText = data.explanation || "No explanation provided.";
418
+
419
+ showAction(data.risk_level);
420
+ } catch (err) {
421
+ alert("Error processing image.");
422
+ document.getElementById('loader1').style.display = "none";
423
+ }
424
+ }
425
+
426
+ async function checkUPI() {
427
+ const upi = document.getElementById('upiInput').value;
428
+ if (!upi) return alert("Please enter a UPI ID.");
429
+
430
+ document.getElementById('loader2').style.display = "block";
431
+ document.getElementById('result2').style.display = "none";
432
+
433
+ try {
434
+ const res = await fetch('/check_upi', {
435
+ method: 'POST',
436
+ headers: { 'Content-Type': 'application/json' },
437
+ body: JSON.stringify({ upi_id: upi })
438
+ });
439
+ const data = await res.json();
440
+
441
+ document.getElementById('loader2').style.display = "none";
442
+ const resBox = document.getElementById('result2');
443
+ resBox.style.display = "block";
444
+
445
+ resBox.className = `result-box ${getRiskClass(data.risk_level)}`;
446
+ document.getElementById('risk2').innerText = `Risk Level: ${data.risk_level}`;
447
+ document.getElementById('reason2').innerText = data.reason;
448
+ document.getElementById('gemini2').innerText = data.explanation || "No explanation provided.";
449
+ } catch (err) {
450
+ alert("Error checking UPI.");
451
+ document.getElementById('loader2').style.display = "none";
452
+ }
453
+ }
454
+
455
+ function showAction(riskLevel) {
456
+ document.getElementById('actionContainer').style.display = "block";
457
+ const title = document.getElementById('actionTitle');
458
+ const list = document.getElementById('actionList');
459
+ const ai = document.getElementById('actionAI');
460
+
461
+ if (riskLevel === "High Risk") {
462
+ title.innerText = "🚨 High Risk Detected!";
463
+ title.style.color = "var(--high-risk)";
464
+ list.innerHTML = "<li>Do NOT enter your UPI PIN.</li><li>Do NOT send money.</li><li>Block the sender immediately.</li>";
465
+ ai.innerText = "Yeh transaction bohot risky hai! Turant block karein aur kisi ko PIN na batayein.";
466
+ } else if (riskLevel === "Suspicious") {
467
+ title.innerText = "⚠️ Suspicious Activity";
468
+ title.style.color = "var(--suspicious)";
469
+ list.innerHTML = "<li>Double-check the receiver's name and details.</li><li>Call the person to verify.</li><li>Ensure you are paying, not receiving.</li>";
470
+ ai.innerText = "Dhyan se check karein. Agar 'Receive' likha hai, toh paise katenge, aayenge nahi.";
471
+ } else {
472
+ title.innerText = "✅ Seems Safe";
473
+ title.style.color = "var(--safe)";
474
+ list.innerHTML = "<li>Verify the name on the bank app before proceeding.</li><li>Keep transaction amounts within limits.</li>";
475
+ ai.innerText = "Sab theek lag raha hai, par ek baar naam zaroor verify kar lein.";
476
+ }
477
+ }
478
+
479
+ function toggleChat() {
480
+ const popup = document.getElementById('chatPopup');
481
+ popup.style.display = popup.style.display === "flex" ? "none" : "flex";
482
+ }
483
+
484
+ async function sendMessage() {
485
+ const input = document.getElementById('chatInput');
486
+ const msg = input.value.trim();
487
+ if (!msg) return;
488
+
489
+ const chatBody = document.getElementById('chatBody');
490
+ chatBody.innerHTML += `<div class="msg user">${msg}</div>`;
491
+ input.value = "";
492
+ chatBody.scrollTop = chatBody.scrollHeight;
493
+
494
+ const typingId = "typing-" + Date.now();
495
+ chatBody.innerHTML += `<div class="msg ai" id="${typingId}">Typing...</div>`;
496
+ chatBody.scrollTop = chatBody.scrollHeight;
497
+
498
+ try {
499
+ const res = await fetch('/ask', {
500
+ method: 'POST',
501
+ headers: { 'Content-Type': 'application/json' },
502
+ body: JSON.stringify({ message: msg })
503
+ });
504
+ const data = await res.json();
505
+ document.getElementById(typingId).innerText = data.response;
506
+ } catch (e) {
507
+ document.getElementById(typingId).innerText = "Error reaching AI.";
508
+ }
509
+ chatBody.scrollTop = chatBody.scrollHeight;
510
+ }
511
+
512
+ const questions = [
513
+ { q: "What should you do to RECEIVE money on UPI?", opts: ["Enter UPI PIN", "Scan QR Code", "Just share UPI ID", "Click on unknown links"], ans: 2 },
514
+ { q: "If an app asks you to install 'AnyDesk' or 'QuickSupport', you should:", opts: ["Install it", "Block the caller", "Give them access", "Ask for OTP"], ans: 1 },
515
+ { q: "Customer care numbers found on Google search are always authentic.", opts: ["True", "False"], ans: 1 },
516
+ { q: "What does a 'Collect Request' mean?", opts: ["Money will be credited", "Money will be debited", "Bank verification", "Cashback received"], ans: 1 },
517
+ { q: "Never share your:", opts: ["UPI ID", "Name", "UPI PIN", "Phone Number"], ans: 2 }
518
+ ];
519
+
520
+ let quizHtml = "";
521
+ questions.forEach((q, i) => {
522
+ quizHtml += `<div style="margin-bottom:15px;"><p><strong>Q${i + 1}:</strong> ${q.q}</p>`;
523
+ q.opts.forEach((opt, j) => {
524
+ quizHtml += `<label class="quiz-option"><input type="radio" name="q${i}" value="${j}"> ${opt}</label>`;
525
+ });
526
+ quizHtml += `</div>`;
527
+ });
528
+ document.getElementById('quiz-container').innerHTML = quizHtml;
529
+
530
+ function submitQuiz() {
531
+ let score = 0;
532
+ questions.forEach((q, i) => {
533
+ const selected = document.querySelector(`input[name="q${i}"]:checked`);
534
+ if (selected && parseInt(selected.value) === q.ans) {
535
+ score++;
536
+ }
537
+ });
538
+ const resBox = document.getElementById('quiz-result');
539
+ resBox.style.display = "block";
540
+ document.getElementById('quizScore').innerText = `Score: ${score}/${questions.length}`;
541
+
542
+ let level = "Beginner";
543
+ if (score >= 4) level = "Expert 🏆";
544
+ else if (score >= 2) level = "Intermediate 👍";
545
+
546
+ document.getElementById('quizLevel').innerText = `Your Awareness Level: ${level}`;
547
+ resBox.className = "result-box " + (score >= 4 ? "safe" : (score >= 2 ? "suspicious" : "high-risk"));
548
+ }
549
+ </script>
550
+ </body>
551
+
552
+ </html>
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ flask
2
+ requests
3
+ pytesseract
4
+ pillow