// ==UserScript==
// @name 닉네임 차단 관리 패널 포함
// @namespace http://tampermonkey.net/
// @version 1.3
// @description 차단/해제 및 관리 패널 기능 추가
// @author 주인님
// @include https://www.dogdrip.net/*
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==
(function () {
'use strict';
let lastClickedMemberClass = null;
// ---------------------
// 닉네임 클릭 감지
// ---------------------
document.addEventListener('click', function (event) {
const target = event.target;
const memberClass = [...target.classList].find(cls => cls.startsWith('member_'));
if (memberClass) {
lastClickedMemberClass = memberClass;
}
});
// ---------------------
// 팝업 감지 및 차단 버튼 삽입
// ---------------------
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
if (!(node instanceof HTMLElement)) continue;
const popupArea = document.querySelector('#popup_menu_area');
if (!popupArea || !lastClickedMemberClass) return;
if (popupArea.querySelector('.ban-button')) return;
const banned = GM_getValue('bannedMembers', []);
const memos = GM_getValue('bannedMemos', {});
const isBanned = banned.includes(lastClickedMemberClass);
const btn = document.createElement('button');
btn.className = 'ban-button';
btn.innerText = isBanned ? '차단 해제' : '차단 추가';
btn.style.marginTop = '10px';
btn.style.display = 'block';
btn.style.background = isBanned ? '#555' : '#d00';
btn.style.color = 'white';
btn.style.border = 'none';
btn.style.padding = '5px';
btn.style.width = '100%';
btn.style.boxSizing = 'border-box';
btn.addEventListener('click', function () {
let list = GM_getValue('bannedMembers', []);
if (isBanned) {
list = list.filter(cls => cls !== lastClickedMemberClass);
alert(`"${lastClickedMemberClass}" 해제됨`);
} else {
list.push(lastClickedMemberClass);
alert(`"${lastClickedMemberClass}" 차단됨`);
}
GM_setValue('bannedMembers', list);
recolorAll();
updateAdminPanel();
});
popupArea.appendChild(btn);
// 🔽 메모가 있을 경우 표시
const memo = memos[lastClickedMemberClass];
if (memo && memo.trim() !== '') {
const memoDiv = document.createElement('div');
memoDiv.innerText = `📝 ${memo}`;
memoDiv.style.marginTop = '6px';
memoDiv.style.fontSize = '12px';
memoDiv.style.color = '#333';
memoDiv.style.whiteSpace = 'pre-wrap';
memoDiv.style.wordBreak = 'break-word';
memoDiv.style.maxWidth = '200px'; // 혹시 popup 영역이 좁으면 제한
popupArea.appendChild(memoDiv);
}
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
// ---------------------
// 닉네임 색상 적용
// ---------------------
function recolorAll() {
const all = document.querySelectorAll('[class*="member_"]');
const banned = GM_getValue('bannedMembers', []);
all.forEach(el => {
const cls = [...el.classList].find(c => c.startsWith('member_'));
if (!cls) return;
if (banned.includes(cls)) {
el.style.setProperty('color', 'red', 'important');
} else {
el.style.removeProperty('color'); // 원래대로 복원
}
});
}
window.addEventListener('load', recolorAll);
// ---------------------
// 관리 패널 UI
// ---------------------
const adminBtn = document.createElement('button');
adminBtn.innerText = '차단목록 관리';
adminBtn.style.position = 'fixed';
adminBtn.style.top = '10px';
adminBtn.style.right = '10px';
adminBtn.style.zIndex = '9999';
adminBtn.style.background = '#333';
adminBtn.style.color = '#fff';
adminBtn.style.border = 'none';
adminBtn.style.padding = '5px 10px';
adminBtn.style.cursor = 'pointer';
document.body.appendChild(adminBtn);
const panel = document.createElement('div');
panel.style.position = 'fixed';
panel.style.top = '40px';
panel.style.right = '10px';
panel.style.zIndex = '9999';
panel.style.background = 'white';
panel.style.border = '1px solid #aaa';
panel.style.padding = '10px';
panel.style.display = 'none';
panel.style.minWidth = '200px';
panel.style.maxHeight = '300px';
panel.style.overflowY = 'auto';
panel.style.boxShadow = '0 0 10px rgba(0,0,0,0.2)';
document.body.appendChild(panel);
adminBtn.addEventListener('click', () => {
panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
updateAdminPanel();
});
// 닉네임 DOM이 동적으로 추가될 때도 감지해서 색상 재적용
const nicknameObserver = new MutationObserver(() => {
recolorAll();
});
nicknameObserver.observe(document.body, {
childList: true,
subtree: true
});
function updateAdminPanel() {
const banned = GM_getValue('bannedMembers', []);
const memoData = GM_getValue('bannedMemos', {});
panel.innerHTML = `<strong>차단된 유저:</strong><br/><br/>`;
if (banned.length === 0) {
panel.innerHTML += '<i>없음</i>';
return;
}
banned.forEach(cls => {
const entry = document.createElement('div');
entry.style.marginBottom = '8px';
const nameSpan = document.createElement('span');
nameSpan.innerText = `${cls}`;
nameSpan.style.marginRight = '8px';
const memoSpan = document.createElement('span');
memoSpan.innerText = memoData[cls] ? `📝 ${memoData[cls]}` : '';
memoSpan.style.marginRight = '8px';
// [메모] 버튼
const memoBtn = document.createElement('button');
memoBtn.innerText = '메모';
memoBtn.style.marginRight = '5px';
memoBtn.style.background = '#4c8';
memoBtn.style.color = 'white';
memoBtn.style.border = 'none';
memoBtn.style.padding = '2px 6px';
memoBtn.style.cursor = 'pointer';
memoBtn.addEventListener('click', () => {
const memo = prompt(`"${cls}"에 대한 메모 입력`, memoData[cls] || '');
if (memo !== null) {
if (memo.trim() === '') {
delete memoData[cls];
} else {
memoData[cls] = memo.trim();
}
GM_setValue('bannedMemos', memoData);
updateAdminPanel();
}
});
// [메모삭제] 버튼
const memoDeleteBtn = document.createElement('button');
memoDeleteBtn.innerText = '메모삭제';
memoDeleteBtn.style.marginRight = '5px';
memoDeleteBtn.style.background = '#cc4444';
memoDeleteBtn.style.color = 'white';
memoDeleteBtn.style.border = 'none';
memoDeleteBtn.style.padding = '2px 6px';
memoDeleteBtn.style.cursor = 'pointer';
memoDeleteBtn.addEventListener('click', () => {
if (memoData[cls]) {
delete memoData[cls];
GM_setValue('bannedMemos', memoData);
updateAdminPanel();
}
});
// [해제] 버튼
const unbanBtn = document.createElement('button');
unbanBtn.innerText = '해제';
unbanBtn.style.background = '#777';
unbanBtn.style.color = 'white';
unbanBtn.style.border = 'none';
unbanBtn.style.cursor = 'pointer';
unbanBtn.style.padding = '2px 6px';
unbanBtn.addEventListener('click', () => {
const newList = banned.filter(item => item !== cls);
delete memoData[cls];
GM_setValue('bannedMembers', newList);
GM_setValue('bannedMemos', memoData);
recolorAll();
updateAdminPanel();
});
entry.appendChild(nameSpan);
entry.appendChild(memoSpan);
entry.appendChild(memoBtn);
if (memoData[cls]) {
entry.appendChild(memoDeleteBtn);
}
entry.appendChild(unbanBtn);
panel.appendChild(entry);
});
}
})();
개드립에서 특정유저를 메모하고 블랙리스트로 등록하기 위한 템퍼몽키 스크립트입니다.
사용시 크롬 확장프로그램에서 템퍼몽키를 설치하고 해당 스크립트를 복붙해주시면 됩니다.
적용시 개드립 우측 상단에 차단목록 관리패널이 나타나게 됩니다. 해당 패널을 클릭하면
차단한 유저를 해제하거나 메모를 할 수 있습니다.
차단은 유저의 닉네임을 누르게되면 차단추가 탭이 생기게 됩니다.
메모는 원하는대로 입력하시면 됩니다.
다만 저장할때 닉네임이 저장되지는 않고 회원번호만 저장되기 때문에 직접
닉네임 + 메모로 저장해주셔도 되고 마음대로 하면 됩니다.
(예시입니다.)
해당 목록에 들어간 유저는 개드립의 모든 페이지에서 빨간색 닉네임으로 표시되게 됩니다.
#개드립 차단 #개드립 메모
'Development' 카테고리의 다른 글
[템퍼몽키] 개드립 댓글 클리너 v02 (0) | 2025.06.29 |
---|---|
개드립 댓글 클리너 (0) | 2024.12.29 |