Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Scam-Signal Verifier</title> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet"> | |
| <style> | |
| * { | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| } | |
| body { | |
| font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| min-height: 100vh; | |
| padding: 20px; | |
| } | |
| .container { | |
| max-width: 800px; | |
| margin: 0 auto; | |
| background: white; | |
| border-radius: 20px; | |
| box-shadow: 0 20px 60px rgba(0, 0, 0, 0.1); | |
| overflow: hidden; | |
| } | |
| .header { | |
| background: linear-gradient(135deg, #ff6b6b, #ffa726); | |
| color: white; | |
| padding: 30px; | |
| text-align: center; | |
| } | |
| .header h1 { | |
| font-size: 2.5rem; | |
| margin-bottom: 10px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 15px; | |
| } | |
| .header p { | |
| font-size: 1.1rem; | |
| opacity: 0.9; | |
| } | |
| .main-content { | |
| padding: 40px; | |
| } | |
| .input-section { | |
| margin-bottom: 30px; | |
| } | |
| .form-group { | |
| margin-bottom: 20px; | |
| } | |
| .form-group label { | |
| display: block; | |
| margin-bottom: 8px; | |
| font-weight: 600; | |
| color: #333; | |
| } | |
| .form-group textarea, | |
| .form-group input { | |
| width: 100%; | |
| padding: 15px; | |
| border: 2px solid #e1e5e9; | |
| border-radius: 10px; | |
| font-size: 14px; | |
| transition: border-color 0.3s ease; | |
| } | |
| .form-group textarea:focus, | |
| .form-group input:focus { | |
| outline: none; | |
| border-color: #667eea; | |
| } | |
| .form-group textarea { | |
| resize: vertical; | |
| min-height: 120px; | |
| } | |
| .analyze-btn { | |
| background: linear-gradient(135deg, #667eea, #764ba2); | |
| color: white; | |
| border: none; | |
| padding: 15px 40px; | |
| border-radius: 10px; | |
| font-size: 16px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| transition: transform 0.2s ease, box-shadow 0.2s ease; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| margin: 0 auto; | |
| } | |
| .analyze-btn:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 10px 30px rgba(102, 126, 234, 0.3); | |
| } | |
| .analyze-btn:disabled { | |
| opacity: 0.6; | |
| cursor: not-allowed; | |
| transform: none; | |
| box-shadow: none; | |
| } | |
| .loading { | |
| display: none; | |
| text-align: center; | |
| padding: 20px; | |
| color: #666; | |
| } | |
| .loading i { | |
| font-size: 24px; | |
| animation: spin 1s linear infinite; | |
| } | |
| @keyframes spin { | |
| 0% { transform: rotate(0deg); } | |
| 100% { transform: rotate(360deg); } | |
| } | |
| .results { | |
| display: none; | |
| margin-top: 30px; | |
| } | |
| .risk-indicator { | |
| text-align: center; | |
| padding: 30px; | |
| border-radius: 15px; | |
| margin-bottom: 30px; | |
| } | |
| .risk-high { | |
| background: linear-gradient(135deg, #ff4757, #ff3838); | |
| color: white; | |
| } | |
| .risk-medium { | |
| background: linear-gradient(135deg, #ffa726, #ff9800); | |
| color: white; | |
| } | |
| .risk-low { | |
| background: linear-gradient(135deg, #26c6da, #00acc1); | |
| color: white; | |
| } | |
| .risk-minimal { | |
| background: linear-gradient(135deg, #66bb6a, #4caf50); | |
| color: white; | |
| } | |
| .risk-score { | |
| font-size: 3rem; | |
| font-weight: 700; | |
| margin-bottom: 10px; | |
| } | |
| .risk-classification { | |
| font-size: 1.2rem; | |
| font-weight: 600; | |
| margin-bottom: 15px; | |
| } | |
| .risk-summary { | |
| font-size: 1rem; | |
| opacity: 0.9; | |
| } | |
| .analysis-section { | |
| margin-bottom: 30px; | |
| } | |
| .section-title { | |
| font-size: 1.3rem; | |
| font-weight: 600; | |
| color: #333; | |
| margin-bottom: 15px; | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| } | |
| .red-flags, | |
| .recommendations { | |
| background: #f8f9fa; | |
| border-radius: 10px; | |
| padding: 20px; | |
| } | |
| .flag-item, | |
| .recommendation-item { | |
| padding: 10px; | |
| margin-bottom: 10px; | |
| border-radius: 8px; | |
| border-left: 4px solid; | |
| } | |
| .flag-item { | |
| background: #fff5f5; | |
| border-left-color: #e53e3e; | |
| color: #c53030; | |
| } | |
| .recommendation-item { | |
| background: #f0fff4; | |
| border-left-color: #38a169; | |
| color: #2d3748; | |
| } | |
| .report-section { | |
| background: #f7fafc; | |
| border-radius: 10px; | |
| padding: 20px; | |
| } | |
| .report-template { | |
| background: white; | |
| border: 1px solid #e2e8f0; | |
| border-radius: 8px; | |
| padding: 15px; | |
| font-family: monospace; | |
| font-size: 12px; | |
| white-space: pre-wrap; | |
| max-height: 200px; | |
| overflow-y: auto; | |
| } | |
| .copy-btn { | |
| background: #4299e1; | |
| color: white; | |
| border: none; | |
| padding: 8px 16px; | |
| border-radius: 6px; | |
| cursor: pointer; | |
| margin-top: 10px; | |
| font-size: 14px; | |
| } | |
| .copy-btn:hover { | |
| background: #3182ce; | |
| } | |
| .footer { | |
| text-align: center; | |
| padding: 20px; | |
| background: #f8f9fa; | |
| color: #666; | |
| font-size: 14px; | |
| } | |
| .example-section { | |
| background: #f0f8ff; | |
| border-radius: 10px; | |
| padding: 20px; | |
| margin-bottom: 30px; | |
| } | |
| .example-title { | |
| font-weight: 600; | |
| color: #2c5aa0; | |
| margin-bottom: 15px; | |
| } | |
| .example-btn { | |
| background: #e6f3ff; | |
| border: 1px solid #b3d9ff; | |
| border-radius: 6px; | |
| padding: 8px 12px; | |
| margin: 5px; | |
| cursor: pointer; | |
| font-size: 12px; | |
| color: #2c5aa0; | |
| transition: background-color 0.2s ease; | |
| } | |
| .example-btn:hover { | |
| background: #cce7ff; | |
| } | |
| @media (max-width: 768px) { | |
| .header h1 { | |
| font-size: 2rem; | |
| } | |
| .main-content { | |
| padding: 20px; | |
| } | |
| .risk-score { | |
| font-size: 2.5rem; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="header"> | |
| <h1><i class="fas fa-shield-alt"></i> Scam-Signal Verifier</h1> | |
| <p>Protect yourself from phishing attempts and fraudulent messages</p> | |
| </div> | |
| <div class="main-content"> | |
| <div class="example-section"> | |
| <div class="example-title">🎯 Try these examples:</div> | |
| <button class="example-btn" onclick="loadExample('phishing')">Phishing Email</button> | |
| <button class="example-btn" onclick="loadExample('job')">Fake Job Offer</button> | |
| <button class="example-btn" onclick="loadExample('investment')">Investment Scam</button> | |
| <button class="example-btn" onclick="loadExample('lottery')">Lottery Scam</button> | |
| </div> | |
| <div class="input-section"> | |
| <div class="form-group"> | |
| <label for="message-input">📧 Paste suspicious message or text:</label> | |
| <textarea id="message-input" placeholder="Paste the suspicious message, email, text, or advertisement content here..."></textarea> | |
| </div> | |
| <div class="form-group"> | |
| <label for="url-input">🔗 URL (optional):</label> | |
| <input type="url" id="url-input" placeholder="https://example.com/suspicious-link"> | |
| </div> | |
| <button class="analyze-btn" onclick="analyzeMessage()"> | |
| <i class="fas fa-search"></i> | |
| <span>Analyze for Scam Signals</span> | |
| </button> | |
| </div> | |
| <div class="loading"> | |
| <i class="fas fa-spinner"></i> | |
| <p>Analyzing message for scam signals...</p> | |
| </div> | |
| <div class="results" id="results"> | |
| <!-- Results will be populated here --> | |
| </div> | |
| </div> | |
| <div class="footer"> | |
| <p>🛡️ Stay safe online • Report suspicious messages to relevant authorities</p> | |
| </div> | |
| </div> | |
| <script> | |
| const examples = { | |
| phishing: `URGENT: Your account will be suspended in 24 hours! | |
| Dear Customer, | |
| We have detected suspicious activity on your account. To prevent closure, verify your information immediately by clicking here: http://secure-bank-verify.net/login | |
| Your account ID: AC-2024-789456 | |
| Time remaining: 23:47:52 | |
| Act now to avoid permanent suspension!`, | |
| job: `🎉 CONGRATULATIONS! You've been selected for a $5000/week work from home opportunity! | |
| No experience required! Just send $99 for training materials to get started. | |
| Limited spots available - act within 2 hours! | |
| Contact: jobs.opportunity@email.com | |
| Phone: (555) 123-SCAM`, | |
| investment: `💰 Double your Bitcoin in 30 days - GUARANTEED! | |
| Join thousands of successful investors earning $10,000+ monthly | |
| ✅ Risk-free investment | |
| ✅ Government approved | |
| ✅ 200% return guaranteed | |
| Send minimum $500 to wallet: 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa | |
| Limited time offer expires TODAY!`, | |
| lottery: `🎊 YOU HAVE WON $2,000,000 in the International Email Lottery! | |
| Confirmation Number: UK/2024/WIN/789 | |
| Your winning email was randomly selected from 50 million addresses. | |
| To claim your prize: | |
| 1. Send $500 processing fee | |
| 2. Provide bank details | |
| 3. Copy of government ID | |
| Contact Mrs. Sarah Johnson: claim.lottery@winner-mail.com | |
| URGENT: Claim expires in 48 hours!` | |
| }; | |
| function loadExample(type) { | |
| document.getElementById('message-input').value = examples[type]; | |
| document.getElementById('url-input').value = ''; | |
| } | |
| async function analyzeMessage() { | |
| const messageText = document.getElementById('message-input').value.trim(); | |
| const urlText = document.getElementById('url-input').value.trim(); | |
| if (!messageText && !urlText) { | |
| alert('Please enter a message or URL to analyze'); | |
| return; | |
| } | |
| // Show loading state | |
| document.querySelector('.analyze-btn').disabled = true; | |
| document.querySelector('.loading').style.display = 'block'; | |
| document.querySelector('.results').style.display = 'none'; | |
| try { | |
| const response = await fetch('/analyze', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ | |
| message: messageText, | |
| url: urlText | |
| }) | |
| }); | |
| const data = await response.json(); | |
| if (data.error) { | |
| throw new Error(data.error); | |
| } | |
| displayResults(data); | |
| } catch (error) { | |
| alert('Error analyzing message: ' + error.message); | |
| } finally { | |
| // Hide loading state | |
| document.querySelector('.analyze-btn').disabled = false; | |
| document.querySelector('.loading').style.display = 'none'; | |
| } | |
| } | |
| function displayResults(data) { | |
| const resultsDiv = document.getElementById('results'); | |
| const explanation = data.explanation; | |
| const riskClass = explanation.classification.toLowerCase().replace(' ', '-'); | |
| resultsDiv.innerHTML = ` | |
| <div class="risk-indicator risk-${riskClass}"> | |
| <div class="risk-score">${explanation.risk_score}</div> | |
| <div class="risk-classification">${explanation.classification}</div> | |
| <div class="risk-summary">${explanation.summary}</div> | |
| </div> | |
| ${explanation.red_flags.length > 0 ? ` | |
| <div class="analysis-section"> | |
| <div class="section-title"> | |
| <i class="fas fa-exclamation-triangle"></i> | |
| Red Flags Detected | |
| </div> | |
| <div class="red-flags"> | |
| ${explanation.red_flags.map(flag => ` | |
| <div class="flag-item">🚨 ${flag}</div> | |
| `).join('')} | |
| </div> | |
| </div> | |
| ` : ''} | |
| <div class="analysis-section"> | |
| <div class="section-title"> | |
| <i class="fas fa-lightbulb"></i> | |
| Recommendations | |
| </div> | |
| <div class="recommendations"> | |
| ${explanation.recommendations.map(rec => ` | |
| <div class="recommendation-item">${rec}</div> | |
| `).join('')} | |
| </div> | |
| </div> | |
| <div class="analysis-section"> | |
| <div class="section-title"> | |
| <i class="fas fa-flag"></i> | |
| Report Template | |
| </div> | |
| <div class="report-section"> | |
| <div class="report-template" id="report-template">${explanation.report_template}</div> | |
| <button class="copy-btn" onclick="copyReportTemplate()"> | |
| <i class="fas fa-copy"></i> Copy Report Template | |
| </button> | |
| </div> | |
| </div> | |
| `; | |
| resultsDiv.style.display = 'block'; | |
| resultsDiv.scrollIntoView({ behavior: 'smooth' }); | |
| } | |
| function copyReportTemplate() { | |
| const template = document.getElementById('report-template').textContent; | |
| navigator.clipboard.writeText(template).then(() => { | |
| const btn = event.target.closest('.copy-btn'); | |
| const originalText = btn.innerHTML; | |
| btn.innerHTML = '<i class="fas fa-check"></i> Copied!'; | |
| btn.style.background = '#48bb78'; | |
| setTimeout(() => { | |
| btn.innerHTML = originalText; | |
| btn.style.background = '#4299e1'; | |
| }, 2000); | |
| }).catch(() => { | |
| // Fallback for older browsers | |
| const textArea = document.createElement('textarea'); | |
| textArea.value = template; | |
| document.body.appendChild(textArea); | |
| textArea.select(); | |
| document.execCommand('copy'); | |
| document.body.removeChild(textArea); | |
| alert('Report template copied to clipboard!'); | |
| }); | |
| } | |
| // Allow Enter key to submit in textarea (Shift+Enter for new line) | |
| document.getElementById('message-input').addEventListener('keydown', function(event) { | |
| if (event.key === 'Enter' && !event.shiftKey) { | |
| event.preventDefault(); | |
| analyzeMessage(); | |
| } | |
| }); | |
| // Auto-resize textarea | |
| document.getElementById('message-input').addEventListener('input', function() { | |
| this.style.height = 'auto'; | |
| this.style.height = Math.max(120, this.scrollHeight) + 'px'; | |
| }); | |
| </script> | |
| </body> | |
| </html> |