bilispace

good

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

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