사용법 설명

1. gallid, gallno, targetips 등등 전부 알맞게 채운다. (절대 '' 따움표 지우지 말 것.)

2. 코드 전부 복사 (IP, 고닉 2개 따로 있으니 알맞게 복사)

3. 댓글을 삭제할 게시물로 이동.

4. 키보드 F12를 눌러 개발자 도구를 열고 console 탭으로 이동.

5. 복사한 코드 붙여넣기 후 엔터 눌러서 실행.


※유동으로는 이 방법 못 씀. (반)고닉 으로만 사용 가능.

※안 되면 GPT한테 물어보셈

※사용할 때 VPN 같은거 써서 하셈. 원래 IP 차단 가능성 있음 ㅇㅇ


2024 6 15 22:10 기준 수정

ID, IP 통합되게 수정.

IP만 지울거면 ID는 [] 만들어서 걍 아무것도 없이 만드셈 ID만 지울거면 반대로.

그리고 실패라고 뜨는데 새로고침하면 전부 삭제되어 있음.

예시:

// 3. 삭제할 사용자 ID 목록 (고정닉 대상)
const targetUserIDs = [];
// 4. 삭제할 IP 목록 (유동닉 대상)
const targetIPs = ['삭제할_IP_1', '삭제할_IP_2'];







// ======================================================================
// ❗ 사용 전 이 부분을 본인 정보에 맞게 수정하세요 ❗
// (비워둘 목록은 [] 이렇게 대괄호만 남겨두세요)
// ======================================================================
// 1. 갤러리 ID (주소창에서 id= 뒤의 값)
const gallId = '여기에_갤러리_ID를_입력하세요';
// 2. 게시물 번호 (주소창에서 no= 뒤의 값)
const gallNo = '여기에_게시물_번호를_입력하세요';
// 3. 삭제할 사용자 ID 목록 (고정닉 대상)
const targetUserIDs = ['삭제할_ID_1', '삭제할_ID_2'];
// 4. 삭제할 IP 목록 (유동닉 대상)
const targetIPs = ['삭제할_IP_1', '삭제할_IP_2'];
// ======================================================================
// ++++++++++ 아래 코드는 수정할 필요가 없습니다 ++++++++++
// ======================================================================

/**
 * 쿠키 값을 가져오는 함수
 * @param {string} name - 가져올 쿠키의 이름
 * @returns {string|null} - 쿠키 값 또는 null
 */
function getCookie(name) {
    const value = `; ${document.cookie}`;
    const parts = value.split(`; ${name}=`);
    if (parts.length === 2) return parts.pop().split(';').shift();
    return null;
}

// 스크립트 실행 시작
(function() {
    const ciToken = getCookie('ci_c');
    const gallType = typeof GALLERY_TYPE !== 'undefined' ? GALLERY_TYPE : 'G';

    if (!ciToken) {
        alert('❌ [실패] 로그인 정보가 없습니다.\n디시인사이드에 로그인했는지 확인해주세요.');
        return;
    }

    if (!gallId || gallId.includes('여기에') || !gallNo || gallNo.includes('여기에')) {
        alert('❌ [실패] 갤러리 ID 또는 게시물 번호가 입력되지 않았습니다.\n코드 상단의 정보를 올바르게 수정해주세요.');
        return;
    }

    console.clear();
    console.log("✅ 스크립트 실행을 시작합니다 (통합 삭제 모드)");
    console.log(`- 대상 갤러리: ${gallId} | 대상 게시물: ${gallNo}`);
    if (targetUserIDs.length > 0) console.log(`- 삭제 대상 ID: ${targetUserIDs.join(', ')}`);
    if (targetIPs.length > 0) console.log(`- 삭제 대상 IP: ${targetIPs.join(', ')}`);

    // [수정됨] .reply_info 클래스까지 포함하여 모든 종류의 댓글/답글 요소를 찾습니다.
    const allComments = document.querySelectorAll('.cmt_info, .re_cmt_info, .reply_info');

    // 삭제 대상 필터링
    const commentsToDelete = [...allComments].filter(commentElement => {
        // 고정닉 ID 확인
        const idElement = commentElement.querySelector('span.refresherUserData');
        const userId = idElement?.title || null;
        if (userId && targetUserIDs.length > 0 && targetUserIDs.includes(userId)) {
            return true;
        }

        // 유동닉 IP 확인
        const ipElement = commentElement.querySelector('.ip');
        const ipText = ipElement?.innerText || "";
        if (ipText && targetIPs.length > 0 && targetIPs.some(targetIp => ipText.includes(targetIp))) {
            return true;
        }

        return false;
    });

    if (commentsToDelete.length === 0) {
        console.log("✅ 작업 완료: 삭제할 대상 댓글/답글을 찾지 못했습니다.");
        alert("✅ 삭제할 댓글이나 답글이 없습니다.");
        return;
    }

    console.log(`+ 총 ${commentsToDelete.length}개의 삭제 대상 댓글/답글을 발견했습니다.`);
    console.log("--- 삭제 작업을 시작합니다 ---");

    let successCount = 0;
    let failureCount = 0;
    const totalCount = commentsToDelete.length;

    const processDeletion = async () => {
        for (const element of commentsToDelete) {
            const commentNo = element.dataset.no;
            
            if (!commentNo) {
                console.error(`❌ [오류] 고유 번호(data-no)가 없는 댓글 요소가 있어 건너뜁니다.`, element);
                failureCount++;
                continue;
            }
            
            // [수정됨]
            const isReply = element.classList.contains('re_cmt_info') || element.classList.contains('reply_info');
            const commentType = isReply ? '답글' : '댓글';
            const nickname = element.querySelector('.nickname')?.innerText || '이름없음';
            const logIdentifier = `${nickname}의 ${commentType} (#${commentNo})`;

            const formData = new URLSearchParams({
                ci_t: ciToken,
                _GALLTYPE_: gallType,
                mode: 'del',
                id: gallId,
                no: gallNo,
                re_no: commentNo
            });

            try {
                const response = await fetch('https://gall.dcinside.com/board/comment/comment_delete_submit', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
                        'X-Requested-With': 'XMLHttpRequest'
                    },
                    body: formData
                });
                const resultText = await response.text();
                
                if (resultText.toLowerCase().includes('success')) {
                    console.log(`✅ [성공] ${logIdentifier} 삭제 완료.`);
                    successCount++;
                } else {
                    console.error(`❌ [실패] ${logIdentifier} 삭제 실패. (사유: 권한 없음 또는 이미 삭제됨)`);
                    failureCount++;
                }
            } catch (error) {
                console.error(`❌ [네트워크 오류] ${logIdentifier} 처리 중 오류 발생.`, error);
                failureCount++;
            }
        }

        console.log("--- 모든 작업이 완료되었습니다 ---");
        console.log(`- 성공: ${successCount}건, 실패: ${failureCount}건`);
        alert(`✅ 삭제 시도 완료 (성공: ${successCount}, 실패: ${failureCount})\n\nF5(새로고침)를 눌러 결과를 확인하세요.`);
    };

    processDeletion();
})();