SEVENX AI — 10 AI TOOLS — IMAGE GENERATOR — CHAT ASSISTANT — BACKGROUND REMOVER — LOGO MAKER — ART STYLES — COLOR PALETTE — ASCII ART — IMAGE VARIATIONS — PROMPT ENHANCER — THUMBNAIL MAKER — POWERED BY POLLINATIONS.AI — 100% FREE — SEVENX AI — 10 AI TOOLS — IMAGE GENERATOR — CHAT ASSISTANT — BACKGROUND REMOVER — LOGO MAKER — ART STYLES — COLOR PALETTE — ASCII ART — IMAGE VARIATIONS — PROMPT ENHANCER — THUMBNAIL MAKER —
SevenX AI Creator Suite
10 powerful AI tools. 100% free..
#ffffff`; break; case 5: html += `
`; break; case 6: html += `
`; break; case 7: html += `
`; break; case 8: html += `
0
Kata
0
Karakter
0
Tanpa Spasi
0
Kalimat
`; break; case 9: html += `
`; break; } return html; } function initToolScript(idx) { if (idx === 8) updateWordCount(); } // ============ 5 API FALLBACK SYSTEM ============ async function downloadWithFallback(platform, type = 'video') { const idMap = { tiktok: 'tt', instagram: 'ig', youtube: 'yt' }; const prefix = idMap[platform]; const urlInput = document.getElementById(`${prefix}Url`); const resultDiv = document.getElementById(`${prefix}Result`); const progressFill = document.getElementById(`${prefix}Progress`); if (!urlInput || !urlInput.value.trim()) { if (resultDiv) { resultDiv.style.display = 'block'; resultDiv.className = 'result-box error'; resultDiv.textContent = 'URL tidak boleh kosong.'; } return; } const url = urlInput.value.trim(); const apis = API_ENDPOINTS[platform]; resultDiv.style.display = 'block'; resultDiv.className = 'result-box'; resultDiv.innerHTML = 'Mencoba API #1 dari 5...'; if (progressFill) progressFill.style.width = '0%'; let apiLog = ''; let successData = null; let successApiName = ''; for (let i = 0; i < apis.length; i++) { try { resultDiv.innerHTML = `Mencoba API #${i+1} dari 5: ${apis[i].name}...`; if (progressFill) progressFill.style.width = `${((i+1)/apis.length)*100}%`; const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 15000); const apiUrl = apis[i].url.replace('{URL}', encodeURIComponent(url)); const response = await fetch(apiUrl, { signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok) throw new Error(`HTTP ${response.status}`); const data = await response.json(); let extracted = null; if (platform === 'tiktok') { extracted = data.video?.noWatermark || data.video?.watermark || data.data?.play || data.download || (typeof data.video === 'string' ? data.video : null); } else if (platform === 'instagram') { extracted = data.media?.url || data.download_url || data.url || data.video_url || data.thumbnail; } else if (platform === 'youtube') { extracted = type === 'mp3' ? (data.audio || data.mp3 || data.download_url) : (data.video || data.download_url || data.formats?.[0]?.url); } if (extracted) { successData = typeof extracted === 'string' ? extracted : extracted; successApiName = apis[i].name; apiLog += `API #${i+1} ${apis[i].name}: BERHASIL
`; if (progressFill) progressFill.style.width = '100%'; break; } throw new Error('Data tidak ditemukan'); } catch (err) { apiLog += `API #${i+1} ${apis[i].name}: GAGAL
`; continue; } } if (successData) { const mediaUrl = successData; resultDiv.className = 'result-box success'; if (platform === 'youtube') { resultDiv.innerHTML = ` Berhasil via: ${successApiName}

YouTube ${type.toUpperCase()} siap diunduh!

Download ${type.toUpperCase()}
${apiLog}
`; } else { resultDiv.innerHTML = ` Berhasil via: ${successApiName} Download Media
${apiLog}
`; } } else { resultDiv.className = 'result-box error'; resultDiv.innerHTML = ` Semua 5 API gagal.

URL mungkin tidak valid, video privat, atau server API sedang down.

