DCInside 자짤 차단기

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

Versione datata 08/07/2025. Vedi la nuova versione l'ultima versione.

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

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

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

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