bilispace

good

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         bilispace
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  good
// @match        *://space.bilibili.com/*
// @run-at       document-start
// @grant        none
// ==/UserScript==
 
(function() {
    'use strict';
    
    const originalFetch = window.fetch;
    const userCardCache = new Map();
    const requestCounter = new Map();
    function safeGet(obj, path, defaultValue = undefined) {
        return path.split('.').reduce((current, key) => {
            return (current && current[key] !== undefined) ? current[key] : defaultValue;
        }, obj);
    }
 
    async function fetchUserCard(mid) {
        // 检查缓存
        if (userCardCache.has(mid)) {
            console.log(`[SpaceTweaks] 使用缓存数据 mid: ${mid}`);
            return userCardCache.get(mid);
        }
 
        const now = Date.now();
        const userRequests = requestCounter.get(mid) || [];
        const recentRequests = userRequests.filter(time => now - time < 60000);
        
        if (recentRequests.length >= 3) {
            console.warn(`[SpaceTweaks] 用户 ${mid} 请求过于频繁,已限制`);
            return null;
        }
        
        try {
            console.log(`[SpaceTweaks] 获取用户卡片信息 mid: ${mid}`);
            
            const cardResponse = await originalFetch(`https://api.bilibili.com/x/web-interface/card?mid=${mid}`);
            
            if (!cardResponse.ok) {
                console.error(`[SpaceTweaks] 卡片接口请求失败: ${cardResponse.status}`);
                return null;
            }
            
            const cardData = await cardResponse.json();
            
            if (cardData.code !== 0) {
                console.warn(`[SpaceTweaks] 卡片接口返回错误: code=${cardData.code}, message=${cardData.message}`);
                return null;
            }
            if (!cardData.data?.card) {
                console.warn('[SpaceTweaks] 卡片数据结构异常');
                return null;
            }
            
            recentRequests.push(now);
            requestCounter.set(mid, recentRequests);
       
            const cacheData = {
                data: cardData.data.card,
                expiry: now + 300000
            };
            userCardCache.set(mid, cacheData);
            setTimeout(() => {
                userCardCache.delete(mid);
            }, 300000);
            
            return cacheData;
            
        } catch (error) {
            console.error(`[SpaceTweaks] 获取用户卡片时发生错误:`, error);
            return null;
        }
    }
    
    function createSafeResponse(cardData, mid) {
        const card = cardData.data;
        
        const official = {
            type: safeGet(card, 'Official.type', -1),
            desc: safeGet(card, 'Official.desc', ''),
            title: safeGet(card, 'Official.title', '')
        };
        
        return {
            code: 0,
            message: "0",
            ttl: 1,
            data: {
                attestation: {
                    type: official.type,
                    desc: official.desc,
                    splice_info: {
                        title: official.title
                    },
                    common_info: {
                        title: official.title
                    }
                },
                birthday: '01-01',
                certificate_show: 0,
                coins: 0,
                contract: {
                    is_display: false,
                    is_follow_display: false
                },
                elec: {
                    show_info: {
                        show: false
                    }
                },
                face: safeGet(card, 'face', 'https://i0.hdslb.com/bfs/face/member/noface.jpg'),
                face_nft: safeGet(card, 'face_nft', 0),
                face_nft_type: safeGet(card, 'face_nft_type', 0),
                fans_badge: true,
                fans_medal: {
                    show: false
                },
                gaia_data: null,
                gaia_res_type: 0,
                is_followed: false,
                is_risk: false,
                is_senior_member: false,
                level: safeGet(card, 'level_info.current_level', 0),
                mid: parseInt(mid, 10),
                name: safeGet(card, 'name', '未知用户'),
                offical: official, 
                sex: safeGet(card, 'sex', '保密'),
                sign: safeGet(card, 'sign', ''),
                tags: [],
                top_photo_v2: {
                    l_img: safeGet(card, 'l_img', '')
                },
                _spacetweaks_processed: true,
                _spacetweaks_timestamp: Date.now()
            }
        };
    }
    
    window.fetch = async function(...args) {
        const response = await originalFetch.apply(this, args);
 
        if (!args[0] || !args[0].includes('x/space/wbi/acc/info')) {
            return response;
        }
        
        try {
            const clone = response.clone();
            let json;
            
            try {
                json = await clone.json();
            } catch (parseError) {
                console.error('[SpaceTweaks] JSON解析失败:', parseError);
                return response;
            }
 
            if (json.code !== -404) {
                return response;
            }
 
            let mid;
            try {
                const fullUrl = args[0].startsWith('http') ? args[0] : `https://api.bilibili.com${args[0]}`;
                mid = (new URL(fullUrl)).searchParams.get('mid');
                
                if (!mid || !/^\d+$/.test(mid)) {
                    console.warn('[SpaceTweaks] 无效的mid参数:', mid);
                    return response;
                }
            } catch (urlError) {
                console.error('[SpaceTweaks] URL解析失败:', urlError);
                return response;
            }
            
            console.log(`[SpaceTweaks] 检测到用户不存在或被封禁 mid: ${mid}, 尝试获取基本信息`);
 
            const cardData = await fetchUserCard(mid);
            if (!cardData) {
                console.log('[SpaceTweaks] 无法获取用户信息,返回原响应');
                return response;
            }
 
            if (Date.now() > cardData.expiry) {
                console.log('[SpaceTweaks] 缓存已过期,返回原响应');
                return response;
            }
            
            // 构造新的响应
            const newJson = createSafeResponse(cardData, mid);
            
            const newResponse = new Response(JSON.stringify(newJson), {
                status: response.status,
                statusText: response.statusText,
                headers: response.headers
            });
            
            console.log(`[SpaceTweaks] 成功为用户 ${mid} 构造响应`);
            return newResponse;
            
        } catch (error) {
            console.error('[SpaceTweaks] 处理响应时发生错误:', error);
            return response;
        }
    };
    
    setInterval(() => {
        const now = Date.now();
        for (const [mid, data] of userCardCache.entries()) {
            if (now > data.expiry) {
                userCardCache.delete(mid);
            }
        }
 
        for (const [mid, requests] of requestCounter.entries()) {
            const recent = requests.filter(time => now - time < 60000);
            if (recent.length === 0) {
                requestCounter.delete(mid);
            } else {
                requestCounter.set(mid, recent);
            }
        }
    }, 60000);
    
    console.log('[SpaceTweaks ');
})();