DCInside 자짤 차단기

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

От 08.07.2025. Виж последната версия.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

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

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

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