Bilibili Comment UID Reader

Read UIDs from Bilibili comments

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Bilibili Comment UID Reader
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Read UIDs from Bilibili comments
// @author       You
// @match        *https://www.bilibili.com/video*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
const sidebarCss = `
#customSidebar {
    position: fixed;
    top: 50%;
    left: 0;
    transform: translateY(-50%);
    z-index: 1000;
    background-color: white;
    padding: 10px;
    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
    display: flex;
    flex-direction: column;
}
`;

const styleElement = document.createElement('style');
styleElement.type = 'text/css';
styleElement.appendChild(document.createTextNode(sidebarCss));
document.head.appendChild(styleElement);

const sidebar = document.createElement('div');
sidebar.id = 'customSidebar';
document.body.appendChild(sidebar);

const displayUsersBtn = document.createElement('button');
displayUsersBtn.innerText = '显示所有用户及其组别';
displayUsersBtn.onclick = displayAllUsersAndGroups;
sidebar.appendChild(displayUsersBtn);
sidebar.appendChild(document.createElement('br')); 

const clearGroupsBtn = document.createElement('button');
clearGroupsBtn.innerText = '清除所有组';
clearGroupsBtn.onclick = function() { clearSpecificGroup(null); };
sidebar.appendChild(clearGroupsBtn);
sidebar.appendChild(document.createElement('br'));

const clearAllBtn = document.createElement('button');
clearAllBtn.innerText = '完全清除';
clearAllBtn.onclick = clearAllData;
sidebar.appendChild(clearAllBtn);
    const observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        mutation.addedNodes.forEach(function(node) {
            if (node.nodeType === 1 && node.classList.contains('user-info')) {
                addSpecialAttentionButton(node.querySelector('.user-name'));
            }
            else if (node.nodeType === 1) {
const userInfoElements = node.querySelectorAll('.user-info .user-name');
userInfoElements.forEach(userInfoElement => {
    const userId = userInfoElement.getAttribute('data-user-id');
    const userName = userInfoElement.textContent;
    addSpecialAttentionButton(userInfoElement, userId, userName);
});
            }
        });
    });
});

observer.observe(document.body, { childList: true, subtree: true });
    function addSpecialAttentionButton(userInfoElement, userId, userName) {
    const { currentGroupName } = getUserCurrentGroup(userId);

    let groupIndicator;
    if (currentGroupName) {
        groupIndicator = document.createElement('span');
        groupIndicator.textContent = `组别: ${currentGroupName}`;
        groupIndicator.style.border = '1px solid black';
        groupIndicator.style.padding = '2px';
        userInfoElement.parentNode.insertBefore(groupIndicator, userInfoElement.nextSibling);
    }
    const buttonText = currentGroupName ? '更改关注组' : '特别关注';
    const specialAttentionButton = document.createElement('button');
    specialAttentionButton.textContent = buttonText;
    userInfoElement.parentNode.appendChild(specialAttentionButton);

    specialAttentionButton.addEventListener('click', function() {
const groupSelect = document.getElementById('group-select-' + userId);
        if (groupSelect && groupSelect.style.display !== 'none') {
            const groupName = groupSelect.value;
            if (groupName) {
                addUserToGroup(userId, userName, groupName);
                groupSelect.style.display = 'none';
                document.getElementById('new-group-input-' + userId).style.display = 'none';
                document.getElementById('add-group-btn-' + userId).style.display = 'none';
            } else {
                alert('请选择一个组,或创建一个新组!');
            }
        } else {
            showGroupSelect(userInfoElement, userId, userName);
        }
        if (groupIndicator) {
            groupIndicator.textContent = `组别: ${groupSelect.value}`;
        }
    });
}
function getUserCurrentGroup(userId) {
    const groups = JSON.parse(localStorage.getItem('userGroups')) || {};
    for (const [groupName, users] of Object.entries(groups)) {
        const userInGroup = users.find(user => user.userId === userId);
        if (userInGroup) {
            return { currentGroupName: groupName };
        }
    }
    return { currentGroupName: null };
}

function updateGroupSelect(select) {
    const groups = JSON.parse(localStorage.getItem('userGroups')) || {};
    select.innerHTML = '<option value="">请选择一个组...</option>';
    select.innerHTML += '<option value="无组别">无组别</option>';

    Object.keys(groups).forEach(groupName => {
        const option = document.createElement('option');
        option.value = groupName;
        option.textContent = groupName;
        select.appendChild(option);
    });
}

