// ==UserScript==
// @name B站用户成分标签
// @namespace lycoris
// @version 1.1
// @description B站评论区根据用户动态成分添加标签(根据 新·三相之力指示器,原神指示器 修改制作)
// @author Lemonades
// @match https://www.bilibili.com/video/*
// @icon https://static.hdslb.com/images/favicon.ico
// @connect bilibili.com
// @grant GM_xmlhttpRequest
// @license MIT
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
// 脚本刷新时间(推荐在10s左右) 单位:ms
const refreshTime = 10000;
// tag中设置或添加成分标签字典,可自定义 标签(tag),内容(text),关键词筛选正则(reg),标签颜色(color),隐藏评论(hide)
// 关键词正则 reg,可自定义(增加关键词用 | 分隔),关键词不要缩写和省略,防止误伤
const tag = [
{ tag: '游戏', text: '原神', reg: '原神|米哈游', color: '#6600CC', hide: false },
{ tag: '游戏', text: '方舟', reg: '明日方舟', color: '#6600CC', hide: false },
{ tag: '游戏', text: '农药', reg: '王者荣耀', color: '#6600CC', hide: false },
{ tag: 'Vtuber', text: '嘉心糖', reg: '嘉然', color: '#946845', hide: false },
{ tag: 'Vtuber', text: '雏草姬', reg: '塔菲', color: '#946845', hide: false },
{ tag: 'Vtuber', text: '杰尼', reg: '七海', color: '#946845', hide: false },
{ tag: 'Vtuber', text: '喵喵露', reg: '猫雷', color: '#946845', hide: false }
];
const blog = 'https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space?&host_mid=';
const is_new = document.getElementsByClassName('item goback').length != 0; // 检测是不是新版
// 网页头部插入标签样式
const tag_style = document.createElement('style');
tag_style.innerHTML = `
.userTag{
display: inline-block;
position: relative;
text-align: center;
border-width: 0px;
vertical-align: middle;
margin-left: 8px;
}
.tag-text{
border-color:rgba(169, 195, 233, 0.1803921568627451);
color:rgba(87, 127, 184, 1);
background-image: linear-gradient(90deg, rgba(158, 186, 232, 0.2), rgba(158, 186, 232, 0.2));
float: left;
text-align: center;
height: 12px;
line-height: 12px;
border-width: 0.5px;
border-style: solid;
border-bottom-left-radius: 1px;
border-top-left-radius: 1px;
}
.tag-font{
width: 200%;
height: 200%;
font-weight: 400;
transform-origin: center;
transform: scale(0.5) translate(-50%, -50%);
font-size: 20px;
line-height: 24px;
}
.tag-name{
position: relative;
border-bottom-right-radius: 1px;
border-top-right-radius: 1px;
float: left;
box-sizing: content-box;
text-align: center;
height: 12px;
line-height: 12px;
border-width: 0.5px;
border-color: #f25d8e;
border-style: solid;
border-bottom-left-radius: 1px;
border-top-left-radius: 1px;
color: #f25d8e;
}`;
document.querySelector('head').appendChild(tag_style);
// 标签
class Tag {
constructor(tag_dic) {
this.tag = tag_dic.tag;
this.text = tag_dic.text;
this.tagReg = new RegExp(tag_dic.text);
this.reg = new RegExp(tag_dic.reg);
this.hide = tag_dic.hide;
this.color = tag_dic.color;
this.width = tag_dic.text.length * 10 + 5;
this.tag_width = RegExp('[A-Za-z0-9]').test(this.tag) ? this.tag.length * 5 + 5 : this.tag.length * 10 + 5;
this.list = new Set();
this.nolist = new Set();
this.inner = `<div class='userTag'><div class='tag-name' style='border-color:#8da8e8;color:#5e80c4; width:${this.tag_width}px'><div class='tag-font'>${this.tag}</div></div>
<div class='tag-text' style='color: ${this.color}; width:${this.width}px;'><div class='tag-font'>${this.text}</div></div></div>`;
};
// 检查列表中是否存在该用户 pid
check(pid, c) {
if (this.list.has(pid)) {
if (this.hide) {
if (is_new) {
if (c.classList.contains('user-name')) {
c.parentElement.nextSibling.children[0].innerText = '评论已屏蔽';
} else {
c.parentElement.nextSibling.innerText = '评论已屏蔽';
}
} else {
if (c.querySelector('.text-con')) {
c.querySelector('.text-con').innerText = '评论已屏蔽';
} else {
c.nextSibling.innerText = '评论已屏蔽';
}
}
}
if (!this.tagReg.test(c.textContent)) {
c.innerHTML += this.inner;
}
return true;
} else if (this.nolist.has(pid)) {
return true;
}
};
// 检测用户标签
detect(st, c, pid) {
//添加标签
if (this.reg.test(st)) {
if (this.hide) {
if (is_new) {
if (c.classList.contains('user-name')) {
c.parentElement.nextSibling.children[0].innerText = '评论已屏蔽';
} else {
c.parentElement.nextSibling.innerText = '评论已屏蔽';
}
} else {
if (c.querySelector('.text-con')) {
c.querySelector('.text-con').innerText = '评论已屏蔽';
} else {
c.nextSibling.innerText = '评论已屏蔽';
}
}
}
c.innerHTML += this.inner;
this.list.add(pid);
} else {
this.nolist.add(pid);
}
};
}
// 标签列表
class TagList {
constructor() {
this.list = [];
}
push(tag) {
this.list.push(tag);
}
check(pid, c) {
for (let i of this.list) {
let a = i.check(pid, c);
if (a) {
return true;
}
}
}
detect(st, c, pid) {
this.list.map(i => i.detect(st, c, pid));
}
}
// 获取用户 id
const getPid = (c) => {
if (is_new) {
return c.dataset.userId;
} else {
return c.querySelector('.name').getAttribute('data-usercard-mid') || c.children[0].href.replace(/[^\d]/g, "");
}
};
// 获取评论列表
const getCommentList = () => {
if (is_new) {
return document.querySelectorAll('.user-name,.sub-user-name');
} else {
return document.querySelectorAll('.user');
}
};
// 成分检测(刷新评论,检测、屏蔽标签)
const IngredientDetection = () => {
let commentlist = getCommentList();
if (commentlist.length != 0) {
commentlist.forEach(c => {
// 检测标签列表中是否含有该用户id
let pid = getPid(c);
let a = tag_list.check(pid, c);
if (a) {
return;
}
// 标签列表中不含该用户 id
// 获取该用户近期动态内容
let blogurl = blog + pid;
GM_xmlhttpRequest({
method: "get",
url: blogurl,
data: '',
headers: {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
},
onload: function(res) {
if (res.status === 200) {
let st = JSON.stringify(JSON.parse(res.response).data);
tag_list.detect(st, c, pid)
} else {
console.log('加载用户信息失败');
console.log(res);
}
},
});
});
}
};
// 初始化标签列表
const tag_list = new TagList();
tag.map(i => tag_list.push(new Tag(i)));
IngredientDetection();
// 设置定时检测
setInterval(() => {
let btns = document.querySelectorAll('.btn-more,.paging-box,.view-more-pagination,.view-more-btn');
for (let btn of btns) {
btn.onclick = () => {
setTimeout(() => {
IngredientDetection();
}, 500);
}
}
IngredientDetection();
}, refreshTime);
console.log('%c成分查询脚本已加载', 'color: #43bb88; font-size: 12px; font-weight: bolder');
})();