Direct Image Link E621/926

Рипалка ссылок / имён / номеров картинок

// ==UserScript==
// @name           Direct Image Link E621/926
// @version        2025.07.03.1
// @description    Рипалка ссылок / имён / номеров картинок
// @match          http*://e621.net/posts*
// @match          http*://e621.net/pool*
// @match          http*://e621.net/favorites*
// @match          http*://e926.net/posts*
// @match          http*://e926.net/pool*
// @match          http*://e926.net/favorites*
// @author         Rainbow-Spike
// @namespace      https://greasyfork.org/users/7568
// @homepage       https://greasyfork.org/ru/users/7568-rainbow-spike
// @icon           https://www.google.com/s2/favicons?domain=e621.net
// @grant          none
// @run-at         document-end
// ==/UserScript==

// Получаем список элементов
const postList = document.querySelectorAll('.thumbnail');

if (postList.length > 0) {
    // Конфигурация параметров
    const config = {
        mode: 2, // 0 - номера постов, 1 - имена файлов, 2 - полные ссылки
        filters: {
            useNegativeList: true,
            usePositiveList: true,
            filterDownloaded: true,
            showTopList: true,
            showUnderImage: true
        },
        tags: {
            negative: /\Wcensored|gore|male\/male/,
            positive: /\Wvulva\W?|female_on_top|tribadism|camel_toe|vaginal_mastu/
        },
        styles: {
            negative: 'opacity: 0.5; border: 3px dotted red;',
            neutral: 'opacity: 0.5; border: 3px dashed gray;',
            downloaded: 'opacity: 0.5; border: 16px double green;',
            topList: 'columns: 300px; font-size: 40%; line-height: .25em; max-height: 100px;',
            underImage: 'word-wrap: anywhere;'
        },
        downloadedMD5: [ // список MD5-кодов уже закачанных файлов, ВСТАВЬ СВОЙ СПИСОК
'00000000000000000000000000000000', '00000000000000000000000000000000'
        ],
        domNodes: {
            topContainer: document.body,
            newContainer: document.createElement('div')
        }
    };

    // Основная функция обработки
    function processPost(postElement) {
        const { filters, tags, styles, downloadedMD5 } = config;
        
        // Извлечение данных
        const postTags = postElement.getAttribute('data-tags');
        const src = postElement.getAttribute('data-file-url');
        const name = src.split('/').pop();
        const [md5, ext] = name.split('.');
        const num = postElement.getAttribute('data-id');
        
        // Фильтрация
        let isValid = true;
        
        if (filters.useNegativeList && tags.negative.test(postTags)) {
            postElement.style = styles.negative;
            isValid = false;
        }
        
        if (isValid && filters.usePositiveList && !tags.positive.test(postTags)) {
            postElement.style = styles.neutral;
            isValid = false;
        }
        
        if (isValid && filters.filterDownloaded && downloadedMD5.includes(md5)) {
            postElement.style = styles.downloaded;
            isValid = false;
        }
        
        // Формирование вывода
        if (isValid) {
            const insertTopContent = getInsertTopContent(md5, num, src, ext);
						const insertUnderContent = getInsertUnderContent(md5, num);
            
            if (filters.showTopList) {
                config.domNodes.newContainer.innerHTML += `<a href="${src}">${insertTopContent}</a><br>`;
            }
            
            if (filters.showUnderImage) {
                postElement.innerHTML += `<a href="${src}" style="${styles.underImage}">${insertUnderContent}</a>`;
            }
        }
    }

    // Получение содержимого для вставки
    function getInsertTopContent(md5, num, src, ext) {
        switch (config.mode) {
            case 0:
                return `${num}.${ext}`;
            case 1:
                return `${md5}.${ext}`;
            case 2:
                return src;
            default:
                return '';
        }
    }
    function getInsertUnderContent(md5, num) {
        switch (config.mode) {
            case 0:
                return num;
            case 1:
                return md5;
            case 2:
                return md5;
            default:
                return '';
        }
    }

    // Обработка всех постов
    postList.forEach(processPost);

    // Функция выделения блока
    function selectBlock(node) {
        try {
            const range = document.createRange();
            range.selectNode(node);
            const selection = window.getSelection();
            selection.removeAllRanges();
            selection.addRange(range);
        } catch (error) {
            console.error('Ошибка при выделении элемента:', error);
        }
    }

    // Добавление верхнего списка
    if (config.filters.showTopList) {
        config.domNodes.newContainer.style = config.styles.topList;
        config.domNodes.topContainer.insertBefore(
            config.domNodes.newContainer,
            config.domNodes.topContainer.firstChild
        );
        selectBlock(config.domNodes.newContainer);
    }
}