function showGroupSelect(userNameDiv, userId, userName) {
    let existingSelect = document.getElementById('group-select-' + userId);
    if (existingSelect) {

        return;
    }

    let select = document.getElementById('group-select-' + userId) || document.createElement('select');
    select.id = 'group-select-' + userId;
    select.style.display = ''; 

    let newGroupInput = document.getElementById('new-group-input-' + userId) || document.createElement('input');
    newGroupInput.id = 'new-group-input-' + userId;
    newGroupInput.style.display = '';

    let addGroupBtn = document.getElementById('add-group-btn-' + userId);
if (!addGroupBtn) {
    addGroupBtn = document.createElement('button');
    addGroupBtn.id = 'add-group-btn-' + userId;
    addGroupBtn.textContent = '新增组类别'; 
    userNameDiv.parentNode.appendChild(addGroupBtn); 
}
addGroupBtn.style.display = ''; 
    updateGroupSelect(select);
    userNameDiv.parentNode.appendChild(select);
    userNameDiv.parentNode.appendChild(newGroupInput);
    userNameDiv.parentNode.appendChild(addGroupBtn);
    addGroupBtn.addEventListener('click', function() {
        const newGroupName = newGroupInput.value.trim();
        if (newGroupName) {
            addNewGroup(newGroupName);
            newGroupInput.value = '';
            updateGroupSelect(select);
        } else {
            alert('组名不能为空!');
        }
    });
}

function addNewGroup(groupName) {
    const groups = JSON.parse(localStorage.getItem('userGroups')) || {};
    if (groups[groupName]) {
        alert('该组已存在!');
        return;
    }
    groups[groupName] = [];
    localStorage.setItem('userGroups', JSON.stringify(groups));
    alert(`新组 "${groupName}" 已成功创建。`);
}
function displayAllUsersAndGroups() {
    const groups = JSON.parse(localStorage.getItem('userGroups')) || {};
    let message = '所有用户及其组别:\n';

    for (const [groupName, users] of Object.entries(groups)) {
        users.forEach(({ userId, userName }) => { 
            message += `用户名: ${userName}, 用户ID: ${userId}, 组别: ${groupName}\n`;
        });
    }

    alert(message);
}

    function clearAllData() {
    const isConfirmed = confirm("确定要完全清除所有数据吗?这将包括所有用户的特别关注组信息。");

    if (isConfirmed) {
        localStorage.removeItem('userGroups');
        alert("所有数据已被成功清除。");
    }
}
function addUserToGroup(userId, userName, groupName) {
    const groups = JSON.parse(localStorage.getItem('userGroups')) || {};
    Object.keys(groups).forEach(group => {
        groups[group] = groups[group].filter(user => user.userId !== userId);
    });
    if (groupName !== "无组别") {
        if (!groups[groupName]) {
            groups[groupName] = [];
        }
        const isUserInGroup = groups[groupName].some(user => user.userId === userId);
        if (!isUserInGroup) {
            groups[groupName].push({ userId, userName });
        }
    }
    localStorage.setItem('userGroups', JSON.stringify(groups));
    alert(`用户 ${userName} (${userId}) 的组别已更新。`);
}

    function clearSpecificGroup(groupNameToClear) {
    const groups = JSON.parse(localStorage.getItem('userGroups')) || {};
    if (groupNameToClear && groups[groupNameToClear]) {
        if (!groups['臨時組']) groups['臨時組'] = [];
        groups['臨時組'] = groups['臨時組'].concat(groups[groupNameToClear]);
        delete groups[groupNameToClear];
    } else if (!groupNameToClear) {
        groups['臨時組'] = [];
        for (const groupName in groups) {
            if (groupName !== '臨時組') {
                groups['臨時組'] = groups['臨時組'].concat(groups[groupName]);
                delete groups[groupName];
            }
        }
    }

    localStorage.setItem('userGroups', JSON.stringify(groups));
    displayAllUsersAndGroups();
}
document.getElementById('add-group-btn').addEventListener('click', function() {
    const groupName = document.getElementById('new-group-name').value.trim();
    if (!groupName) {
        alert('關注組名稱不能為空!');
        return;
    }
    const groups = JSON.parse(localStorage.getItem('userGroups')) || {};
    if (groups[groupName]) {
        alert('該關注組已存在!');
        return;
    }
    groups[groupName] = [];
    localStorage.setItem('userGroups', JSON.stringify(groups));
    document.getElementById('new-group-name').value = '';
    updateGroupSelect();
});
    document.getElementById('assign-group-btn').addEventListener('click', function() {
        const uid = document.getElementById('user-uid').value;
        const groupName = document.getElementById('group-select').value;
    });
    updateGroupSelect();
})();