const shortcut = document.getElementById('findMyShortcut'); let failIndex = 0; const iconItems = [ { id: 'findmydevice', img: '/custom/launcher/img/find-my.svg', label: '나의 찾기', onclick: () => { requireAccess(() => location.href = '/findmydevice'); } }, { id: 'wakeonlan', img: '/custom/launcher/img/wakeonlan-svgrepo-com.svg', label: 'PC 켜기', onclick: () => { fetch('/custom/wakeonlan/api.php?status=1') .then(res => res.ok ? res.json() : Promise.reject()) .then(data => { if (!data || data.result !== 'ok') { showAlert('error'); return; } if (data.state === 'on') { showAlert('wakeonlan_already'); return; } fetch('/custom/wakeonlan/api.php', { method: 'POST' }) .then(res => res.ok ? res.json() : Promise.reject()) .then(() => { showAlert('wakeonlan_request_sent'); let attempts = 0; const interval = setInterval(() => { attempts++; fetch('/custom/wakeonlan/api.php?status=1') .then(res => res.ok ? res.json() : Promise.reject()) .then(status => { if (status.state === 'on') { clearInterval(interval); showAlert('wakeonlan_success'); } else if (attempts >= 12) { clearInterval(interval); } }) .catch(() => clearInterval(interval)); }, 5000); }) .catch(() => showAlert('error')); }) .catch(() => showAlert('error')); } }, { id: 'poke', img: '/custom/launcher/img/R1280x0.jpg', label: '콕 찌르기', onclick: () => { showAlert('poke_completed'); const alertBox = document.querySelector('#poke_completed'); const content = alertBox.querySelector('.alert-content'); content.style.minHeight = 'auto'; content.style.padding = '15px 20px 10px 20px'; content.style.justifyContent = 'flex-start'; const renderMain = (countText = "조회 중...") => { content.innerHTML = `

${countText}

`; document.getElementById('btn_poke_cancel').onclick = () => { closeAlert('poke_completed'); }; document.getElementById('btn_poke_confirm').onclick = handlePoke; }; fetch('/custom/launcher/api.php?pokeCount=0') .then(res => res.json()) .then(data => { const n = Number(data.count) || 0; document.getElementById('poke_title').innerHTML = `현재까지 ${n}회 찔렸습니다!`; }) .catch(() => { document.getElementById('poke_title').innerText = "현재 횟수를 불러올 수 없음"; }); const handlePoke = () => { const sender = document.getElementById('poke_sender').value.trim() || "익명"; const message = document.getElementById('poke_message').value.trim() || ""; const titleField = document.getElementById('poke_title'); const statusField = document.getElementById('poke_status'); const confirmBtn = document.getElementById('btn_poke_confirm'); confirmBtn.disabled = true; statusField.innerText = "전송 중..."; const params = new URLSearchParams({ sender, message }); fetch(`https://ha.chaegeon.com/api/webhook/jczSPJyIX4iG4JTvy9HztFq91MsrIfsUErFh4DLstDcsm7RKL?${params.toString()}`, { method: 'POST', mode: 'no-cors' }); fetch(`/custom/launcher/api.php?pokeCount=1&sender=${encodeURIComponent(sender)}`) .then(res => res.json()) .then(data => { const n = Number(data.count); titleField.innerHTML = `현재까지 ${n}회 찔렸습니다!`; statusField.innerText = "성공!"; setTimeout(() => { confirmBtn.disabled = false; statusField.innerText = ""; }, 300); }) .catch(() => { statusField.innerText = "오류 발생"; confirmBtn.disabled = false; }); }; renderMain(); } }, { id: 'car', img: '/custom/launcher/img/car.png', label: '니모', onclick: () => { requireAccess(() => location.href = 'https://seo.chaegeon.com/car/monitor.php'); } } ]; function renderIcons() { shortcut.className = 'find-container'; shortcut.innerHTML = ''; iconItems.forEach(item => { const div = document.createElement('div'); div.className = 'iconContainer'; div.id = item.id; if (item.onclick) div.addEventListener('click', item.onclick); const img = document.createElement('img'); img.src = item.img; img.alt = item.label; const label = document.createElement('div'); label.className = 'iconLabel'; label.textContent = item.label; div.appendChild(img); div.appendChild(label); shortcut.appendChild(div); }); } function requireAccess(nextAction) { const access = getCookie('access'); if (access === '9KxH6236') { nextAction && nextAction(); } else { showPasswordForm(nextAction); } } function showPasswordForm(onSuccess) { shortcut.className = 'password-container'; shortcut.innerHTML = ''; const header = document.createElement('div'); header.id = 'settingsHeader'; header.style.display = 'flex'; header.style.alignItems = 'center'; header.style.justifyContent = 'center'; header.style.position = 'relative'; header.style.marginBottom = '15px'; header.style.padding = '12px'; header.style.fontSize = '16px'; header.style.color = '#000'; header.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif'; const backLink = document.createElement('a'); backLink.id = 'blogBackLink'; backLink.innerHTML = ' 목록'; backLink.style.position = 'absolute'; backLink.style.left = '0px'; backLink.style.fontSize = '16px'; backLink.style.top = '3px'; backLink.style.color = '#007AFF'; backLink.style.textDecoration = 'none'; backLink.style.fontWeight = 'normal'; backLink.style.cursor = 'pointer'; backLink.addEventListener('click', () => renderIcons()); backLink.querySelector('.backArrow').style.cssText = ` font-size: 26px; position: relative; top: 1px; margin-right: 1px; `; const title = document.createElement('span'); title.className = 'headerTitle'; title.textContent = '비밀번호'; title.style.fontWeight = 'bold'; header.appendChild(backLink); header.appendChild(title); shortcut.appendChild(header); const input = document.createElement('input'); input.type = 'password'; input.placeholder = '비밀번호'; input.id = 'blog_secret'; input.inputMode = 'numeric'; input.pattern = '[0-9]*'; const button = document.createElement('button'); button.id = 'blog_secret_check'; button.textContent = '확인'; const msg = document.createElement('div'); msg.id = 'failMsg'; const inputRow = document.createElement('div'); inputRow.style.display = 'flex'; inputRow.style.alignItems = 'center'; inputRow.appendChild(input); inputRow.appendChild(button); const column = document.createElement('div'); column.style.display = 'flex'; column.style.flexDirection = 'column'; column.style.alignItems = 'center'; column.appendChild(inputRow); shortcut.appendChild(column); const submit = async () => { const password = input.value; try { const messageRes = await fetch('/custom/launcher/api.php?failMessages=1'); const messagesJson = await messageRes.json(); const failMessages = messagesJson.failMessages || []; const res = await fetch('/custom/launcher/api.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams({ password }) }); const data = await res.json(); if (data.result === 'ok') { document.cookie = 'access=9KxH6236; path=/; max-age=21600; SameSite=Strict' + (location.protocol === 'https:' ? '; Secure' : ''); if (typeof onSuccess === 'function') { onSuccess(); } else { location.reload(); } } else { column.appendChild(msg); msg.textContent = failMessages[failIndex] || '비밀번호가 틀렸습니다.'; failIndex = (failIndex + 1) % Math.max(1, failMessages.length); input.value = ''; input.focus(); } } catch (_) { } }; button.addEventListener('click', submit); input.addEventListener('keydown', (e) => { if (e.key === 'Enter') submit(); }); } function getCookie(name) { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop().split(';').shift(); return null; } document.addEventListener('DOMContentLoaded', async () => { renderIcons(); const findShortcut = document.getElementById('findMyShortcut'); if (findShortcut) { findShortcut.style.userSelect = 'none'; findShortcut.style.webkitUserSelect = 'none'; findShortcut.style.msUserSelect = 'none'; findShortcut.style.MozUserSelect = 'none'; findShortcut.style.webkitTouchCallout = 'none'; findShortcut.addEventListener('dragstart', e => e.preventDefault()); } }); if (location.pathname.split('/').filter(Boolean).length === 1) document.title = "블로그 - 채건닷컴";