更好的B站分享按钮

替换原有分享按钮,点击后调用api生成短链接并复制页面标题和短链接到剪切板

当前为 2024-08-14 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         更好的B站分享按钮
// @author       果冻大神
// @namespace    http://tampermonkey.net/
// @version      1.3.8
// @description  替换原有分享按钮,点击后调用api生成短链接并复制页面标题和短链接到剪切板
// @match        *://www.bilibili.com/*
// @match        *://live.bilibili.com/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const SHORTEN_API_URL = 'https://api.bilibili.com/x/share/click';

    function cleanUrl(url) {
        const urlObj = new URL(url);
        urlObj.search = '';
        return urlObj.toString();
    }

    function cleanTitle(title, isLive = false) {
        if (isLive) {
            // 针对直播间的标题清理逻辑
            const liveSuffixes = [' - 哔哩哔哩直播,二次元弹幕直播平台'];
            for (const suffix of liveSuffixes) {
                const index = title.indexOf(suffix);
                if (index !== -1) {
                    return title.substring(0, index).trim();
                }
            }
        } else {
            // 针对其他页面的标题清理逻辑
            const suffixes = ['_哔哩哔哩', 'bilibili', '_bilibili', '哔哩哔哩'];
            for (const suffix of suffixes) {
                const index = title.indexOf(suffix);
                if (index !== -1) {
                    return title.substring(0, index).trim();
                }
            }
        }
        return title.trim();
    }

    function copyToClipboard(text) {
        navigator.clipboard.writeText(text).catch(err => {
            console.error('复制失败: ', err);
        });
    }

    async function getShortenedUrl(longUrl) {
        try {
            const build = Math.floor(Math.random() * (9000000 - 6000000 + 1)) + 6000000;
            const buvid = Array.from({ length: 32 }, () => Math.random().toString(36)[2]).join('') + 'infoc';
            const platform = ['android', 'ios'][Math.floor(Math.random() * 2)];
            const shareMode = Math.floor(Math.random() * 10) + 1;

            const response = await fetch(SHORTEN_API_URL, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: new URLSearchParams({
                    build: build,
                    buvid: buvid,
                    oid: longUrl,
                    platform: platform,
                    share_channel: 'COPY',
                    share_id: 'public.webview.0.0.pv',
                    share_mode: shareMode
                }).toString()
            });

            const data = await response.json();
            if (data.data && data.data.content) {
                return data.data.content;
            } else {
                throw new Error('B站没有返回短链接。');
            }
        } catch (error) {
            console.error('获取短链接时出错:', error);
            return longUrl;
        }
    }

    function createReplacementButton(isLive = false) {
        const button = document.createElement('button');
        button.innerText = isLive ? '分享' : '点击复制分享链接';
        button.style.padding = '10px 20px';
        button.style.border = 'none';
        button.style.color = isLive ? '#FFFFFF' : '#61666D';
        button.style.backgroundColor = 'transparent';
        button.style.borderRadius = '5px';
        button.style.cursor = 'pointer';
        button.style.fontSize = '14px';
        button.style.fontWeight = 'bold';
        button.style.transition = 'color 0.3s';

        button.addEventListener('click', async (event) => {
            event.stopPropagation();

            button.style.color = '#ffd432';
            setTimeout(() => {
                button.style.color = isLive ? '#FFFFFF' : '#61666D';
            }, 1000);

            const title = cleanTitle(document.title, isLive);
            const url = cleanUrl(window.location.href);

            try {
                const shortUrl = await getShortenedUrl(url);
                const textToCopy = `【${title}】\n${shortUrl}`;
                copyToClipboard(textToCopy);
            } catch (error) {
                console.error('获取短链接失败:', error);
            }
        });

        return button;
    }

    function replaceShareButton() {
        const shareButton = document.getElementById('share-btn-outer');
        if (shareButton) {
            shareButton.remove();
            const replacementButton = createReplacementButton();
            const toolbar = document.querySelector('.video-toolbar-left-main');
            if (toolbar) {
                toolbar.style.position = 'relative';
                toolbar.appendChild(replacementButton);
            }
        } else {
            setTimeout(replaceShareButton, 500);
        }
    }

    function replaceLiveShareButton() {
        const liveShareButton = document.querySelector("#head-info-vm > div > div.rows-ctnr.rows-content > div.upper-row > div.right-ctnr > div.more.live-skin-normal-a-text");
        if (liveShareButton) {
            liveShareButton.remove();
            const replacementButton = createReplacementButton(true);
            const liveToolbar = document.querySelector("#head-info-vm > div > div.rows-ctnr.rows-content > div.upper-row > div.right-ctnr");
            if (liveToolbar) {
                liveToolbar.style.position = 'relative';
                liveToolbar.appendChild(replacementButton);
            }
        } else {
            setTimeout(replaceLiveShareButton, 500);
        }
    }

    function init() {
        if (window.location.hostname === 'live.bilibili.com') {
            replaceLiveShareButton();
        } else {
            replaceShareButton();
        }
    }

    init();
})();