DeepShield-Web / static /script.js
MrTsp's picture
Update static/script.js
b15c9f4
/**
* DeepShield AI — script.js (SupCon SOTA Version)
*/
const API_URL = "";
async function checkServerStatus() {
const statusMenu = document.getElementById("server-status");
const statusText = document.getElementById("status-text");
const dropZone = document.getElementById("drop-zone");
if (!statusMenu) return;
try {
const res = await fetch(`${API_URL}/health`);
if (!res.ok) throw new Error("Server not OK");
const data = await res.json();
statusMenu.className = "server-status";
if (data.model_loaded === true) {
statusMenu.classList.add("status-connected");
statusText.textContent = "AI Ready ✓";
dropZone.style.pointerEvents = "auto";
dropZone.style.opacity = "1";
document.querySelector(".drop-title").innerHTML = "Drop your video or photo here";
} else {
statusMenu.classList.add("status-error");
statusText.textContent = "Model Missing";
dropZone.style.pointerEvents = "none";
dropZone.style.opacity = "0.5";
document.querySelector(".drop-title").innerHTML = "⚠️ Model Not Uploaded";
document.querySelector(".drop-sub").textContent = "Upload best_model.pth from scripts3.";
}
} catch (err) {
statusMenu.className = "server-status status-error";
statusText.textContent = "Starting Server...";
dropZone.style.pointerEvents = "none";
dropZone.style.opacity = "0.5";
}
}
checkServerStatus();
setInterval(checkServerStatus, 10000);
const MAX_FILE_MB = 30;
const MAX_FILE_BYTES = MAX_FILE_MB * 1024 * 1024;
let currentFile = null;
function showSection(id) {
["upload-section", "loading-section", "results-section", "error-section"].forEach(s => {
document.getElementById(s).classList.toggle("hidden", s !== id);
});
}
function onDragOver(e) { e.preventDefault(); document.getElementById("drop-zone").classList.add("dragging"); }
function onDragLeave() { document.getElementById("drop-zone").classList.remove("dragging"); }
function onDrop(e) {
e.preventDefault();
document.getElementById("drop-zone").classList.remove("dragging");
const file = e.dataTransfer?.files?.[0];
if (file) processFile(file);
}
function onFileSelected(e) {
const file = e.target.files?.[0];
if (file) processFile(file);
}
function processFile(file) {
const allowedExt = [".mp4", ".mov", ".avi", ".mkv", ".jpg", ".jpeg", ".png", ".webp"];
const ext = "." + file.name.split(".").pop().toLowerCase();
if (!allowedExt.includes(ext)) {
showError(`❌ Unsupported file type. Use Video (MP4/MOV/AVI) or Photo (JPG/PNG).`);
return;
}
if (file.size > MAX_FILE_BYTES) {
showError(`❌ File too large. Max: ${MAX_FILE_MB} MB.`);
return;
}
currentFile = file;
document.getElementById("file-name").textContent = file.name;
document.getElementById("file-size").textContent = (file.size / (1024*1024)).toFixed(1) + " MB";
const url = URL.createObjectURL(file);
const isVideo = [".mp4", ".mov", ".avi", ".mkv"].includes(ext);
const videoPrev = document.getElementById("video-preview");
const videoCont = document.getElementById("video-container");
// Check if image-preview element exists, if not create it
let imgPrev = document.getElementById("image-preview");
if (!imgPrev) {
imgPrev = document.createElement("img");
imgPrev.id = "image-preview";
imgPrev.className = "video-preview"; // reuse styling
videoCont.appendChild(imgPrev);
}
if (isVideo) {
videoPrev.src = url;
videoPrev.style.display = "block";
imgPrev.style.display = "none";
} else {
videoPrev.style.display = "none";
imgPrev.src = url;
imgPrev.style.display = "block";
}
document.getElementById("drop-zone").classList.add("hidden");
document.getElementById("file-preview").classList.remove("hidden");
}
function resetUpload() {
currentFile = null;
document.getElementById("file-input").value = "";
showSection("upload-section");
document.getElementById("drop-zone").classList.remove("hidden");
document.getElementById("file-preview").classList.add("hidden");
document.getElementById("ring-fill").style.strokeDashoffset = "314";
}
async function analyzeVideo() {
if (!currentFile) return;
showSection("loading-section");
const formData = new FormData();
formData.append("file", currentFile);
try {
const res = await fetch(`${API_URL}/predict`, { method: "POST", body: formData });
if (!res.ok) throw new Error("Analysis failed on server.");
const data = await res.json();
renderResults(data);
showSection("results-section");
} catch (err) {
showError(err.message);
}
}
function renderResults(data) {
const isFake = data.verdict === "FAKE";
const fakePct = data.fake_probability;
document.getElementById("verdict-card").className = "verdict-card " + (isFake ? "is-fake" : "is-real");
document.getElementById("verdict-pct").textContent = `${fakePct}%`;
document.getElementById("verdict-label").textContent = data.verdict;
document.getElementById("verdict-badge").textContent = isFake ? "⚠ FAKE DETECTED" : "✅ REAL CONTENT";
document.getElementById("verdict-badge").className = "verdict-badge " + (isFake ? "fake" : "real");
const ring = document.getElementById("ring-fill");
ring.style.stroke = isFake ? "#ef4444" : "#22c55e";
ring.style.strokeDashoffset = 314 - (fakePct / 100) * 314;
document.getElementById("stat-fake").textContent = `${fakePct}%`;
document.getElementById("stat-real").textContent = `${data.real_probability}%`;
document.getElementById("stat-frames").textContent = data.frame_count;
document.getElementById("stat-size").textContent = data.file_size_mb + " MB";
renderFrameChart(data.per_frame_scores || []);
}
function renderFrameChart(scores) {
const container = document.getElementById("frame-chart");
container.innerHTML = "";
scores.forEach((s, i) => {
const bar = document.createElement("div");
bar.className = "bar-wrap";
bar.innerHTML = `<div class="bar ${s > 50 ? 'bar-fake' : 'bar-real'}" style="height:${s}%"></div>`;
container.appendChild(bar);
});
}
function showError(msg) {
document.getElementById("error-msg").textContent = msg;
showSection("error-section");
}