|
2025-11-07 20:31
조회: 3,358
추천: 1
카드뒤집기 존나 귀찮아서만듬크롬브라우저에서 쓰셈
Violentmonkey 라는 확장 프로그램 필요함 귀찮으니 자세한 사용방법은 생략한다 사용책임은 각자한테 있음 ![]() 이하 소스코드 // ==UserScript== // @name LA Card Hook - write img filename into clicked button // @namespace daeyeol.lostark.cardhook // @version 1.0.0 // @description Intercept GetCard251105 response and put filename into the clicked button // @match https://lostark.game.onstove.com/* // @run-at document-start // @grant none // ==/UserScript== (function () { 'use strict'; // 🔎 타겟 API 엔드포인트 (부분일치) const TARGET_PATH = '/Promotion/Card/GetCard251105'; // 마지막 클릭된 버튼(또는 버튼 역할 요소) 추적 let lastClickedBtn = null; // 버튼 판별 보조 function asButton(el) { if (!el) return null; // 실제 <button> 또는 role=button, 클릭 가능한 <a>, data-속성 등 가볍게 커버 return el.closest('button, [role="button"], a[role="button"], a.button, .btn, [data-button], [data-btn]') || el.closest('a, button'); } // 캡처 단계에서 pointerdown / mousedown으로 "어떤 버튼"이 눌렸는지 먼저 기록 function clickCapture(e) { const btn = asButton(e.target); if (btn) lastClickedBtn = btn; } window.addEventListener('pointerdown', clickCapture, true); window.addEventListener('mousedown', clickCapture, true); // 파일명 추출 (확장자 제외) function extractBaseNameFromImg(imgPath) { if (!imgPath) return null; // 예: "/2025/event/.../card21.webp" -> "card21" const m = String(imgPath).match(/([^/]+).[a-z0-9]+$/i); return m ? m[1] : null; } // 버튼 내부에 파일명 쓰기 (원래 텍스트 보존/병기 옵션) function writeIntoButton(btn, filename) { if (!btn || !filename) return; // 원래 텍스트를 덮어쓰기보다는, 안전하게 넣는 쪽으로. 필요시 아래 한 줄로 교체. // btn.textContent = filename; // 깔끔한 배지로 표시 const tag = document.createElement('span'); tag.textContent = filename; tag.style.marginLeft = '6px'; tag.style.padding = '2px 6px'; tag.style.borderRadius = '999px'; tag.style.fontSize = '20px'; tag.style.lineHeight = '1'; tag.style.border = '1px solid #fff'; tag.style.opacity = '0.9'; tag.style.color = '#fff' tag.style.background = '#111' // 중복 삽입 방지용 클래스 tag.className = 'la-cardhook-filename'; // 기존 표시 제거 후 다시 삽입 btn.querySelectorAll('.la-cardhook-filename').forEach(n => n.remove()); btn.appendChild(tag); } // ------- fetch 후킹 ------- const origFetch = window.fetch; window.fetch = async function (input, init) { const url = typeof input === 'string' ? input : (input && input.url) || ''; const res = await origFetch.call(this, input, init); try { if (url.includes(TARGET_PATH)) { // 응답 복제 후 JSON 파싱 const clone = res.clone(); clone.json().then(data => { // { img: "/2025/.../card21.webp" } 구조 가정 const filename = extractBaseNameFromImg(data && data.img); if (!filename) return; // 클릭했던 버튼이 아직 DOM에 살아있을 때만 기록 const btnRef = lastClickedBtn && document.contains(lastClickedBtn) ? lastClickedBtn : null; if (btnRef) writeIntoButton(btnRef, filename); }).catch(() => {}); } } catch (e) { // no-op } return res; }; // ------- XHR 후킹 (사이트가 XHR을 쓸 경우 대비) ------- const origOpen = XMLHttpRequest.prototype.open; const origSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.open = function (method, url, ...rest) { this.__isTarget = typeof url === 'string' && url.includes(TARGET_PATH); return origOpen.call(this, method, url, ...rest); }; XMLHttpRequest.prototype.send = function (...args) { if (this.__isTarget) { this.addEventListener('load', () => { try { const data = JSON.parse(this.responseText); const filename = extractBaseNameFromImg(data && data.img); if (!filename) return; const btnRef = lastClickedBtn && document.contains(lastClickedBtn) ? lastClickedBtn : null; if (btnRef) writeIntoButton(btnRef, filename); } catch (e) { /* ignore */ } }); } return origSend.apply(this, args); }; })();
|
로스트아크 인벤 자유 게시판 게시판
인벤 전광판
[규듀기] 여름 신캐는 남자 창술사
[규듀기] 여름 신캐는 남자 창술사
[전국절제협회] 절제의 왕, 사멸이 하늘에 서겠다.
[규듀기] 여름 신캐는 남자 창술사
[규듀기] 여름 신캐는 남자 창술사
[규듀기] 여름 신캐는 남자 창술사
로아 인벤 전광판 시작!!
[규듀기] 여름 신캐는 남자 창술사
[규듀기] 여름 신캐는 남자 창술사
[규듀기] 여름 신캐는 남자 창술사
[규듀기] 여름 신캐는 남자 창술사
[규듀기] 여름 신캐는 남자 창술사
[규듀기] 여름 신캐는 남자 창술사
[두번째동료] 타대의 왕, 두동이 하늘에 서겠다.






