Greasy Fork

Greasy Fork is available in English.

“好友”改为“关注”

将关于好友的描述修改为关注

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         “好友”改为“关注”
// @namespace    https://bgm.tv/group/topic/410150
// @version      0.0.4
// @description  将关于好友的描述修改为关注
// @author       oom
// @match        http*://bgm.tv/
// @match        http*://chii.in/
// @match        http*://bangumi.tv/
// @icon         https://bgm.tv/img/favicon.ico
// @grant        none
// @license      MIT
// @gf           http://greasyfork.icu/zh-CN/scripts/518358
// ==/UserScript==

(function () {
    'use strict';

    // 无限定页面
    // 右上面板
    const userPanela = document.querySelector('#badgeUserPanel a[href$="/friends"]');
    if (userPanela) userPanela.textContent = '关注';
    // 通知
    observeElement('.reply_content.tip', tip => {
        if (tip.textContent === '\n通过了你的好友请求') {
            tip.textContent = '回关了你';
        } else if (tip.textContent === '\n请求与你成为好友') {
            tip.textContent = '关注了你';
        }
    }, { once: false });
    observeElement('.frd_connect .nt_confirm_notify', notify => notify.textContent = '回关', { once: false });
    // 春菜
    observeTextContent('#robot_speech_js', speech => {
        if (speech.textContent === '恭喜恭喜,好友添加成功咯~') {
            speech.textContent = '恭喜恭喜,关注成功咯~';
        } else if (speech.textContent === ' 请稍候...正在添加好友...') {
            speech.textContent = ' 请稍候...正在关注...';
        }
    });
    // 兼容在讨论帖子标记出楼主和好友(https://bgm.tv/dev/app/1075)
    observeElement('.friends-chip', chip => chip.title = '我的关注', { once: false });

    if (location.pathname.match(/\/user\/[^/]+/) ||
        location.pathname.match(/(anime|book|game|music|real)\/list/)) { // 个人页
        const tab = document.querySelector('.navTabs a[href$="/friends"]');
        if (tab) tab.textContent = '关注';
    }

    if (location.pathname.match(/\/user\/[^/]+$/)) { // 个人主页
        const btn = document.querySelector('.chiiBtn:not([href="/settings"]) span');
        const feeds = document.querySelectorAll('.timeline .feed');
        if (btn) btn.textContent = btn.textContent.replace('解除好友', '取消关注').replace('加为好友', '关注');
        feeds.forEach(feed => feed.innerHTML = feed.innerHTML.replace(/将(.+?)加为了好友/, '关注了$1'));

        // 添加好友后当前页面直接出现,故监视
        observeElement('#friend_flag small', flag => flag.textContent = '/ 正在关注');

        replaceFollowingBox('#friend');

        const originalConfirm = window.confirm;
        window.confirm = function (message) {
            // 兼容确认是否添加为好友(https://bgm.tv/dev/app/783)
            // 原组件疑似存在昵称获取错误
            // const newMessage = message.replace(/确定添加(.*?)为好友吗?/, '确定关注$1吗?');
            const newMessage = message.replace(/确定添加(.*?)为好友吗?/, '确定关注吗?')
                .replace('确认从朋友列表中去掉', '确认取消关注');
            return originalConfirm(newMessage);
        }

        // 兼容班固米马赛克瓷砖(https://bgm.tv/group/topic/344198)
        observeElement('.tab_btn[target=relation]', mosaic => mosaic.textContent = '关注');
    } else if (location.pathname.match(/\/user\/[^/]+\/friends$/)) { // 关注列表
        document.title = document.title.replace('的朋友', '的关注列表');

        // 兼容显示/一键删除单向好友(https://bgm.tv/dev/app/1942)
        observeElement('.del-friend span', () => {
            observeTextContent('.del-friend span', del => del.textContent = del.textContent.replace('好友', '关注'));
        });
    } else if (location.pathname.match(/\/user\/[^/]+\/rev_friends$/)) { // 被关注列表
        document.title = document.title.replace(/谁加(.*?)为好友/, '谁关注了$1');
    } else if (location.pathname.match(/\/subject\/\d+$/)) { // 条目页
        const frdScore = document.querySelector('.frdScore');
        if (frdScore) frdScore.innerHTML = frdScore.innerHTML.replace('好友', '关注');

        // 兼容好友看?(https://bgm.tv/dev/app/20)
        observeElement('.SimpleSidePanel', panel => {
            const titlea = panel.querySelector('h2 > a');
            if (!titlea) return;
            titlea.textContent = titlea.textContent.replace('好友', '关注');
        }, { once: false });
    } else if (location.search.includes('filter=friends')) { // 筛选后短评
        document.title = document.title.replace('好友', '关注');
    } else if (location.pathname.match(/\/subject\/\d+\/(wishes|collections|doings|on_hold|dropped)$/)) { // 短评
        const followingOnly = document.querySelector('.chiiBtn[href$="?filter=friends"] span');
        if (followingOnly) followingOnly.textContent = '只看关注';
    } else if (location.pathname.match(/\/user\/[^/]+\/timeline$/)) { // 用户时间胶囊
        const tipa = document.querySelector('.tip_j [href="/timeline"]');
        if (tipa) tipa.textContent = '前往关注列表的时间胶囊';

        replaceTimeline();
    } else if (location.pathname === '/timeline') { // 时间胶囊
        document.title = '关注列表的时间胶囊';

        const h1 = document.querySelector('#header h1');
        h1.textContent = '关注列表的时间胶囊 / 时空管理局';

        replaceTimeline();
        replaceFollowingBox('#columnTimelineB');
    } else if (location.pathname === '/') { // 主页
        replaceTimeline();
    }

    function replaceFollowingBox(parent) {
        const h2 = document.querySelector(`${parent} h2`);
        const followed = document.querySelector(`${parent} .SidePanel > a`);
        if (h2) h2.innerHTML = h2.innerHTML.replace('的朋友', '的关注');
        if (followed) followed.textContent = followed.textContent.replace(/谁加(.*?)为好友/, '谁关注了$1');
    }

    function replaceTimeline() {
        const menua = document.querySelector('#filter_relation span:not([class])');
        if (menua) menua.textContent = '关注';

        observeElement('.tml_item span.info', msg => {
            if (msg.querySelectorAll(`a[href^="${location.origin}/user/"]`).length !== 3) return;
            msg.innerHTML = msg.innerHTML.replace(/将(.+?)加为了好友/, '关注了$1');
        }, { once: false });
    }

    // Copilot
    function observeElement(selector, callback, options = { once: true }) {
        selector = `${selector}:not(.incheijs_edited)`;
        const realCallback = callback;
        callback = function (element) {
            element.classList.add('incheijs_edited');
            return realCallback(element);
        }

        const targetNodes = document.querySelectorAll(selector);
        if (targetNodes.length > 0) {
            targetNodes.forEach(element => callback(element));
            if (options.once) return;
        }

        const config = { childList: true, subtree: true };
        const observer = new MutationObserver((mutationsList, observer) => {
            const detectedTargets = document.querySelectorAll(selector);
            if (detectedTargets[0]) {
                observer.disconnect();
                detectedTargets.forEach(element => {
                    callback(element);
                });
                if (!options.once) observer.observe(document.body, config);
            }
        });

        observer.observe(document.body, config);
    }

    function observeTextContent(selector, callback) {
        const targetNode = document.querySelector(selector);
        if (!targetNode) {
            console.error(`Element not found: ${selector}`);
            return;
        }
        callback(targetNode);

        const config = { characterData: true, childList: true, subtree: true };
        const observer = new MutationObserver((mutationsList, observer) => {
            observer.disconnect();
            for (let mutation of mutationsList) {
                if (mutation.type === 'characterData' || mutation.type === 'childList') {
                    callback(targetNode);
                }
            }
            observer.observe(targetNode, config);
        });

        observer.observe(targetNode, config);
    }
})();