${apiLog}
`; } } function startQRScanner() { const el = document.getElementById('qrReader'); if (!el) return; if (qrScanner) { qrScanner.stop().then(() => { qrScanner.clear(); qrScanner = null; startQRScanner(); }); return; } document.getElementById('qrStartBtn').style.display = 'none'; document.getElementById('qrStopBtn').style.display = 'inline-flex'; qrScanner = new Html5Qrcode("qrReader"); qrScanner.start({ facingMode: "environment" }, { fps: 10, qrbox: 250 }, (txt) => { const res = document.getElementById('qrResult'); res.style.display = 'block'; res.className = 'result-box success'; res.textContent = 'Hasil: ' + txt; stopQRScanner(); }, () => {}).catch(() => { document.getElementById('qrStartBtn').style.display = 'inline-flex'; document.getElementById('qrStopBtn').style.display = 'none'; }); } function stopQRScanner() { if (qrScanner) { qrScanner.stop().then(() => { qrScanner.clear(); qrScanner = null; }); } const startBtn = document.getElementById('qrStartBtn'); const stopBtn = document.getElementById('qrStopBtn'); if (startBtn) startBtn.style.display = 'inline-flex'; if (stopBtn) stopBtn.style.display = 'none'; } function scanQRFile(input) { const file = input.files[0]; if (!file) return; const html5QrCode = new Html5Qrcode("qrReader"); html5QrCode.scanFile(file, true).then(txt => { const res = document.getElementById('qrResult'); res.style.display = 'block'; res.className = 'result-box success'; res.textContent = 'Hasil: ' + txt; }).catch(() => { const res = document.getElementById('qrResult'); res.style.display = 'block'; res.className = 'result-box error'; res.textContent = 'QR Code tidak terdeteksi pada gambar.'; }); } function generateQR() { const content = document.getElementById('qrContent').value.trim(); const fg = document.getElementById('qrFg').value; const bg = document.getElementById('qrBg').value; const preview = document.getElementById('qrPreview'); if (!content) return; preview.style.display = 'flex'; preview.innerHTML = ''; const canvas = document.createElement('canvas'); QRCode.toCanvas(canvas, content, { width: 200, color: { dark: fg, light: bg } }, (err) => { if (err) { preview.innerHTML = 'Gagal membuat QR.'; return; } preview.appendChild(canvas); }); } function previewCompress(input) { compFile = input.files[0]; if (compFile) { const reader = new FileReader(); reader.onload = e => { const img = document.getElementById('compPreview'); img.src = e.target.result; img.style.display = 'block'; }; reader.readAsDataURL(compFile); } } function compressImage() { if (!compFile) return; const quality = parseInt(document.getElementById('imgQuality').value) / 100; const reader = new FileReader(); reader.onload = function(e) { const img = new Image(); img.onload = function() { const canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); canvas.toBlob(blob => { const res = document.getElementById('compResult'); res.style.display = 'block'; res.className = 'result-box success'; const pct = Math.round((1 - blob.size / compFile.size) * 100); res.innerHTML = `Ukuran awal: ${(compFile.size/1024).toFixed(1)} KB
Ukuran setelah: ${(blob.size/1024).toFixed(1)} KB
Penghematan: ${pct}%
Unduh hasil`; }, 'image/jpeg', quality); }; img.src = e.target.result; }; reader.readAsDataURL(compFile); } function previewConvert(input) { convFile = input.files[0]; if (convFile) { const reader = new FileReader(); reader.onload = e => { const img = document.getElementById('convPreview'); img.src = e.target.result; img.style.display = 'block'; }; reader.readAsDataURL(convFile); } } function convertImage() { if (!convFile) return; const format = document.getElementById('convFormat').value; const ext = format.split('/')[1]; const reader = new FileReader(); reader.onload = function(e) { const img = new Image(); img.onload = function() { const canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); canvas.toBlob(blob => { const res = document.getElementById('convResult'); res.style.display = 'block'; res.className = 'result-box success'; res.innerHTML = `Format: ${ext.toUpperCase()}
Ukuran: ${(blob.size/1024).toFixed(1)} KB
Unduh hasil`; }, format); }; img.src = e.target.result; }; reader.readAsDataURL(convFile); } function generatePassword() { const len = parseInt(document.getElementById('pwLength').value) || 20; const upper = document.getElementById('pwUpper').checked; const lower = document.getElementById('pwLower').checked; const num = document.getElementById('pwNum').checked; const sym = document.getElementById('pwSym').checked; let chars = ''; if (upper) chars += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; if (lower) chars += 'abcdefghijklmnopqrstuvwxyz'; if (num) chars += '0123456789'; if (sym) chars += '!@#$%^&*()_+-=[]{}|;:,.<>?'; if (!chars) { const res = document.getElementById('pwResult'); res.style.display = 'block'; res.className = 'result-box error'; res.textContent = 'Pilih minimal satu set karakter.'; return; } let pw = ''; const arr = new Uint32Array(len); crypto.getRandomValues(arr); for (let i = 0; i < len; i++) pw += chars[arr[i] % chars.length]; const res = document.getElementById('pwResult'); res.style.display = 'block'; res.className = 'result-box success'; res.textContent = pw; const strength = document.getElementById('pwStrength'); strength.style.display = 'flex'; let score = 0; if (len >= 12) score++; if (len >= 20) score++; if (upper && lower) score++; if (num) score++; if (sym) score++; const colors = ['#e74c3c', '#e67e22', '#f1c40f', '#2ecc71', '#2ecc71']; strength.innerHTML = Array.from({ length: 5 }, (_, i) => `
`).join(''); } function updateWordCount() { const textEl = document.getElementById('wcText'); if (!textEl) return; const text = textEl.value; const words = text.trim() ? text.trim().split(/\s+/).length : 0; const chars = text.length; const charsNoSpace = text.replace(/\s/g, '').length; const sentences = text.split(/[.!?]+/).filter(s => s.trim().length > 0).length; document.getElementById('wcWords').textContent = words; document.getElementById('wcChars').textContent = chars; document.getElementById('wcCharsNoSpace').textContent = charsNoSpace; document.getElementById('wcSentences').textContent = sentences; } async function runSpeedTest() { const btn = document.getElementById('speedBtn'); btn.disabled = true; btn.textContent = 'Menguji...'; const progress = document.getElementById('speedProgress'); progress.style.width = '10%'; const pingStart = performance.now(); try { await fetch('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css', { mode: 'no-cors', cache: 'no-store' }); } catch (e) {} const ping = Math.round(performance.now() - pingStart); document.getElementById('speedPing').textContent = ping; progress.style.width = '30%'; const dlStart = performance.now(); let dlSize = 0; try { const resp = await fetch('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/webfonts/fa-solid-900.woff2', { cache: 'no-store' }); const data = await resp.arrayBuffer(); dlSize = data.byteLength; } catch (e) {} const dlTime = (performance.now() - dlStart) / 1000; const dlMbps = dlTime > 0 ? ((dlSize * 8) / (dlTime * 1e6)).toFixed(2) : '0'; document.getElementById('speedDown').textContent = dlMbps; progress.style.width = '70%'; const ulStart = performance.now(); const testData = new Uint8Array(50000); try { await fetch('https://httpbin.org/post', { method: 'POST', body: testData, cache: 'no-store' }); } catch (e) {} const ulTime = (performance.now() - ulStart) / 1000; const ulMbps = ulTime > 0 ? ((50000 * 8) / (ulTime * 1e6)).toFixed(2) : '0'; document.getElementById('speedUp').textContent = ulMbps; progress.style.width = '100%'; document.getElementById('speedStats').style.display = 'flex'; btn.disabled = false; btn.textContent = 'Mulai Uji Kecepatan'; } function toggleSidebar() { document.getElementById('sidebar').classList.toggle('open'); document.querySelector('.overlay').classList.toggle('show'); } function closeSidebar() { document.getElementById('sidebar').classList.remove('open'); document.querySelector('.overlay').classList.remove('show'); } renderDashboard();