Greasy Fork

Greasy Fork is available in English.

★一键查看Bangumi动画详情★

该脚本适配Bilibili,次元城动漫,稀饭动漫,mutefun,风铃动漫,NT动漫,Age动漫等动画网站,可一键跳转到Bangumi查看动画详情

当前为 2025-07-29 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         ★一键查看Bangumi动画详情★
// @namespace    http://tampermonkey.net/
// @version      0.1.7
// @description  该脚本适配Bilibili,次元城动漫,稀饭动漫,mutefun,风铃动漫,NT动漫,Age动漫等动画网站,可一键跳转到Bangumi查看动画详情
// @author       Aomine
// @match        *://www.agedm.vip/play*
// @match        *://www.cycani.org/watch*
// @match        *://www.mutean.com/vodplay*
// @match        *://www.aafun.cc/f*
// @match        *://www.ntdm8.com/play*
// @match        *://www.mwcy.net/play*
// @match        *://dm.xifanacg.com/watch*
// @match        *://anich.emmmm.eu.org/b*
// @match        *://www.bilibili.com/bangumi/play*
// @grant        GM_xmlhttpRequest
// @grant        GM_registerMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue
// @connect      bgm.tv
// @license      GPL License
// @icon         https://bgm.tv/img/favicon.ico
// ==/UserScript==

