DCInside 자짤 차단기

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

Versión del día 08/07/2025. Echa un vistazo a la versión más reciente.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

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

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==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);
})();