(function() { if (window.location.pathname !== '/challenges') return; // LocalStorage to bypass server-side cache delays const getLocalSolves = () => JSON.parse(localStorage.getItem('temp_solves') || "[]"); const addLocalSolve = (id) => { const solves = getLocalSolves(); if (!solves.includes(id)) { solves.push(id); localStorage.setItem('temp_solves', JSON.stringify(solves)); } }; function injectBoxes(config) { // Highlight locally solved challenges getLocalSolves().forEach(id => { const el = document.querySelector(`[data-id="${id}"]`); if (el && !el.classList.contains('solved')) el.classList.add('solved'); }); const enabledCategories = config.categories || []; // We look for category headers document.querySelectorAll('.category-header').forEach(header => { const catName = header.textContent.trim(); // Prevent duplicate injections if (enabledCategories.includes(catName) && !header.parentElement.querySelector('.cat-sub-container')) { const container = document.createElement('div'); container.className = "cat-sub-container mb-4"; // Style to match the alignment of the text exactly container.style.maxWidth = "700px"; container.style.marginTop = "10px"; container.innerHTML = `
`; header.after(container); const input = container.querySelector('input'); const btn = container.querySelector('button'); const msg = container.querySelector('.status-msg'); const submitFlag = () => { const val = input.value.trim(); if (!val || btn.disabled) return; btn.disabled = true; msg.innerHTML = 'Checking flag...'; const params = new URLSearchParams({ submission: val, category: catName, nonce: init.csrfNonce }); fetch('/category_submit', { method: 'POST', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, body: params }) .then(r => r.json()) .then(data => { if (data.success) { addLocalSolve(data.challenge_id); msg.innerHTML = `✔ ${data.message}`; input.value = ''; // Visual feedback on the challenge card const card = document.querySelector(`[data-id="${data.challenge_id}"]`); if (card) card.classList.add('solved'); setTimeout(() => { window.location.reload(); }, 1200); } else { msg.innerHTML = `✘ ${data.message}`; btn.disabled = false; } }) .catch(() => { msg.innerHTML = 'Submission error'; btn.disabled = false; }); }; btn.onclick = submitFlag; input.onkeypress = (e) => { if (e.key === 'Enter') submitFlag(); }; } }); } fetch('/category_submit/config') .then(r => r.json()) .then(config => { injectBoxes(config); const observer = new MutationObserver(() => { observer.disconnect(); injectBoxes(config); observer.observe(document.body, { childList: true, subtree: true }); }); observer.observe(document.body, { childList: true, subtree: true }); }); })();