(function() {
    'use strict';

    // 初始化设置
    const config = {
        showButton: GM_getValue('showButton', true),  // 默认显示按钮
        excludedSites: GM_getValue('excludedSites', [])  // 默认不排除任何站点
    };

    // 注册菜单命令
    GM_registerMenuCommand("⚙️ 脚本设置", openSettings);
    GM_registerMenuCommand(config.showButton ? "🔘 按钮开关" :"❌ 隐藏按钮" , toggleButton);

    // 各网站标题选择器配置
    const siteSelectors = {
        'www.agedm.vip': '.card-body .card-title',
        'www.cycani.org':'a.player-title-link',
        'www.mutean.com': '.module-info-heading h1 a',
        'anich.emmmm.eu.org': 'section[player-info] a[href^="/b/"]',
        'www.ntdm8.com': 'h4#detailname a:first-child',
        'www.mwcy.net': 'h2.top20 a.player-title-link',
        'dm.xifanacg.com': 'a.player-title-link',
        'www.aafun.cc': [
                         'h2.play-title .hl-infos-title',
                          '.hl-dc-title .hl-data-menu'
                         ],
        'www.bilibili.com': [
            '.mediainfo_mediaTitle__Zyiqh',
            '[class*="mediaTitle"]',
            '.video-info .video-title',
            '.media-title',
            'h1.title'
        ].join(', ')
    };

    // 切换按钮显示状态
    function toggleButton() {
        config.showButton = !config.showButton;
        GM_setValue('showButton', config.showButton);

        const button = document.querySelector('#bangumiJumpButton');
        if (button) {
            if (config.showButton) {
                button.style.display = 'block';
                setTimeout(() => { button.style.opacity = '1'; }, 10);
            } else {
                button.style.opacity = '0';
                setTimeout(() => { button.style.display = 'none'; }, 300);
            }
        } else if (config.showButton && shouldShowButton()) {
            createJumpButton();
        }
    }

    // 打开设置界面
    function openSettings() {
        const settings = `
            <div style="padding:10px;font-family:Arial,sans-serif;max-width:500px">
                <h3>Bangumi跳转脚本设置</h3>
                <label style="display:block;margin:10px 0">
                    <input type="checkbox" ${config.showButton ? 'checked' : ''}
                           id="showButtonCheckbox">
                    显示右下角"查看详情"按钮
                </label>
                <h4>排除网站:</h4>
                ${Object.keys(siteSelectors).map(domain => `
                    <label style="display:block;margin:5px 0">
                        <input type="checkbox" ${config.excludedSites.includes(domain) ? 'checked' : ''}
                               class="excludeCheckbox" data-domain="${domain}">
                        ${domain}
                    </label>
                `).join('')}
            </div>
            <script>
                document.getElementById('showButtonCheckbox').addEventListener('change', function() {
                    window.opener.postMessage({
                        type: 'updateShowButton',
                        value: this.checked
                    }, '*');
                });

                document.querySelectorAll('.excludeCheckbox').forEach(checkbox => {
                    checkbox.addEventListener('change', function() {
                        window.opener.postMessage({
                            type: 'updateExcludedSite',
                            domain: this.dataset.domain,
                            value: this.checked
                        }, '*');
                    });
                });
            </script>
        `;

        const win = window.open('', '_blank', 'width=500,height=400');
        win.document.write(settings);

        // 监听设置窗口的消息
        window.addEventListener('message', function(event) {
            if (event.data.type === 'updateShowButton') {
                config.showButton = event.data.value;
                GM_setValue('showButton', config.showButton);
                toggleButton(); // 直接调用切换函数更新按钮状态
            } else if (event.data.type === 'updateExcludedSite') {
                const excluded = GM_getValue('excludedSites', []);
                if (event.data.value && !excluded.includes(event.data.domain)) {
                    excluded.push(event.data.domain);
                } else {
                    const index = excluded.indexOf(event.data.domain);
                    if (index > -1) excluded.splice(index, 1);
                }
                GM_setValue('excludedSites', excluded);
                config.excludedSites = excluded;

                // 检查当前站点是否被排除
                const button = document.querySelector('#bangumiJumpButton');
                if (button) {
                    if (shouldShowButton()) {
                        button.style.display = 'block';
                        setTimeout(() => { button.style.opacity = '1'; }, 10);
                    } else {
                        button.style.opacity = '0';
                        setTimeout(() => { button.style.display = 'none'; }, 300);
                    }
                }
            }
        });
    }

    // 判断是否显示按钮
    function shouldShowButton() {
        // 如果全局关闭按钮或当前站点被排除
        if (!config.showButton || config.excludedSites.includes(window.location.hostname)) {
            return false;
        }

        const path = window.location.pathname;
        return (
            (window.location.hostname === 'www.mutean.com' && path.includes('/vodplay')) ||
            (window.location.hostname === 'www.aafun.cc' && path.includes('/f')) ||
            (window.location.hostname === 'www.cycani.org' && path.includes('/watch')) ||
            (window.location.hostname === 'www.agedm.vip' && path.includes('/play')) ||
            (window.location.hostname === 'www.ntdm8.com' && path.includes('/play')) ||
            (window.location.hostname === 'www.mwcy.net' && path.includes('/play')) ||
            (window.location.hostname === 'dm.xifanacg.com' && path.includes('/watch')) ||
            (window.location.hostname === 'www.bilibili.com' && path.includes('/play')) ||
            (window.location.hostname === 'anich.emmmm.eu.org' && path.includes('/b')) ||
            !!getAnimeTitle()
        );
    }

    // 获取动画标题
    function getAnimeTitle() {
        const domain = window.location.hostname;
        const selector = siteSelectors[domain];

        if (!selector) {
            console.warn(`当前网站 ${domain} 未配置标题选择器`);
            return null;
        }

        const titleElement = document.querySelector(selector);
        if (titleElement) {
            let title = titleElement.textContent.trim();
            title = title.replace(/^【.+?】/, '')
                        .replace(/^《|》$/g, '')
                        .replace(/^"|"$/g, '')
                        .trim();
            return title;
        }
        return null;
    }

    // 使用Bangumi API获取动画ID
    function getBangumiId(title) {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: "GET",
                url: `https://api.bgm.tv/search/subject/${encodeURIComponent(title)}?type=2&responseGroup=small`,
                headers: {
                    "User-Agent": "Mozilla/5.0 (BangumiScript)"
                },
                onload: function(response) {
                    try {
                        const data = JSON.parse(response.responseText);
                        if (data.list && data.list.length > 0) {
                            resolve(data.list[0].id);
                        } else {
                            reject('未找到匹配的动画');
                        }
                    } catch (e) {
                        reject('解析API响应失败');
                    }
                },
                onerror: function(error) {
                    reject('API请求失败');
                }
            });
        });
    }

    // 跳转到Bangumi详情页
    async function jumpToBangumi() {
        const animeTitle = getAnimeTitle();
        if (!animeTitle) {
            alert('无法获取动画标题');
            return;
        }

        try {
            const subjectId = await getBangumiId(animeTitle);
            window.open(`https://bgm.tv/subject/${subjectId}`, '_blank');
            console.log(`跳转到Bangumi详情页: ${animeTitle}`);
        } catch (error) {
            console.warn(`直接跳转失败: ${error}, 改用搜索页`);
            const encodedTitle = encodeURIComponent(animeTitle);
            window.open(`https://bgm.tv/subject_search/${encodedTitle}?cat=2`, '_blank');
        }
    }

    // 跳转到Bangumi搜索页(右击功能)
    function jumpToBangumiSearch() {
        const animeTitle = getAnimeTitle();
        if (!animeTitle) {
            alert('无法获取动画标题');
            return;
        }
        const encodedTitle = encodeURIComponent(animeTitle);
        window.open(`https://bgm.tv/subject_search/${encodedTitle}?cat=2`, '_blank');
        console.log(`跳转到Bangumi搜索页: ${animeTitle}`);
    }

    // 创建右下角按钮
    function createJumpButton() {
        if (!shouldShowButton()) return;

        const button = document.createElement('button');
        button.id = 'bangumiJumpButton';
        button.textContent = '查看详情';
        button.style.position = 'fixed';
        button.style.bottom = '20px';
        button.style.right = '20px';
        button.style.zIndex = '9999';
        button.style.padding = '8px 16px';
        button.style.backgroundColor = '#1E88E5';
        button.style.color = 'white';
        button.style.border = 'none';
        button.style.borderRadius = '4px';
        button.style.cursor = 'pointer';
        button.style.fontSize = '14px';
        button.style.fontWeight = '500';
        button.style.boxShadow = '0 2px 10px rgba(0,0,0,0.2)';
        button.style.transition = 'all 0.3s ease';
        button.style.opacity = config.showButton ? '1' : '0';
        button.style.display = config.showButton ? 'block' : 'none';

        // 添加title属性用于悬停提示
        button.title = '搜索错误时右击';

        // 悬停效果
        button.addEventListener('mouseover', () => {
            button.style.backgroundColor = '#1565C0';
            button.style.transform = 'translateY(-2px)';
        });
        button.addEventListener('mouseout', () => {
            button.style.backgroundColor = '#1E88E5';
            button.style.transform = 'translateY(0)';
        });

        // 左键点击事件
        button.addEventListener('click', jumpToBangumi);

        // 右键点击事件
        button.addEventListener('contextmenu', (e) => {
            e.preventDefault();
            jumpToBangumiSearch();
        });

        document.body.appendChild(button);
    }

    // 键盘事件处理
    function handleKeyPress(e) {
        const isShiftF8 = (e.key === 'F8' && e.shiftKey) ||
                         (e.keyCode === 119 && e.shiftKey);
        if (isShiftF8) {
            e.preventDefault();
            e.stopPropagation();
            jumpToBangumi();
            return false;
        }
    }

    // 添加键盘监听
    function addKeyListener() {
        document.addEventListener('keydown', handleKeyPress);
        window.addEventListener('keydown', handleKeyPress);
    }

    // 主函数
    function main() {
        addKeyListener();
        if (shouldShowButton()) {
            createJumpButton();
        }
        console.log('Bangumi跳转脚本已加载',
                   config.showButton ? '按钮已启用' : '按钮已禁用');
    }

    // 页面加载完成后初始化
    if (document.readyState === 'complete') {
        main();
    } else {
        window.addEventListener('load', main);
    }
})();