313 lines
16 KiB
HTML
313 lines
16 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>AntiScam Pro</title>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
|
|
<link rel="stylesheet" href="/static/css/style.css">
|
|
</head>
|
|
<body class="transition-theme">
|
|
|
|
<div class="container py-5">
|
|
<!-- Standard Bootstrap container (responsive) -->
|
|
<!-- Header with title and buttons - using responsive flexbox -->
|
|
<!-- d-flex justify-content-between align-items-center is a default horizontal flexbox -->
|
|
<!-- flex-column-sm-row: stack in column on < sm, row on >= sm -->
|
|
<div class="d-flex justify-content-between align-items-center mb-4 flex-column flex-sm-row">
|
|
<!-- Title - bottom margin on small screens (mb-3), removed on >= sm (mb-sm-0) -->
|
|
<h1 class="fw-bold mb-3 mb-sm-0">AntiScam Pro</h1>
|
|
|
|
<!-- Button container - also stacked on small screens -->
|
|
<div class="d-flex flex-column flex-sm-row">
|
|
<!-- Theme button - bottom margin on small, right margin on >= sm -->
|
|
<button id="toggleTheme" class="btn btn-outline-secondary mb-2 me-sm-2">
|
|
<i class="fas fa-moon"></i> <span id="theme-btn-text" data-pl="Zmień motyw" data-en="Toggle theme">Toggle theme</span>
|
|
</button>
|
|
<!-- Language toggle button -->
|
|
<button id="toggleLanguage" class="btn btn-outline-secondary">
|
|
<i class="fas fa-language"></i> <span id="lang-btn-text">PL</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Form section -->
|
|
<form method="POST" class="bg-body-tertiary p-4 rounded shadow-sm">
|
|
<input type="hidden" name="lang" id="langInput" value="en">
|
|
<div class="mb-3">
|
|
<!-- Single textarea instead of 3 inputs -->
|
|
<label for="single_input" class="form-label" data-pl="Wprowadź dane do analizy:" data-en="Enter data for analysis:">Enter data for analysis:</label>
|
|
<textarea name="input_data" id="single_input" rows="3" class="form-control"
|
|
data-pl-placeholder="Wprowadź wiadomość, numer telefonu lub link..."
|
|
data-en-placeholder="Enter message, phone number, or link..."
|
|
placeholder="Enter message, phone number, or link..."></textarea>
|
|
</div>
|
|
<!-- Submit button -->
|
|
<button type="submit" class="btn btn-primary" data-pl="Sprawdź" data-en="Check">Check</button>
|
|
</form>
|
|
|
|
<!-- Results section -->
|
|
<div class="mt-4">
|
|
|
|
<!-- Message result -->
|
|
{% if result.message %}
|
|
<div class="alert {{ 'alert-danger' if result.message.is_suspicious else 'alert-success' }}">
|
|
<strong data-pl="Wiadomość:" data-en="Message:">Message:</strong>
|
|
{% if result.message.is_suspicious %}
|
|
{% if result.message.suspicious_words %}
|
|
<span data-pl="Podejrzana. Znalezione wyrazy:" data-en="Suspicious. Found words:">Suspicious. Found words:</span>
|
|
<em>{{ result.message.suspicious_words | join(', ') }}</em>
|
|
{% endif %}
|
|
{% if result.message.ai_result %}
|
|
<p data-pl="Wykryte przez AI:" data-en="Detected by AI:">Detected by AI:</p>
|
|
<p>{{ result.message.ai_result.label }} ({{ (result.message.ai_result.confidence * 100) | round(1) }}%)</p>
|
|
{% endif %}
|
|
{% else %}
|
|
<span data-pl="Brak podejrzanych treści." data-en="No suspicious content.">No suspicious content.</span>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Phone number result -->
|
|
{% if result.phone %}
|
|
<div class="alert {{ 'alert-danger' if result.phone.is_suspicious else 'alert-success' }}">
|
|
<strong data-pl="Numer telefonu:" data-en="Phone number:">Phone number:</strong>
|
|
{% if result.phone.is_suspicious %}
|
|
<span data-pl="Podejrzany numer." data-en="Suspicious number.">Suspicious number.</span>
|
|
<p data-pl="Powód podejrzenia: Numer w bazie danych podejrzanych numerów." data-en="Reason: Number found in suspicious database.">
|
|
Reason: Number found in suspicious database.
|
|
</p>
|
|
{% else %}
|
|
<span data-pl="Wygląda na bezpieczny." data-en="Looks safe.">Looks safe.</span>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Link result section -->
|
|
{% if result.link is defined and (result.link.is_suspicious or result.link.details) %}
|
|
|
|
{% set overall_link_suspicious_display = result.link.is_suspicious %}
|
|
|
|
<div class="alert {{ 'alert-danger' if overall_link_suspicious_display else 'alert-success' }}">
|
|
<strong data-pl="Link:" data-en="Link:">Link:</strong>
|
|
|
|
{% if overall_link_suspicious_display %}
|
|
<span style="color: red;" data-pl="Podejrzany." data-en="Suspicious.">Suspicious.</span>
|
|
{% else %}
|
|
<span style="color: green;" data-pl="Brak podejrzanej aktywności." data-en="No suspicious activity detected.">No suspicious activity detected.</span>
|
|
{% endif %}
|
|
|
|
{% if result.link.details %}
|
|
<p data-pl="Szczegóły analizy:" data-en="Analysis Details:">Analysis Details:</p>
|
|
<ul>
|
|
{% for detail in result.link.details %}
|
|
<li>
|
|
<span data-pl="{{ detail.get('data-pl', detail.get('text', '')) }}" data-en="{{ detail.get('data-en', detail.get('text', '')) }}">
|
|
{{ detail.get('text', 'Unknown analysis detail') }}
|
|
</span>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
{% elif not overall_link_suspicious_display %}
|
|
<p data-pl="Brak dodatkowych szczegółów analizy." data-en="No additional analysis details.">No additional analysis details.</p>
|
|
{% endif %}
|
|
|
|
{% if result.link is defined and result.link.is_valid is defined %}
|
|
<p data-pl="Format URL poprawny: {{ 'Tak' if result.link.is_valid else 'Nie' }}" data-en="URL format valid: {{ 'Yes' if result.link.is_valid else 'No' }}">URL format valid: {{ 'Yes' if result.link.is_valid else 'No' }}</p>
|
|
{% endif %}
|
|
</div>
|
|
{% elif result.link is not defined %}
|
|
<div class="alert alert-info">
|
|
<span data-pl="Podaj dane do analizy." data-en="Provide data for analysis.">Provide data for analysis.</span>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Info and Statistics section -->
|
|
<div class="container mt-4">
|
|
<div class="row g-4">
|
|
<div class="col-md-6">
|
|
<div class="card h-100 transition-theme">
|
|
<div class="card-body">
|
|
<h2 class="card-title" data-pl="O AntiScam Pro" data-en="About AntiScam Pro">About AntiScam Pro</h2>
|
|
<p class="card-text" data-pl="AntiScam Pro to zaawansowana aplikacja do wykrywania oszustw..." data-en="AntiScam Pro is an advanced tool for scam detection...">
|
|
AntiScam Pro is an advanced application for detecting scams, spam, and suspicious links. It uses AI and databases to ensure safety.
|
|
</p>
|
|
|
|
<h3 class="card-title" data-pl="Funkcje:" data-en="Features:">Features:</h3>
|
|
<ul class="list-group list-group-flush">
|
|
<li class="list-group-item transition-theme" data-pl="Wykrywanie podejrzanych wiadomości tekstowych" data-en="Detects suspicious text messages">Detects suspicious text messages</li>
|
|
<li class="list-group-item transition-theme" data-pl="Weryfikacja numerów telefonów i linków" data-en="Phone number and link verification">Phone number and link verification</li>
|
|
<li class="list-group-item transition-theme">
|
|
<details>
|
|
<summary data-pl="Integracja z VirusTotal" data-en="Integration with VirusTotal">Integration with VirusTotal</summary>
|
|
<p class="text-muted mt-2 transition-theme" data-pl="Analiza linków obejmuje skanowanie VirusTotal..." data-en="Link analysis includes VirusTotal scanning if API key is configured and link requires verification.">
|
|
Link analysis includes VirusTotal scanning if API key is configured and link requires verification.
|
|
</p>
|
|
</details>
|
|
</li>
|
|
<li class="list-group-item transition-theme">
|
|
<details>
|
|
<summary data-pl="Obszerne bazy danych" data-en="Extensive databases">Extensive databases</summary>
|
|
<p class="text-muted mt-2 transition-theme" data-pl="Nasza baza zawiera..." data-en="Our database contains over 186,000 suspicious domains.">
|
|
Our database contains over 186,000 suspicious domains.
|
|
</p>
|
|
</details>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="card h-100 transition-theme">
|
|
<div class="card-body">
|
|
<h3 class="card-title" data-pl="📊 Statystyki globalne" data-en="📊 Global statistics">📊 Global statistics</h3>
|
|
<p class="text-muted transition-theme" data-pl="(od uruchomienia serwera)" data-en="(since server start)">(since server start)</p>
|
|
<ul class="list-group list-group-flush">
|
|
<li class="list-group-item transition-theme">
|
|
<span data-pl="Wiadomości sprawdzone:" data-en="Messages checked:">Messages checked:</span>
|
|
<span class="badge bg-primary">{{ global_stats.messages_checked }}</span>
|
|
</li>
|
|
<li class="list-group-item transition-theme">
|
|
<span data-pl="Numery sprawdzone:" data-en="Phones checked:">Phones checked:</span>
|
|
<span class="badge bg-primary">{{ global_stats.phones_checked }}</span>
|
|
</li>
|
|
<li class="list-group-item transition-theme">
|
|
<span data-pl="Linki sprawdzone:" data-en="Links checked:">Links checked:</span>
|
|
<span class="badge bg-primary">{{ global_stats.links_checked }}</span>
|
|
</li>
|
|
</ul>
|
|
|
|
<h3 class="card-title mt-4" data-pl="👤 Twoje statystyki" data-en="👤 Your statistics">👤 Your statistics</h3>
|
|
<p class="text-muted transition-theme" data-pl="(ta sesja)" data-en="(this session)">(this session)</p>
|
|
<ul class="list-group list-group-flush">
|
|
<li class="list-group-item transition-theme">
|
|
<span data-pl="Wiadomości sprawdzone:" data-en="Messages checked:">Messages checked:</span>
|
|
<span class="badge bg-info">{{ session_stats.messages_checked }}</span>
|
|
</li>
|
|
<li class="list-group-item transition-theme">
|
|
<span data-pl="Numery sprawdzone:" data-en="Phones checked:">Phones checked:</span>
|
|
<span class="badge bg-info">{{ session_stats.phones_checked }}</span>
|
|
</li>
|
|
<li class="list-group-item transition-theme">
|
|
<span data-pl="Linki sprawdzone:" data-en="Links checked:">Links checked:</span>
|
|
<span class="badge bg-info">{{ session_stats.links_checked }}</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
<!-- JS Scripts -->
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
|
|
<script>
|
|
const btnTheme = document.getElementById("toggleTheme");
|
|
const btnLang = document.getElementById("toggleLanguage");
|
|
const themeText = document.getElementById("theme-btn-text");
|
|
const langText = document.getElementById("lang-btn-text");
|
|
const langInput = document.getElementById("langInput");
|
|
const singleInput = document.getElementById("single_input");
|
|
|
|
// User system preference for dark mode
|
|
const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)');
|
|
|
|
// Get preferences from localStorage or use system preference
|
|
let darkMode = localStorage.getItem("darkMode");
|
|
if (darkMode === null) {
|
|
darkMode = prefersDarkMode.matches;
|
|
} else {
|
|
darkMode = (darkMode === "true");
|
|
}
|
|
|
|
// Default language = English
|
|
let lang = localStorage.getItem("lang") || "en";
|
|
|
|
// Update theme button text and icon
|
|
function updateThemeButtonText(isDarkMode, currentLang) {
|
|
const textPl = isDarkMode ? "Jasny motyw" : "Ciemny motyw";
|
|
const textEn = isDarkMode ? "Light theme" : "Dark theme";
|
|
if (themeText) {
|
|
themeText.dataset.pl = textPl;
|
|
themeText.dataset.en = textEn;
|
|
themeText.textContent = currentLang === "pl" ? textPl : textEn;
|
|
}
|
|
const themeIcon = btnTheme ? btnTheme.querySelector('i') : null;
|
|
if (themeIcon) {
|
|
themeIcon.classList.toggle('fa-moon', isDarkMode);
|
|
themeIcon.classList.toggle('fa-sun', !isDarkMode);
|
|
}
|
|
}
|
|
|
|
// Apply theme
|
|
function applyTheme(isDarkMode) {
|
|
if (document.body) {
|
|
document.body.classList.toggle("dark-mode", isDarkMode);
|
|
updateThemeButtonText(isDarkMode, lang);
|
|
localStorage.setItem("darkMode", isDarkMode);
|
|
}
|
|
}
|
|
|
|
// Apply language + placeholder updates
|
|
function applyLanguage(language) {
|
|
document.querySelectorAll("[data-pl]").forEach(el => {
|
|
if (el.dataset.pl && el.dataset.en) {
|
|
el.textContent = el.dataset[language];
|
|
}
|
|
});
|
|
if (singleInput) {
|
|
singleInput.placeholder = singleInput.dataset[language + '-placeholder'] || singleInput.placeholder;
|
|
}
|
|
if (langText) {
|
|
langText.textContent = language === "pl" ? "EN" : "PL";
|
|
}
|
|
if (langInput) {
|
|
langInput.value = language;
|
|
}
|
|
localStorage.setItem("lang", language);
|
|
updateThemeButtonText(darkMode, language);
|
|
}
|
|
|
|
// Initial setup
|
|
applyTheme(darkMode);
|
|
applyLanguage(lang);
|
|
|
|
// Button listeners
|
|
if (btnTheme) {
|
|
btnTheme.addEventListener("click", () => {
|
|
darkMode = !darkMode;
|
|
applyTheme(darkMode);
|
|
});
|
|
}
|
|
if (btnLang) {
|
|
btnLang.addEventListener("click", () => {
|
|
lang = lang === "pl" ? "en" : "pl";
|
|
applyLanguage(lang);
|
|
});
|
|
}
|
|
|
|
// System preference listener
|
|
if (prefersDarkMode) {
|
|
prefersDarkMode.addListener(function(e) {
|
|
if (localStorage.getItem("darkMode") === null) {
|
|
applyTheme(e.matches);
|
|
}
|
|
});
|
|
}
|
|
|
|
console.log("AntiScam Pro custom JavaScript script finished execution.");
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|
|
|