DCInside 자짤 차단기

빠른 실행 + 차단 목록 기반 CSS + 편집 UI 포함

08.07.2025 itibariyledir. En son verisyonu görün.

Bu betiği kurabilmeniz için Tampermonkey, Greasemonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

You will need to install an extension such as Tampermonkey to install this script.

Bu betiği kurabilmeniz için Tampermonkey ya da Violentmonkey gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

Bu betiği kurabilmeniz için Tampermonkey ya da Userscripts gibi bir kullanıcı betiği eklentisini kurmanız gerekmektedir.

You will need to install an extension such as Tampermonkey to install this script.

Bu komut dosyasını yüklemek için bir kullanıcı komut dosyası yöneticisi uzantısı yüklemeniz gerekecek.

(Zaten bir kullanıcı komut dosyası yöneticim var, kurmama izin verin!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Zateb bir user-style yöneticim var, yükleyeyim!)

// ==UserScript==
// @name         DCInside 자짤 차단기
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  빠른 실행 + 차단 목록 기반 CSS + 편집 UI 포함
// @match        *://*.dcinside.com/*
// @grant        GM_registerMenuCommand
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_addStyle
// @license MIT
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    const STORAGE_KEY = 'dc_blocked_urls';

    // 현재 차단 목록 가져오기
    function getBlockedList() {
        return JSON.parse(GM_getValue(STORAGE_KEY, '[]'));
    }

    // 차단 목록 저장
    function saveBlockedList(list) {
        GM_setValue(STORAGE_KEY, JSON.stringify(list));
    }

    // CSS로 직접 차단
    function applyCSSBlocking() {
        const list = getBlockedList();
        if (list.length === 0) return;

        const style = document.createElement('style');
        style.id = 'dc-block-style';
        style.textContent = list.map(part => `
            img[src*="${part}"],
            video[data-src*="${part}"],
            video[src*="${part}"]
            { display: none !important; }
        `).join('\n');
        document.documentElement.appendChild(style);
    }

    // DOM 요소 숨기기 (Fallback)
    function hideBlockedElements() {
        const blocked = getBlockedList();
        document.querySelectorAll('img, video').forEach(el => {
            const src = el.src || el.getAttribute('data-src') || '';
            if (blocked.some(part => src.includes(part))) {
                el.style.display = 'none';
            }
        });
    }

    // 팝업 기반 편집 UI
    function openBlockEditorPopup() {
        const old = document.getElementById('blockEditorPopup');
        if (old) old.remove();

        const wrapper = document.createElement('div');
        wrapper.id = 'blockEditorPopup';
        wrapper.innerHTML = `
            <div class="popup-box">
                <h3>차단된 URL 목록 편집</h3>
                <textarea id="blockEditorTextarea">${getBlockedList().join('\n')}</textarea>
                <div class="popup-actions">
                    <button id="saveBlockedUrls">저장</button>
                    <button id="cancelBlockedUrls">취소</button>
                </div>
            </div>
        `;
        document.body.appendChild(wrapper);

        GM_addStyle(`
    #blockEditorPopup {
        position: fixed;
        top: 50%; left: 50%;
        transform: translate(-50%, -50%);
        background: #2a2a2a;  /* 다크모드 대비용 진회색 */
        color: #f0f0f0;       /* 밝은 텍스트 */
        border: 2px solid #555;
        padding: 16px;
        z-index: 99999;
        width: 400px;
        box-shadow: 0 0 10px rgba(0,0,0,0.5);
        font-family: sans-serif;
        border-radius: 6px;
    }
    #blockEditorPopup h3 {
        margin-top: 0;
        font-size: 1.1em;
    }
    #blockEditorPopup textarea {
        width: 100%;
        height: 200px;
        margin-top: 8px;
        resize: vertical;
        font-family: monospace;
        background: #1e1e1e;
        color: #f0f0f0;
        border: 1px solid #777;
        padding: 8px;
    }
    #blockEditorPopup .popup-actions {
        margin-top: 10px;
        text-align: right;
    }
    #blockEditorPopup button {
        margin-left: 8px;
        padding: 6px 12px;
        background: #444;
        color: #f0f0f0;
        border: 1px solid #888;
        border-radius: 4px;
        cursor: pointer;
    }
    #blockEditorPopup button:hover {
        background: #666;
        border-color: #aaa;
    }
`);


        document.getElementById('saveBlockedUrls').onclick = () => {
            const value = document.getElementById('blockEditorTextarea').value;
            const list = value.split('\n').map(s => s.trim()).filter(s => s.length > 0);
            saveBlockedList(list);
            document.getElementById('dc-block-style')?.remove();
            applyCSSBlocking();
            hideBlockedElements();
            alert('저장되었습니다!');
            wrapper.remove();
        };

        document.getElementById('cancelBlockedUrls').onclick = () => {
            wrapper.remove();
        };
    }

    // 메뉴 등록
    GM_registerMenuCommand('차단 목록 보기/편집 (팝업)', openBlockEditorPopup);
    GM_registerMenuCommand('마지막 우클릭한 URL 차단하기', function () {
        const url = GM_getValue('__temp_block_candidate', '');
        if (!url) {
            alert('이미지나 영상을 먼저 우클릭하세요.');
            return;
        }

        const short = prompt('차단할 URL 일부를 입력하세요 (기본값: 전체 URL)', url);
        if (short !== null) {
            const list = getBlockedList();
            const trimmed = short.trim();
            if (!list.includes(trimmed)) {
                list.push(trimmed);
                saveBlockedList(list);
                document.getElementById('dc-block-style')?.remove();
                applyCSSBlocking();
                hideBlockedElements();
                alert('차단되었습니다: ' + trimmed);
            }
        }
    });

    // 우클릭한 URL 저장
    document.addEventListener('contextmenu', function (e) {
        const target = e.target;
        let url = '';
        if (target.tagName === 'IMG') {
            url = target.src;
        } else if (target.tagName === 'VIDEO') {
            url = target.getAttribute('data-src') || target.src;
        }

        if (url) {
            GM_setValue('__temp_block_candidate', url);
        }
    });

    // 초기 실행
    applyCSSBlocking();

    // 동적 이미지 대응
    const observer = new MutationObserver(() => hideBlockedElements());
    observer.observe(document.documentElement, { childList: true, subtree: true });

    // 로딩 후 한번 더 (혹시 누락된 경우)
    window.addEventListener('load', hideBlockedElements);
})();