跳转到内容

User:Kurgenera/killRSP.js

维基百科,自由的百科全书
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
//这玩意误杀率至少有15%,但编者有复核的机会。误杀结果与脚本制作者无关,仅与执行者相关。
//已知bug:[[Special:Diff/91937521]]
$(function() {
    'use strict';

    // ================= 配置区 =================
    const PORTAL_DOMAINS = ['sina', 'sohu', '163', 'ifeng', 'qq', 'weibo', 'baidu','huxiu', 'msn', 'armyrecognition'];
    const SOCIAL_DOMAINS = ['youtube', 'facebook', 'x.com', 'twitter', 'instagram'];
    const KEYWORDS = ['新浪', '搜狐', '网易', '凤凰', '腾讯'];
    const EXEMPT_DOMAINS = ['\\.gov\\.cn', '\\.edu\\.cn', 'rfa\\.org']; 
    // ==========================================

    var modalCSS = 
        '#maint-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.7); z-index: 99999; }' +
        '#maint-modal { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: #fff; padding: 25px; border: 1px solid #ccc; border-radius: 5px; z-index: 100000; width: 650px; max-width: 95%; box-shadow: 0 0 20px rgba(0,0,0,0.5); font-family: sans-serif; }' +
        '#maint-modal h2 { margin-top: 0; border-bottom: 2px solid #d33; padding-bottom: 10px; color: #d33; font-size: 1.1em; }' +
        '#maint-modal .source-scroll { max-height: 450px; overflow-y: auto; margin: 15px 0; border: 1px solid #eee; padding: 10px; background: #f9f9f9; }' +
        '#maint-modal .source-item { display: block; margin-bottom: 15px; border-bottom: 2px solid #eee; padding-bottom: 10px; }' +
        '#maint-modal .source-content { font-size: 12px; color: #444; background: #fff; border-left: 3px solid #d33; padding: 5px 8px; margin: 5px 0; word-break: break-all; }' +
        '#maint-modal .badge-danger { background: #f8d7da; color: #721c24; font-size: 10px; padding: 2px 5px; border-radius: 3px; font-weight: bold; margin-right: 8px; border: 1px solid #f5c6cb; }' +
        '#maint-modal .badge-warn { background: #fff3cd; color: #856404; font-size: 10px; padding: 2px 5px; border-radius: 3px; font-weight: bold; margin-right: 8px; border: 1px solid #ffeeba; }' +
        '#maint-modal .source-link { color: #3366cc; text-decoration: none; font-size: 11px; font-family: monospace; }' +
        '#maint-modal .source-link:hover { text-decoration: underline; }' +
        '#maint-modal button { padding: 12px; background-color: #d33; color: white; border: none; border-radius: 3px; cursor: pointer; font-weight: bold; width: 100%; font-size: 1.1em; }' +
        '.maint-close { float: right; cursor: pointer; font-size: 1.5em; color: #aaa; line-height: 0.8; }';
    mw.util.addCSS(modalCSS);

    var portletLink = mw.util.addPortletLink('p-cactions', '#', 'KILLRSP', 'ca-killrsp-v14', '斩杀工具:带源码预览的高级版');

    $(portletLink).on('click', function(e) {
        e.preventDefault();
        if ($('#maint-overlay').length) return;

        var api = new mw.Api();
        var pageTitle = mw.config.get('wgPageName');
        mw.notify('正在深度解析引用内容...', { autoHide: true });

        api.get({
            action: 'query',
            prop: 'revisions',
            titles: pageTitle,
            rvprop: 'content',
            rvlimit: 1,
            formatversion: 2
        }).done(function(data) {
            var page = data.query.pages[0];
            if (page.missing) return;

            var wikitext = page.revisions[0].content;
            var allRefs = wikitext.match(/<ref[^>]*>[\s\S]*?(?:\/>|<\/ref>)/gi);
            if (!allRefs) {
                mw.notify('未发现引用。');
                return;
            }

            var targets = PORTAL_DOMAINS.concat(SOCIAL_DOMAINS).concat(KEYWORDS);
            var checkRe = new RegExp(targets.join('|'), 'i');
            var exemptRe = new RegExp(EXEMPT_DOMAINS.join('|'), 'i');

            var matches = allRefs.filter(function(ref) {
                // 确保排除空引用和豁免项
                return checkRe.test(ref) && !exemptRe.test(ref) && ref.length > 10;
            });

            if (matches.length === 0) {
                mw.notify('干净如新,无需斩杀。');
                return;
            }

            renderKillPanel(wikitext, Array.from(new Set(matches)), api, pageTitle);
        });

        function renderKillPanel(originalText, sources, api, title) {
            var $overlay = $('<div id="maint-overlay">').appendTo('body');
            var $modal = $('<div>').attr('id', 'maint-modal').appendTo('body');
            $modal.html('<span class="maint-close">&times;</span><h2>KILLRSP: 斩杀决策终端</h2>');
            var $scroll = $('<div class="source-scroll">');
            
            var portalRe = new RegExp('(' + PORTAL_DOMAINS.join('|') + ')', 'i');

            sources.forEach(function(src) {
                var isPortal = portalRe.test(src);
                var $item = $('<div>').addClass('source-item');
                
                // 提取预览用的文字内容:去除标签,保留核心参数
                var previewText = src.replace(/<[^>]+>/g, '').replace(/[\r\n\t]+/g, ' ').trim();
                if (previewText.length > 120) previewText = previewText.substring(0, 120) + '...';
                if (!previewText) previewText = "(自闭合或无文本引用: " + src.match(/name\s*=\s*["']?([^"'>\s/]+)/i)[1] + ")";

                var $checkbox = $('<input type="checkbox" name="u-src">').val(src);
                var $header = $('<div style="margin-bottom:5px;">').append($checkbox);
                
                if (isPortal) {
                    $header.append($('<span>').addClass('badge-danger').text('高度确信'));
                    $checkbox.prop('checked', true);
                } else {
                    $header.append($('<span>').addClass('badge-warn').text('疑似 URG'));
                }
                
                $item.append($header);
                $item.append($('<div>').addClass('source-content').text(previewText));
                
                var urlMatch = src.match(/\|?\s*url\s*=\s*(https?:\/\/[^\s|}\[\]]+)/i) || src.match(/https?:\/\/[^\s|}<>\]]+/);
                if (urlMatch) {
                    var safeUrl = (urlMatch[1] || urlMatch[0]).replace(/^http:/i, 'https:');
                    $item.append($('<a>').attr({
                        href: safeUrl, 
                        target: '_blank', 
                        class: 'source-link'
                    }).text('🌐 预览链接: ' + safeUrl));
                }
                $scroll.append($item);
            });

            var $btn = $('<button>天生万物以养人,人无一物以报天,杀杀杀杀杀杀杀!</button>').on('click', function() {
                var selected = [];
                $('input[name="u-src"]:checked').each(function() { selected.push($(this).val()); });
                if (!selected.length) return;

                var newText = originalText;
                selected.forEach(function(item) {
                    var escapedItem = item.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
                    newText = newText.replace(new RegExp(escapedItem, 'g'), '');
                    
                    // 同时尝试清理基于 name 的复用标签
                    var nameMatch = item.match(/<ref[^>]+name\s*=\s*["']?([^"'>\s/]+)["']?[^>]*>/i);
                    if (nameMatch) {
                        var refName = nameMatch[1].replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
                        newText = newText.replace(new RegExp('<ref\\s+name\\s*=\\s*["\']?' + refName + '["\']?\\s*\\/>', 'gi'), '');
                    }
                });

                api.postWithToken('csrf', {
                    action: 'edit',
                    title: title,
                    text: newText,
                    summary: '批量移除不可靠来源 (使用[[User:Kurgenera/killRSP.js]])',
                    nocreate: true
                }).done(function() {
                    mw.notify('斩杀任务已执行。');
                    setTimeout(function() { location.reload(); }, 1000);
                });
                $overlay.add($modal).remove();
            });

            $modal.append($scroll, $btn);
            $overlay.add('.maint-close').on('click', function() { $overlay.add($modal).remove(); });
        }
    });
});