IqraFatima commited on
Commit
32f8533
·
verified ·
1 Parent(s): f030d37

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +659 -0
app.py ADDED
@@ -0,0 +1,659 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import os
3
+ import re
4
+ import fitz # PyMuPDF
5
+ import tempfile
6
+ import base64
7
+ from datetime import datetime
8
+ import streamlit as st
9
+ from transformers import pipeline
10
+ from groq import Groq
11
+ import streamlit.components.v1 as components
12
+ from io import BytesIO
13
+ import random
14
+ import matplotlib.pyplot as plt
15
+ import numpy as np
16
+ import time
17
+
18
+ # Page configuration
19
+ st.set_page_config(
20
+ page_title="ZeroPhish Gate",
21
+ page_icon="🛡️",
22
+ layout="wide",
23
+ initial_sidebar_state="collapsed"
24
+ )
25
+
26
+ # ⛳ Access secrets securely from environment variables
27
+ GROQ_API_KEY = os.getenv("GROQ_API_KEY")
28
+ HF_TOKEN = os.getenv("HF_TOKEN")
29
+
30
+ # ✅ Validate secrets (simplified for Hugging Face)
31
+ if not HF_TOKEN:
32
+ st.warning("⚠️ HF_TOKEN not found. Using demo mode with limited features.")
33
+
34
+ # Use GROQ if available, otherwise show a warning
35
+ groq_client = None
36
+ if GROQ_API_KEY:
37
+ try:
38
+ groq_client = Groq(api_key=GROQ_API_KEY)
39
+ except:
40
+ st.warning("⚠️ Failed to initialize GROQ client. Expert analysis will be limited.")
41
+
42
+ # ✅ Load phishing detection pipeline from Hugging Face
43
+ @st.cache_resource(show_spinner="Loading AI model...")
44
+ def load_phishing_model():
45
+ try:
46
+ return pipeline(
47
+ "text-classification",
48
+ model="ealvaradob/bert-finetuned-phishing",
49
+ token=HF_TOKEN
50
+ )
51
+ except Exception as e:
52
+ st.error(f"❌ Error loading model: {e}")
53
+ # Return a simple lambda function as fallback
54
+ return lambda text: [{'label': 'UNKNOWN', 'score': 0.5}]
55
+
56
+ phishing_pipe = load_phishing_model()
57
+
58
+ # ✅ Language and role options
59
+ language_choices = ["English", "Urdu", "French", "Spanish", "German", "Chinese"]
60
+ role_choices = ["Admin", "Procurement", "Logistics", "Finance", "HR", "IT", "Executive"]
61
+
62
+ # ✅ Glossary terms
63
+ GLOSSARY = {
64
+ "phishing": "Phishing is a scam where attackers trick you into revealing personal information.",
65
+ "malware": "Malicious software designed to harm or exploit systems.",
66
+ "spam": "Unwanted or unsolicited messages.",
67
+ "tone": "The emotional character of the message.",
68
+ "spear phishing": "Targeted phishing attacks aimed at specific individuals or organizations.",
69
+ "smishing": "SMS phishing - phishing conducted via text messages.",
70
+ "vishing": "Voice phishing - phishing conducted via phone calls.",
71
+ "social engineering": "Manipulating people into revealing confidential information."
72
+ }
73
+
74
+ # ✅ Translations (demo dictionary-based)
75
+ TRANSLATIONS = {
76
+ "Phishing": {"Urdu": "فشنگ", "French": "Hameçonnage", "Spanish": "Suplantación de identidad", "German": "Phishing", "Chinese": "钓鱼"},
77
+ "Spam": {"Urdu": "سپیم", "French": "Courrier indésirable", "Spanish": "Correo basura", "German": "Spam", "Chinese": "垃圾邮件"},
78
+ "Malware": {"Urdu": "میلویئر", "French": "Logiciel malveillant", "Spanish": "Software malicioso", "German": "Schadware", "Chinese": "恶意软件"},
79
+ "Safe": {"Urdu": "محفوظ", "French": "Sûr", "Spanish": "Seguro", "German": "Sicher", "Chinese": "安全的"}
80
+ }
81
+
82
+ # ✅ In-memory history
83
+ if "history" not in st.session_state:
84
+ st.session_state.history = []
85
+
86
+ # =======================
87
+ # Custom CSS for Enhanced UI
88
+ # =======================
89
+ def load_css():
90
+ st.markdown("""
91
+ <style>
92
+ /* Main app styling */
93
+ .main {
94
+ background-color: #F9FAFB;
95
+ }
96
+
97
+ /* Header styling */
98
+ .app-header {
99
+ background-color: white;
100
+ padding: 2rem;
101
+ border-radius: 1rem;
102
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
103
+ margin-bottom: 2rem;
104
+ }
105
+
106
+ /* Card styling */
107
+ .card {
108
+ background-color: white;
109
+ padding: 1.5rem;
110
+ border-radius: 0.75rem;
111
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
112
+ margin-bottom: 1.5rem;
113
+ border-left: 4px solid #3B82F6;
114
+ }
115
+
116
+ .card-danger {
117
+ border-left: 4px solid #EF4444;
118
+ }
119
+
120
+ .card-warning {
121
+ border-left: 4px solid #F59E0B;
122
+ }
123
+
124
+ .card-success {
125
+ border-left: 4px solid #10B981;
126
+ }
127
+
128
+ /* Badge styling */
129
+ .badge {
130
+ display: inline-block;
131
+ padding: 0.25rem 0.5rem;
132
+ border-radius: 9999px;
133
+ font-size: 0.875rem;
134
+ font-weight: 500;
135
+ margin-right: 0.5rem;
136
+ }
137
+
138
+ .badge-danger {
139
+ background-color: #FEE2E2;
140
+ color: #B91C1C;
141
+ }
142
+
143
+ .badge-warning {
144
+ background-color: #FEF3C7;
145
+ color: #92400E;
146
+ }
147
+
148
+ .badge-success {
149
+ background-color: #D1FAE5;
150
+ color: #065F46;
151
+ }
152
+
153
+ /* Button styling */
154
+ .stButton>button {
155
+ border-radius: 0.5rem;
156
+ padding: 0.5rem 1rem;
157
+ font-weight: 500;
158
+ }
159
+
160
+ /* Report container */
161
+ .report-container {
162
+ border: 1px solid #E5E7EB;
163
+ padding: 1.5rem;
164
+ border-radius: 0.75rem;
165
+ background-color: white;
166
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
167
+ }
168
+
169
+ .highlight {
170
+ font-weight: 500;
171
+ color: #4B5563;
172
+ }
173
+
174
+ /* History entries */
175
+ .history-entry {
176
+ padding: 1rem;
177
+ border-radius: 0.5rem;
178
+ background-color: white;
179
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
180
+ margin-bottom: 1rem;
181
+ border-left: 3px solid #3B82F6;
182
+ }
183
+
184
+ /* Voice playback container */
185
+ .voice-container {
186
+ display: flex;
187
+ align-items: center;
188
+ gap: 0.5rem;
189
+ margin-top: 1rem;
190
+ padding: 0.75rem;
191
+ background-color: #F3F4F6;
192
+ border-radius: 0.5rem;
193
+ }
194
+
195
+ /* Progress indicators */
196
+ @keyframes pulse {
197
+ 0% { opacity: .5; }
198
+ 50% { opacity: 1; }
199
+ 100% { opacity: .5; }
200
+ }
201
+
202
+ .analyzing {
203
+ animation: pulse 1.5s infinite;
204
+ }
205
+ </style>
206
+ """, unsafe_allow_html=True)
207
+
208
+ # =======================
209
+ # Function Definitions
210
+ # =======================
211
+ def extract_text_from_file(file):
212
+ if file is None:
213
+ return ""
214
+ ext = file.name.split(".")[-1].lower()
215
+ if ext == "pdf":
216
+ try:
217
+ doc = fitz.open(stream=file.read(), filetype="pdf")
218
+ return "\n".join(page.get_text() for page in doc)
219
+ except Exception as e:
220
+ st.error(f"❌ Error reading PDF: {e}")
221
+ return ""
222
+ elif ext == "txt":
223
+ try:
224
+ return file.read().decode("utf-8")
225
+ except Exception as e:
226
+ st.error(f"❌ Error reading text file: {e}")
227
+ return ""
228
+ return ""
229
+
230
+ def analyze_with_huggingface(text):
231
+ try:
232
+ result = phishing_pipe(text)
233
+ label = result[0]['label']
234
+ confidence = round(result[0]['score'] * 100, 2)
235
+ threat_type = {
236
+ "PHISHING": "Phishing",
237
+ "SPAM": "Spam",
238
+ "MALWARE": "Malware",
239
+ "LEGITIMATE": "Safe"
240
+ }.get(label.upper(), "Unknown")
241
+ return label, confidence, threat_type
242
+ except Exception as e:
243
+ st.error(f"❌ Model error: {e}")
244
+ return "Error", 0, f"Error: {e}"
245
+
246
+ def get_severity_class(threat_type, score):
247
+ if threat_type.lower() == "safe":
248
+ return "success"
249
+ elif score > 85:
250
+ return "danger"
251
+ else:
252
+ return "warning"
253
+
254
+ def semantic_analysis(text, role, language):
255
+ # If GROQ is not available, return a generic analysis
256
+ if not groq_client:
257
+ return f"This message shows signs of potentially being a {random.choice(['phishing attempt', 'spam', 'suspicious message'])}. Be cautious with any links or attachments. Always verify the sender through official channels before taking any action."
258
+
259
+ try:
260
+ prompt = f"""
261
+ You are a cybersecurity expert specialized in analyzing suspicious messages and explaining them in simple terms.
262
+
263
+ Analyze the following message for a {role} and provide:
264
+ 1. Whether it appears to be a phishing attempt, spam, malware, or legitimate
265
+ 2. The specific red flags or indicators that support your analysis
266
+ 3. What actions the recipient should take
267
+ 4. How this type of attack typically works
268
+
269
+ Keep your explanation concise (150-200 words), informative and avoid asking questions.
270
+
271
+ Message to analyze:
272
+ {text}
273
+ """
274
+
275
+ response = groq_client.chat.completions.create(
276
+ model="llama3-8b-8192",
277
+ messages=[
278
+ {"role": "system", "content": "You are a cybersecurity assistant specialized in explaining phishing and suspicious messages."},
279
+ {"role": "user", "content": prompt}
280
+ ]
281
+ )
282
+ raw = response.choices[0].message.content
283
+ clean = re.sub(r"Is there anything else you'd like.*", "", raw, flags=re.I).strip()
284
+ return clean
285
+ except Exception as e:
286
+ st.warning(f"⚠️ LLM analysis unavailable: {e}")
287
+ return "This message shows signs of potentially malicious content. Be cautious with any links or attachments. Always verify the sender through official channels before taking any action."
288
+
289
+ def translate_label(threat_type, language="English"):
290
+ if language == "English":
291
+ return threat_type
292
+ return TRANSLATIONS.get(threat_type, {}).get(language, threat_type)
293
+
294
+ def create_report(label, score, threat_type, explanation, text):
295
+ ts = datetime.now().strftime("%Y%m%d_%H%M%S")
296
+ filename = f"Zerophish_Report_{ts}.txt"
297
+ report = f"""
298
+ 🔍 AI THREAT DETECTION REPORT
299
+ ============================
300
+ Generated: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
301
+
302
+ INPUT MESSAGE:
303
+ {text}
304
+
305
+ ANALYSIS RESULTS:
306
+ ----------------
307
+ Prediction: {label}
308
+ Threat Type: {threat_type}
309
+ Confidence: {score}%
310
+
311
+ EXPERT EXPLANATION:
312
+ -----------------
313
+ {explanation}
314
+
315
+ RECOMMENDATIONS:
316
+ --------------
317
+ 1. Do not click any links or download any attachments from this message if marked as suspicious
318
+ 2. Report this message to your IT security team
319
+ 3. Delete the message from your inbox
320
+ 4. Be vigilant for similar messages in the future
321
+
322
+ ============================
323
+ Generated by ZeroPhish Gate
324
+ """
325
+ with tempfile.NamedTemporaryFile(mode="w+", delete=False, suffix=".txt") as temp:
326
+ temp.write(report)
327
+ return temp.name
328
+
329
+ def render_history():
330
+ if not st.session_state.history:
331
+ st.info("🕒 No analysis history yet. Analyze messages to see your history here.")
332
+ return
333
+
334
+ for i, record in enumerate(reversed(st.session_state.history)):
335
+ severity = get_severity_class(record['threat'], record['score'])
336
+ with st.container():
337
+ st.markdown(f"""
338
+ <div class="history-entry card-{severity}">
339
+ <h4>Entry #{len(st.session_state.history) - i}</h4>
340
+ <p><strong>Input:</strong> {record['input'][:100]}{'...' if len(record['input']) > 100 else ''}</p>
341
+ <p>
342
+ <span class="badge badge-{severity}">{record['threat']}</span>
343
+ <strong>Confidence:</strong> {record['score']}%
344
+ </p>
345
+ <p><strong>Summary:</strong> {record['summary'][:150]}{'...' if len(record['summary']) > 150 else ''}</p>
346
+ </div>
347
+ """, unsafe_allow_html=True)
348
+
349
+ def create_threat_visualization(threat_type, score):
350
+ # Create figure and axis
351
+ fig, ax = plt.subplots(figsize=(8, 1))
352
+
353
+ # Define the color gradient based on threat type and score
354
+ if threat_type.lower() == "safe":
355
+ color = '#10B981' # Green for safe
356
+ elif score > 85:
357
+ color = '#EF4444' # Red for high confidence threats
358
+ else:
359
+ color = '#F59E0B' # Amber for medium confidence threats
360
+
361
+ # Create the gauge chart
362
+ ax.barh(0, score, height=0.6, color=color)
363
+ ax.barh(0, 100, height=0.6, color='#E5E7EB', zorder=0)
364
+
365
+ # Add score text
366
+ ax.text(score/2, 0, f"{score}%", ha='center', va='center', color='white', fontweight='bold')
367
+
368
+ # Clean up the chart
369
+ ax.set_xlim(0, 100)
370
+ ax.set_ylim(-0.5, 0.5)
371
+ ax.axis('off')
372
+
373
+ # Add threat level indicators
374
+ plt.text(25, -0.4, 'LOW', ha='center', fontsize=8, color='#4B5563')
375
+ plt.text(50, -0.4, 'MEDIUM', ha='center', fontsize=8, color='#4B5563')
376
+ plt.text(75, -0.4, 'HIGH', ha='center', fontsize=8, color='#4B5563')
377
+
378
+ # Create buffer for returning
379
+ buf = BytesIO()
380
+ plt.savefig(buf, format='png', bbox_inches='tight', dpi=100)
381
+ plt.close(fig)
382
+ buf.seek(0)
383
+ return buf
384
+
385
+ # Web-based text-to-speech using ResponsiveVoice (no server-side dependencies)
386
+ def add_responsive_voice(text, lang='English'):
387
+ # Map our language names to ResponsiveVoice API names
388
+ lang_map = {
389
+ 'English': 'UK English Female',
390
+ 'French': 'French Female',
391
+ 'Spanish': 'Spanish Female',
392
+ 'German': 'Deutsch Female',
393
+ 'Chinese': 'Chinese Female',
394
+ 'Urdu': 'Hindi Female' # Fallback since Urdu isn't directly supported
395
+ }
396
+
397
+ voice = lang_map.get(lang, 'UK English Female')
398
+
399
+ html = f"""
400
+ <script src="https://code.responsivevoice.org/responsivevoice.js?key=dE72SdOb"></script>
401
+ <div class="voice-container">
402
+ <button id="play-btn" onclick="playText()">
403
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
404
+ <polygon points="5 3 19 12 5 21 5 3"></polygon>
405
+ </svg>
406
+ </button>
407
+ <button id="stop-btn" onclick="stopText()" style="display:none;">
408
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
409
+ <rect x="6" y="6" width="12" height="12" rx="1" ry="1"></rect>
410
+ </svg>
411
+ </button>
412
+ <div>Listen to analysis</div>
413
+ </div>
414
+
415
+ <script>
416
+ function playText() {{
417
+ const text = {repr(text)};
418
+ const voice = "{voice}";
419
+
420
+ document.getElementById('play-btn').style.display = 'none';
421
+ document.getElementById('stop-btn').style.display = 'inline-block';
422
+
423
+ responsiveVoice.speak(text, voice, {{
424
+ onend: () => {{
425
+ document.getElementById('play-btn').style.display = 'inline-block';
426
+ document.getElementById('stop-btn').style.display = 'none';
427
+ }}
428
+ }});
429
+ }}
430
+
431
+ function stopText() {{
432
+ responsiveVoice.cancel();
433
+ document.getElementById('play-btn').style.display = 'inline-block';
434
+ document.getElementById('stop-btn').style.display = 'none';
435
+ }}
436
+ </script>
437
+ """
438
+
439
+ components.html(html, height=60)
440
+
441
+ # Create demo messages for user to try
442
+ def get_demo_messages():
443
+ return [
444
+ "Hello, I noticed an issue with your account. Please click this link to verify your details: http://amaz0n-secure.com/verify",
445
+ "URGENT: Your account has been compromised. Call this number immediately: +1-555-123-4567 to secure your account.",
446
+ "Dear user, we have detected unusual activity on your account. Please download this attachment to review the details.",
447
+ "This is a reminder that the company picnic is scheduled for this Saturday at 2pm in Central Park. Please RSVP by Thursday."
448
+ ]
449
+
450
+ # =======================
451
+ # Streamlit App UI
452
+ # =======================
453
+ def main():
454
+ load_css()
455
+
456
+ # App Header
457
+ st.markdown('<div class="app-header">', unsafe_allow_html=True)
458
+ col1, col2 = st.columns([1, 5])
459
+ with col1:
460
+ st.image("https://img.icons8.com/fluency/96/shield.png", width=80)
461
+ with col2:
462
+ st.title("🛡️ ZeroPhish Gate")
463
+ st.markdown("**AI-powered phishing detection and security education platform**")
464
+ st.markdown('</div>', unsafe_allow_html=True)
465
+
466
+ # Main app tabs
467
+ tab1, tab2, tab3 = st.tabs(["📝 Analyze Message", "📊 History", "📚 Security Resources"])
468
+
469
+ with tab1:
470
+ st.markdown('<div class="card">', unsafe_allow_html=True)
471
+ st.subheader("✉️ Enter the suspicious message")
472
+
473
+ # Input method selection
474
+ input_method = st.radio("Choose input method:", ["Text Input", "Upload File", "Try Demo"], horizontal=True)
475
+
476
+ text_input = ""
477
+
478
+ if input_method == "Text Input":
479
+ text_input = st.text_area("Paste the suspicious message here:", height=150)
480
+
481
+ elif input_method == "Upload File":
482
+ uploaded_file = st.file_uploader("📄 Upload PDF/TXT file", type=["pdf", "txt"])
483
+ if uploaded_file:
484
+ with st.spinner("Extracting text from file..."):
485
+ text_input = extract_text_from_file(uploaded_file)
486
+ if text_input:
487
+ st.success(f"✅ Successfully extracted {len(text_input)} characters from {uploaded_file.name}")
488
+ st.text_area("Extracted text:", text_input, height=150)
489
+ else:
490
+ st.error("❌ Could not extract text from the file.")
491
+
492
+ elif input_method == "Try Demo":
493
+ demo_messages = get_demo_messages()
494
+ selected_demo = st.selectbox(
495
+ "Select a demo message:",
496
+ range(len(demo_messages)),
497
+ format_func=lambda i: f"Demo {i+1}: {demo_messages[i][:50]}..."
498
+ )
499
+ text_input = demo_messages[selected_demo]
500
+ st.text_area("Demo message:", text_input, height=150)
501
+
502
+ col1, col2 = st.columns(2)
503
+ with col1:
504
+ language = st.selectbox("🌐 Preferred Language", language_choices)
505
+ with col2:
506
+ role = st.selectbox("🧑‍💼 Your Role", role_choices)
507
+
508
+ col1, col2 = st.columns([1, 4])
509
+ with col1:
510
+ analyze_btn = st.button("🔍 Analyze", use_container_width=True)
511
+ with col2:
512
+ clear_btn = st.button("🗑️ Clear History", use_container_width=True)
513
+ st.markdown('</div>', unsafe_allow_html=True)
514
+
515
+ # Run analysis
516
+ if analyze_btn and text_input.strip():
517
+ st.markdown('<div class="analyzing">', unsafe_allow_html=True)
518
+ st.markdown("🔄 **Analyzing message... please wait**")
519
+ st.markdown('</div>', unsafe_allow_html=True)
520
+
521
+ # Create a placeholder for the progress bar
522
+ progress_placeholder = st.empty()
523
+
524
+ # Simulate a progress bar for better UX
525
+ for percent_complete in range(0, 101, 5):
526
+ time.sleep(0.05)
527
+ progress_placeholder.progress(percent_complete)
528
+
529
+ # Analysis logic
530
+ label, score, threat_type = analyze_with_huggingface(text_input)
531
+ translated_threat = translate_label(threat_type, language)
532
+
533
+ # Remove the progress bar
534
+ progress_placeholder.empty()
535
+
536
+ # Get severity class for styling
537
+ severity = get_severity_class(threat_type, score)
538
+
539
+ # Display results
540
+ st.markdown(f'<div class="card card-{severity}">', unsafe_allow_html=True)
541
+ st.subheader("🔍 Analysis Results")
542
+
543
+ col1, col2 = st.columns([2, 1])
544
+ with col1:
545
+ st.markdown(f"""
546
+ <div class="report-container">
547
+ <h3>Threat Assessment</h3>
548
+ <p><span class="highlight">Detection:</span> <span class="badge badge-{severity}">{threat_type}</span> ({translated_threat})</p>
549
+ <p><span class="highlight">Confidence:</span> {score}%</p>
550
+ <p><span class="highlight">Status:</span> {'⚠️ CAUTION ADVISED' if threat_type.lower() != 'safe' else '✅ MESSAGE APPEARS SAFE'}</p>
551
+ </div>
552
+ """, unsafe_allow_html=True)
553
+
554
+ with col2:
555
+ # Show confidence visualization
556
+ confidence_chart = create_threat_visualization(threat_type, score)
557
+ st.image(confidence_chart, caption="Threat Confidence Level")
558
+
559
+ # More detailed analysis if suspicious
560
+ if threat_type.lower() != "safe":
561
+ st.markdown("### 🧠 Expert Analysis")
562
+
563
+ with st.spinner("Generating detailed analysis..."):
564
+ summary = semantic_analysis(text_input, role, language)
565
+ st.write(summary)
566
+
567
+ # Add voice playback using ResponsiveVoice
568
+ add_responsive_voice(summary, language)
569
+
570
+ col1, col2 = st.columns(2)
571
+ with col1:
572
+ if st.button("📤 Send Report to IT Security Team", use_container_width=True):
573
+ st.success("📨 Report sent to IT security team successfully.")
574
+
575
+ with col2:
576
+ # Generate and offer download link
577
+ report_path = create_report(label, score, threat_type, summary, text_input)
578
+ with open(report_path, "rb") as f:
579
+ report_data = f.read()
580
+ b64_report = base64.b64encode(report_data).decode()
581
+ href = f'<a href="data:file/txt;base64,{b64_report}" download="ZeroPhish_Report.txt" style="text-decoration:none;"><button style="background-color:#3B82F6;color:white;padding:0.5rem 1rem;border:none;border-radius:0.5rem;cursor:pointer;width:100%;">📄 Download Full Report</button></a>'
582
+ st.markdown(href, unsafe_allow_html=True)
583
+
584
+ # Security tips based on threat type
585
+ st.markdown("### 🔐 Security Tips")
586
+ if threat_type.lower() == "phishing":
587
+ st.info("• Never click on suspicious links\n• Check the sender's email address carefully\n• Contact the supposed sender through official channels to verify")
588
+ elif threat_type.lower() == "spam":
589
+ st.info("• Mark as spam in your email client\n• Consider using email filtering services\n• Don't reply or click on any links")
590
+ elif threat_type.lower() == "malware":
591
+ st.warning("• Don't download any attachments\n• Run a virus scan if you've interacted with this message\n• Report to your IT department immediately")
592
+ else:
593
+ st.success("✅ This message appears to be legitimate. No further action required.")
594
+
595
+ # Save to history
596
+ st.session_state.history.append({
597
+ "input": text_input,
598
+ "threat": threat_type,
599
+ "score": score,
600
+ "summary": summary if threat_type.lower() != "safe" else "Message appears to be safe. No detailed analysis required."
601
+ })
602
+
603
+ st.markdown('</div>', unsafe_allow_html=True)
604
+
605
+ elif analyze_btn and not text_input.strip():
606
+ st.warning("⚠️ Please enter some text or upload a file to analyze.")
607
+
608
+ with tab2:
609
+ st.subheader("📊 Analysis History")
610
+
611
+ if clear_btn:
612
+ st.session_state.history.clear()
613
+ st.success("✅ History cleared!")
614
+
615
+ render_history()
616
+
617
+ with tab3:
618
+ st.subheader("📚 Security Resources")
619
+
620
+ st.markdown('<div class="card">', unsafe_allow_html=True)
621
+ st.markdown("### 📖 Glossary of Security Terms")
622
+ for term, definition in GLOSSARY.items():
623
+ st.markdown(f"**{term.capitalize()}**: {definition}")
624
+ st.markdown('</div>', unsafe_allow_html=True)
625
+
626
+ st.markdown('<div class="card">', unsafe_allow_html=True)
627
+ st.markdown("### 🎓 Educational Resources")
628
+ st.markdown("""
629
+ * [CISA: Phishing Awareness](https://www.cisa.gov/topics/cyber-threats-and-advisories/phishing)
630
+ * [FTC: How to Recognize and Avoid Phishing Scams](https://consumer.ftc.gov/articles/how-recognize-and-avoid-phishing-scams)
631
+ * [Google's Phishing Quiz](https://phishingquiz.withgoogle.com/)
632
+ * [SANS Security Awareness Training](https://www.sans.org/security-awareness-training/)
633
+ """)
634
+ st.markdown('</div>', unsafe_allow_html=True)
635
+
636
+ st.markdown('<div class="card">', unsafe_allow_html=True)
637
+ st.markdown("### 🚨 How to Report Phishing")
638
+ st.markdown("""
639
+ **Internal Reporting:**
640
+ * Forward suspicious emails to your IT security team
641
+ * Report through your organization's security incident portal
642
+
643
+ **External Reporting:**
644
+ * [Report to the Anti-Phishing Working Group](https://apwg.org/reportphishing/)
645
+ * [Report to the FBI's Internet Crime Complaint Center](https://www.ic3.gov/)
646
+ * Forward phishing emails to [phishing-report@us-cert.gov](mailto:phishing-report@us-cert.gov)
647
+ """)
648
+ st.markdown('</div>', unsafe_allow_html=True)
649
+
650
+ # Footer
651
+ st.markdown("""
652
+ <hr>
653
+ <p style="text-align:center;color:#6B7280;font-size:0.8rem;">
654
+ ZeroPhish Gate | AI-powered phishing detection | Created with ❤️ for cybersecurity
655
+ </p>
656
+ """, unsafe_allow_html=True)
657
+
658
+ if __name__ == "__main__":
659
+ main()