Greasy Fork

Greasy Fork is available in English.

B站动态批量删除助手

这是一个帮助B站用户高效管理个人动态的脚本,支持多种类型动态的批量删除操作。

当前为 2025-01-27 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         B站动态批量删除助手
// @version      0.28
// @description  这是一个帮助B站用户高效管理个人动态的脚本,支持多种类型动态的批量删除操作。
// @author       梦把我
// @match        https://space.bilibili.com/*
// @match        http://space.bilibili.com/*
// @require      http://greasyfork.icu/scripts/38220-mscststs-tools/code/MSCSTSTS-TOOLS.js?version=713767
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/axios.min.js
// @icon         https://static.hdslb.com/images/favicon.ico
// @namespace http://greasyfork.icu/users/1383389
// @license      MIT
// @grant        GM_addStyle
// ==/UserScript==
(function () {
    'use strict';
 
    const uid = window.location.pathname.split("/")[1];
 
    function getUserCSRF() {
        return document.cookie.split("; ").find(row => row.startsWith("bili_jct="))?.split("=")[1];
    }
 
    const csrfToken = getUserCSRF();
 
    class Api {
        constructor() { }
 
        async spaceHistory(offset = 0) { // 获取个人动态
            return this.retryOn429(() => this._api(
                `https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/space_history?visitor_uid=${uid}&host_uid=${uid}&offset_dynamic_id=${offset}`,
                {}, "get"
            ));
        }
 
        async removeDynamic(id) { // 删除动态
            return this._api(
                "https://api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/rm_dynamic",
                { dynamic_id: id, csrf_token: csrfToken }
            );
        }
 
        async _api(url, data, method = "post") { // 通用请求
            return axios({
                url,
                method,
                data: this.transformRequest(data),
                withCredentials: true,
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded'
                }
            }).then(res => res.data);
        }
 
        transformRequest(data) { // 转换请求参数
            return Object.entries(data).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join('&');
        }
 
        async fetchJsonp(url) { // jsonp请求
            return fetchJsonp(url).then(res => res.json());
        }
 
        async retryOn429(func, retries = 5, delay = 100) { // 出现429错误时冷却100ms重试,出现412错误时提示并退出
            while (retries > 0) {
                try {
                    return await func();
                } catch (err) {
                    if (err.response && err.response.status === 429) {
                        await this.sleep(delay);
                        retries--;
                    } else if (err.response && err.response.status === 412) {
                        alert('由于请求过于频繁,IP暂时被ban,请更换IP或稍后再试。');
                        throw new Error('IP blocked, please retry later.');
                    } else {
                        throw err;
                    }
                }
            }
            throw new Error('Too many retries, request failed.');
        }
 
        sleep(ms) { // 睡眠
            return new Promise(resolve => setTimeout(resolve, ms));
        }
    }
 
    const api = new Api();
    const buttons = [
        ".onlyDeleteRepost", 
        ".deleteVideo", 
        ".deleteImage", 
        ".deleteText", 
        ".deleteArticle", 
        ".deleteShortVideo"
    ];
    let logNode;
 
    // 添加确认状态管理
    const confirmStates = {
        deleteStates: {},
        resetTimer: null
    };
 
    // 获取当前URL中的UID
    function getCurrentUID() {
        const pathParts = window.location.pathname.split('/');
        return pathParts[1] || '';
    }

    // 获取自己的UID(通过访问space.bilibili.com)
    async function getMyUID() {
        try {
            const response = await fetch('https://space.bilibili.com/', {
                credentials: 'include'  // 确保携带cookie
            });
            // 获取重定向后的URL
            const redirectUrl = response.url;
            const uid = redirectUrl.split('/').pop();
            return uid;
        } catch (error) {
            console.error('获取用户UID失败:', error);
            return null;
        }
    }
 
    async function init() {
        try {
            // 等待页面加载完成
            await new Promise(resolve => setTimeout(resolve, 500));

            // 获取当前页面UID和自己的UID
            const currentUID = getCurrentUID();
            const myUID = await getMyUID();

            // 判断是否为自己的空间
            if (!currentUID || !myUID || currentUID !== myUID) {
                console.log('当前不是自己的个人动态页面,脚本未启用');
                return;
            }

            // 创建控制面板节点
            const node = createControlPanel();
            
            // 尝试插入到新版或旧版界面
            try {
                // 先尝试获取新版界面的位置
                const newVersionContainer = document.querySelector("#app > main > div.space-dynamic > div.space-dynamic__right");
                if (newVersionContainer) {
                    const firstChild = newVersionContainer.querySelector("div:nth-child(1)");
                    if (firstChild) {
                        newVersionContainer.insertBefore(node, firstChild);
                    } else {
                        newVersionContainer.appendChild(node);
                    }
                    console.log('成功插入到新版界面');
                } else {
                    // 如果找不到新版界面,尝试旧版界面
                    const oldVersionContainer = document.querySelector("#page-dynamic .col-2");
                    if (oldVersionContainer) {
                        oldVersionContainer.appendChild(node);
                        console.log('成功插入到旧版界面');
                    } else {
                        console.error('无法找到合适的插入位置');
                        return;
                    }
                }

                // 设置事件监听
                setEventListeners();
                
                // 设置教程链接
                document.querySelector('.tutorial-btn').href = 'https://www.bilibili.com/video/BV13NBnYyEML/';
                
                // 添加样式
                addConfirmationStyles();
                
            } catch (error) {
                console.error('插入控制面板失败:', error);
            }

        } catch (error) {
            console.error('验证用户身份失败:', error);
        }
    }
 
    function createControlPanel() {
        const node = document.createElement("div");
        node.className = "msc_panel";
        node.innerHTML = `
            <div class="inner">
                <div class="panel-section quick-actions">
                    <h3>快捷操作</h3>
                    <div class="button-group">
                        <button class="onlyDeleteRepost">删除转发动态</button>
                        <button class="deleteVideo">删除视频动态</button>
                        <button class="deleteImage">删除图片动态</button>
                        <button class="deleteText">删除文字动态</button>
                        <button class="deleteArticle">删除专栏动态</button>
                        <button class="deleteShortVideo">删除小视频动态</button>
                    </div>
                </div>

                <div class="panel-section other-actions">
                    <h3>其他</h3>
                    <div class="button-group">
                        <a href="#" class="tutorial-btn" target="_blank">使用视频教程</a>
                    </div>
                </div>

                <div class="panel-section pin-settings">
                    <h3>动态保留设置</h3>
                    <div class="setting-group">
                        <label class="switch">
                            <input type="checkbox" id="preservePinned">
                            <span class="slider round"></span>
                            <span class="label">保留指定的动态</span>
                        </label>
                        <div class="preserve-contents">
                            <div class="preserve-content-item">
                                <input type="text" class="preserve-content" placeholder="输入要保留的动态文字内容">
                                <small class="tip">输入动态中的部分内容即可,建议复制完整内容以提高匹配准确度</small>
                            </div>
                            <button class="add-preserve-content" title="添加更多保留内容">
                                <span>+</span>
                            </button>
                        </div>
                        
                        <div class="most-liked-setting">
                            <label class="switch">
                                <input type="checkbox" id="preserveMostLiked">
                                <span class="slider round"></span>
                                <span class="label">保留点赞最高的动态</span>
                            </label>
                            <div class="most-liked-count">
                                <input type="number" id="mostLikedCount" value="3" min="1" disabled>
                                <small class="tip">设置要保留的点赞最高动态数量</small>
                            </div>
                        </div>
                    </div>
                </div>
            </div>`;
        return node;
    }
 
    function setEventListeners() {
        document.querySelector(".onlyDeleteRepost").addEventListener("click", () => handleConfirmation("onlyDeleteRepost", () => handleDelete(false)));
        document.querySelector(".deleteVideo").addEventListener("click", () => handleConfirmation("deleteVideo", () => handleDeleteByType(8)));
        document.querySelector(".deleteImage").addEventListener("click", () => handleConfirmation("deleteImage", () => handleDeleteByType(2)));
        document.querySelector(".deleteText").addEventListener("click", () => handleConfirmation("deleteText", () => handleDeleteByType(4)));
        document.querySelector(".deleteArticle").addEventListener("click", () => handleConfirmation("deleteArticle", () => handleDeleteByType(64)));
        document.querySelector(".deleteShortVideo").addEventListener("click", () => handleConfirmation("deleteShortVideo", () => handleDeleteByType(16)));
        
        // 添加新的保留内容输入框
        document.querySelector('.add-preserve-content').addEventListener('click', addPreserveContentInput);
        
        // 添加点赞设置相关的事件监听
        const preserveMostLikedCheckbox = document.querySelector('#preserveMostLiked');
        const mostLikedCountInput = document.querySelector('#mostLikedCount');
        
        preserveMostLikedCheckbox.addEventListener('change', (e) => {
            mostLikedCountInput.disabled = !e.target.checked;
        });
        
        mostLikedCountInput.addEventListener('input', (e) => {
            const value = parseInt(e.target.value);
            if (value < 1) e.target.value = 1;
        });
    }
 
    async function handleDelete(deleteLottery) { // 删除参数 unfollow
        disableAll();
        let deleteCount = 0; // 删除计数
        let hasMore = true; // 是否还有更多动态
        let offset = 0; // 动态偏移量
 
        while (hasMore) {
            const { data } = await api.spaceHistory(offset);
            hasMore = data.has_more;
 
            for (const card of data.cards) {
                offset = card.desc.dynamic_id_str;
 
                if (card.desc.orig_dy_id != 0) { // 如果是转发动态
                    try {
                        const content = JSON.parse(card.card);
                        const content2 = JSON.parse(content.origin_extend_json);
 
                        if (!deleteLottery || content2.lott) { // 如果"仅删除抽奖"为假,或判断为抽奖动态
                            const rm = await api.removeDynamic(card.desc.dynamic_id_str);
                            if (rm.code === 0) deleteCount++;
                            else throw new Error("删除出错");
                        }
                        await api.sleep(50);
                        log(`已删除 ${deleteCount} 条动态`);
                    } catch (e) {
                        console.error(e);
                        break;
                    }
                }
            }
        }
        enableAll();
    }
 
    function disableAll() {
        console.log('start');
        buttons.forEach(btn => {
            const button = document.querySelector(btn);
            button.disabled = true;
            resetButtonState(btn.substring(1)); // 移除开头的点号
        });
        confirmStates.deleteStates = {}; // 清除所有确认状态
    }
 
    function enableAll() {
        console.log('done');
        buttons.forEach(btn => {
            const button = document.querySelector(btn);
            if (button) {
                button.disabled = false;
                resetButtonState(btn.substring(1));
            }
        });
        confirmStates.deleteStates = {};
        log('操作已完成!', true);
    }
 
    let currentPopup = null;
    let currentTimer = null;

    function log(message, autoRefresh = false) {
        // 如果存在之前的弹窗和定时器,先清除
        if (currentPopup) {
            currentPopup.remove();
            clearTimeout(currentTimer);
        }

        // 创建新的弹窗
        const popup = document.createElement('div');
        popup.className = 'log-popup';
        popup.textContent = message;
        document.body.appendChild(popup);
        currentPopup = popup;

        if (autoRefresh) {
            let countdown = 3;
            const updateCountdown = () => {
                popup.textContent = `${message} (${countdown}秒后自动刷新)`;
                countdown--;
                if (countdown < 0) {
                    window.location.reload();
                } else {
                    currentTimer = setTimeout(updateCountdown, 1000);
                }
            };
            updateCountdown();
        } else {
            // 3秒后自动隐藏弹窗
            currentTimer = setTimeout(() => {
                popup.classList.add('hide');
                setTimeout(() => popup.remove(), 300);
            }, 3000);
        }
    }
 
    async function handleDeleteByType(targetType) {
        const preservePinned = document.querySelector('#preservePinned').checked;
        const preserveMostLiked = document.querySelector('#preserveMostLiked').checked;
        const mostLikedCount = parseInt(document.querySelector('#mostLikedCount').value);
        const preserveContents = Array.from(document.querySelectorAll('.preserve-content'))
            .map(input => input.value.trim())
            .filter(value => value !== '');
        
        if (preservePinned && preserveContents.length === 0) {
            alert('检测到开启保留动态功能,请至少输入一个要保留的动态内容');
            return;
        }

        try {
            disableAll();
            let deleteCount = 0;
            let hasMore = true;
            let offset = 0;
            let allDynamics = [];

            // 首先收集所有动态
            while (hasMore) {
                const { data } = await api.spaceHistory(offset);
                hasMore = data.has_more;
                
                for (const card of data.cards) {
                    if (card.desc.type === targetType) {
                        allDynamics.push({
                            id: card.desc.dynamic_id_str,
                            likes: card.desc.like,
                            content: JSON.parse(card.card)?.item?.content || ''
                        });
                    }
                    offset = card.desc.dynamic_id_str;
                }
            }

            // 如果需要保留点赞最高的动态
            let preservedIds = new Set();
            if (preserveMostLiked && mostLikedCount > 0) {
                const topLiked = allDynamics
                    .sort((a, b) => b.likes - a.likes)
                    .slice(0, mostLikedCount);
                preservedIds = new Set(topLiked.map(d => d.id));
            }

            // 执行删除操作
            for (const dynamic of allDynamics) {
                // 跳过需要保留的动态
                if (preservedIds.has(dynamic.id)) {
                    console.log('保留点赞数最高的动态:', dynamic.id, '点赞数:', dynamic.likes);
                    continue;
                }

                // 检查是否包含需要保留的内容
                if (preservePinned && preserveContents.length > 0) {
                    if (preserveContents.some(content => dynamic.content.includes(content))) {
                        console.log('跳过包含保留内容的动态:', dynamic.content);
                        continue;
                    }
                }

                try {
                    const rm = await api.removeDynamic(dynamic.id);
                    if (rm.code === 0) deleteCount++;
                    await api.sleep(50);
                    log(`已删除 ${deleteCount} 条类型为 ${targetType} 的动态`);
                } catch (e) {
                    console.error(e);
                    break;
                }
            }
        } catch (error) {
            console.error('删除操作执行出错:', error);
        } finally {
            enableAll();
        }
    }
 
    // 添加确认处理函数
    function handleConfirmation(buttonId, callback) {
        const button = document.querySelector(`.${buttonId}`);
        if (!button) return;
        
        const originalText = button.textContent;
        
        // 如果是首次点击
        if (!confirmStates.deleteStates[buttonId]) {
            // 设置确认状态
            confirmStates.deleteStates[buttonId] = true;
            
            // 修改按钮文字
            button.textContent = "确认删除?";
            button.style.backgroundColor = "#ff6b6b";
            
            // 添加闪烁动画
            button.style.animation = "buttonBlink 1s infinite";
            
            // 5秒后重置状态
            setTimeout(() => {
                resetButtonState(buttonId);
            }, 5000);
            
            // 显示提示
            log("请再次点击确认删除操作");
        } else {
            try {
                // 第二次点击,执行删除
                resetButtonState(buttonId);
                callback();
            } catch (error) {
                console.error('执行删除操作时出错:', error);
                resetButtonState(buttonId);
                enableAll();
                log('操作执行出错,请重试');
            }
        }
    }
 
    // 重置按钮状态
    function resetButtonState(buttonId) {
        const button = document.querySelector(`.${buttonId}`);
        if (!button) return;
        
        // 重置确认状态
        confirmStates.deleteStates[buttonId] = false;
        
        // 重置按钮状态
        button.disabled = false;
        button.textContent = getOriginalButtonText(buttonId);
        button.style.backgroundColor = "";
        button.style.animation = "";
        
        // 清除可能存在的定时器
        if (confirmStates.resetTimer) {
            clearTimeout(confirmStates.resetTimer);
            confirmStates.resetTimer = null;
        }
    }
 
    // 获取按钮原始文字
    function getOriginalButtonText(buttonId) {
        const textMap = {
            'onlyDeleteRepost': '删除转发动态',
            'deleteVideo': '删除视频动态',
            'deleteImage': '删除图片动态',
            'deleteText': '删除文字动态',
            'deleteArticle': '删除专栏动态',
            'deleteShortVideo': '删除小视频动态'
        };
        return textMap[buttonId] || '删除';
    }
 
    // 添加闪烁动画样式
    function addConfirmationStyles() {
        // 使用 GM_addStyle 替代直接创建 style 标签
        const styles = `
            .msc_panel {
                max-width: 100%;
                margin: 0 0 20px 0;
                padding: 20px;
                background: #fff;
                border-radius: 8px;
                box-shadow: 0 2px 8px rgba(0,0,0,0.1);
            }

            .panel-section {
                margin-bottom: 24px;
                padding-bottom: 20px;
                border-bottom: 1px solid #eee;
            }

            .panel-section:last-child {
                border-bottom: none;
                margin-bottom: 0;
            }

            .panel-section h3 {
                font-size: 16px;
                color: #18191c;
                margin-bottom: 16px;
                font-weight: 500;
            }

            .type-table table {
                width: 100%;
                border-collapse: collapse;
                margin: 10px 0;
                font-size: 14px;
            }

            .type-table th, .type-table td {
                padding: 8px;
                text-align: center;
                border: 1px solid #eee;
            }

            .type-table th {
                background: #f6f7f8;
            }

            .input-group {
                display: flex;
                gap: 10px;
                margin-bottom: 10px;
            }

            .type-input {
                flex: 1;
                padding: 8px 12px;
                border: 1px solid #ddd;
                border-radius: 4px;
                font-size: 14px;
            }

            .button-group {
                display: flex;
                flex-wrap: wrap;
                gap: 10px;
            }

            .msc_panel button {
                padding: 8px 16px;
                border-radius: 4px;
                border: 1px solid #ddd;
                background: #fff;
                cursor: pointer;
                font-size: 14px;
                transition: all 0.2s;
            }

            .msc_panel button:hover {
                background: #f6f7f8;
            }

            .msc_panel button.primary-btn {
                background: #00aeec;
                color: #fff;
                border-color: #00aeec;
            }

            .msc_panel button.primary-btn:hover {
                background: #0096cc;
            }

            .msc_panel button.warning-btn {
                background: #fb7299;
                color: #fff;
                border-color: #fb7299;
            }

            .msc_panel button.warning-btn:hover {
                background: #e45c80;
            }

            .msc_panel button:disabled {
                background: #eee;
                color: #999;
                cursor: not-allowed;
                border-color: #ddd;
            }

            .tutorial-btn {
                display: inline-block;
                padding: 8px 16px;
                background: #6c757d;
                color: #fff;
                text-decoration: none;
                border-radius: 4px;
                transition: all 0.2s;
            }

            .tutorial-btn:hover {
                background: #5a6268;
            }

            .log {
                margin-top: 16px;
                padding: 12px;
                background: #f6f7f8;
                border-radius: 4px;
                font-size: 14px;
                color: #666;
            }

            @keyframes buttonBlink {
                0% { opacity: 1; }
                50% { opacity: 0.7; }
                100% { opacity: 1; }
            }
            
            .msc_panel button.confirming {
                background-color: #ff6b6b !important;
                color: white !important;
            }
            
            .msc_panel button:disabled {
                animation: none !important;
                opacity: 0.5 !important;
            }

            .pin-settings {
                margin: 15px 0;
            }
            .setting-group {
                display: flex;
                flex-direction: column;
                gap: 10px;
            }
            .switch {
                display: flex;
                align-items: center;
                gap: 10px;
            }
            .switch input {
                display: none;
            }
            .slider {
                position: relative;
                width: 40px;
                height: 20px;
                background-color: #ccc;
                border-radius: 20px;
                cursor: pointer;
                transition: .4s;
            }
            .slider:before {
                position: absolute;
                content: "";
                height: 16px;
                width: 16px;
                left: 2px;
                bottom: 2px;
                background-color: white;
                border-radius: 50%;
                transition: .4s;
            }
            input:checked + .slider {
                background-color: #2196F3;
            }
            input:checked + .slider:before {
                transform: translateX(20px);
            }
            .pin-content-input {
                margin-top: 5px;
            }
            .pin-content-input input {
                width: 100%;
                padding: 5px;
                border: 1px solid #ddd;
                border-radius: 4px;
            }
            .tip {
                color: #999;
                font-size: 12px;
                margin-top: 5px;
                display: block;
            }

            /* 弹窗样式 */
            .log-popup {
                position: fixed;
                bottom: 20px;
                right: 20px;
                background: rgba(0, 0, 0, 0.8);
                color: white;
                padding: 12px 20px;
                border-radius: 8px;
                z-index: 999999;
                font-size: 14px;
                max-width: 300px;
                animation: fadeInOut 0.3s ease-in-out;
                box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
            }

            @keyframes fadeInOut {
                0% {
                    opacity: 0;
                    transform: translateY(20px);
                }
                100% {
                    opacity: 1;
                    transform: translateY(0);
                }
            }

            .log-popup.hide {
                animation: fadeOut 0.3s ease-in-out forwards;
            }

            @keyframes fadeOut {
                0% {
                    opacity: 1;
                    transform: translateY(0);
                }
                100% {
                    opacity: 0;
                    transform: translateY(20px);
                }
            }

            .preserve-contents {
                display: flex;
                flex-direction: column;
                gap: 10px;
                margin-top: 10px;
            }
            
            .preserve-content-item {
                position: relative;
            }
            
            .input-wrapper {
                display: flex;
                gap: 8px;
                align-items: center;
            }
            
            .preserve-content {
                flex: 1;
                padding: 8px 12px;
                border: 1px solid #ddd;
                border-radius: 4px;
                width: 100%;
            }
            
            .add-preserve-content {
                align-self: flex-start;
                padding: 4px 12px;
                background: #00aeec;
                color: white;
                border: none;
                border-radius: 4px;
                cursor: pointer;
                font-size: 16px;
                margin-top: 5px;
            }
            
            .add-preserve-content:hover {
                background: #0096cc;
            }
            
            .remove-content {
                padding: 4px 8px;
                background: #ff6b6b;
                color: white;
                border: none;
                border-radius: 4px;
                cursor: pointer;
                font-size: 16px;
            }
            
            .remove-content:hover {
                background: #ff5252;
            }

            .most-liked-setting {
                margin-top: 15px;
            }
            
            .most-liked-count {
                margin-top: 10px;
                margin-left: 30px;
            }
            
            .most-liked-count input {
                width: 60px;
                padding: 5px;
                border: 1px solid #ddd;
                border-radius: 4px;
            }
            
            .most-liked-count input:disabled {
                background-color: #f5f5f5;
                cursor: not-allowed;
            }
        `;
        
        // 添加 @grant GM_addStyle 到脚本头部后,使用 GM_addStyle
        GM_addStyle(styles);
    }
 
    // 添加动态类型验证函数
    function isValidDynamicType(type) {
        const validTypes = [1, 2, 4, 8, 16, 64];
        return validTypes.includes(type);
    }
 
    // 检查是否存在置顶动态
    async function checkPinnedDynamic() {
        try {
            // 检查新版界面
            const newVersionPin = document.evaluate(
                '//*[@id="app"]/main/div[1]/div[2]/div/div/div/div[1]/div[1]/div/div[1]/div/div',
                document,
                null,
                XPathResult.FIRST_ORDERED_NODE_TYPE,
                null
            ).singleNodeValue;

            // 检查旧版界面
            const oldVersionPin = document.evaluate(
                '//*[@id="page-dynamic"]/div[1]/div/div[1]/div/div/div[1]/div/div',
                document,
                null,
                XPathResult.FIRST_ORDERED_NODE_TYPE,
                null
            ).singleNodeValue;

            return !!(newVersionPin || oldVersionPin);
        } catch (error) {
            console.error('检查置顶动态失败:', error);
            return false;
        }
    }
 
    // 添加新的保留内容输入框的函数
    function addPreserveContentInput() {
        const container = document.querySelector('.preserve-contents');
        const newItem = document.createElement('div');
        newItem.className = 'preserve-content-item';
        newItem.innerHTML = `
            <div class="input-wrapper">
                <input type="text" class="preserve-content" placeholder="输入要保留的动态文字内容">
                <button class="remove-content" title="删除此条件">×</button>
            </div>
            <small class="tip">输入动态中的部分内容即可,建议复制完整内容以提高匹配准确度</small>
        `;
        
        // 添加删除按钮的事件监听
        newItem.querySelector('.remove-content').addEventListener('click', () => {
            newItem.remove();
        });
        
        container.insertBefore(newItem, document.querySelector('.add-preserve-content'));
    }
 
    init();
})();