- // ==UserScript==
- // @name 乐子人玩家指示器
- // @version 0.9
- // @description B站视频及动态评论区自动标注各种游戏玩家,依据是动态里是否有各种游戏相关,可自定义关键词,提供给各位乐子人,纯图一乐,默认添加了原神、幻塔、明日方舟等高热度游戏(乐子人角度)
- // @author xulaupuz,trychen,abcd1234564499sc
- // @match https://*.bilibili.com/*
- // @icon https://static.hdslb.com/images/favicon.ico
- // @connect bilibili.com
- // @grant GM_xmlhttpRequest
- // @license GPLv3
- // @run-at document-end
- // @namespace https://gf.qytechs.cn/users/958001
- // ==/UserScript==
-
-
- (function() {
- 'use strict';
- const solvedPid = new Set()
- const solvedDict = {}
- const checkArr = []
- // 添加各种关键词、关注B站号的UID,以及对应标签
- checkArr.push({
- "tag":"原神玩家",
- "keywords":["原神"],
- "followings": [401742377] // 官方号的 UID
- })
- checkArr.push({
- "tag":"幻塔玩家",
- "keywords":["幻塔"],
- "followings": [586631367] // 官方号的 UID
- })
- checkArr.push({
- "tag":"明日方舟玩家",
- "keywords":["明日方舟"],
- "followings": [161775300] // 官方号的 UID
- })
- checkArr.push({
- "tag":"碧蓝航线玩家",
- "keywords":["碧蓝航线"],
- "followings": [233114659] // 官方号的 UID
- })
- checkArr.push({
- "tag":"崩坏三玩家",
- "keywords":["崩坏三","崩坏3"],
- "followings": [27534330] // 官方号的 UID
- })
- checkArr.push({
- "tag":"FGO玩家",
- "keywords":["fgo","fate grand order"],
- "followings": [233108841] // 官方号的 UID
- })
-
- 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 get_pid = (c) => {
- if (is_new) {
- return c.dataset['userId']
- } else {
- return c.children[0]['href'].replace(/[^\d]/g, "")
- }
- }
-
- const get_comment_list = () => {
- let lst = new Set()
- for (let c of document.getElementsByClassName('user-name')) {
- lst.add(c)
- }
- for (let c of document.getElementsByClassName('sub-user-name')) {
- lst.add(c)
- }
- for (let c of document.getElementsByClassName('user')) {
- lst.add(c)
- }
- return lst
- }
-
- const get_tag = (context,checkArr) => {
- context = context.toLowerCase()
- let reTags = new Set()
- checkArr.forEach(checkDict => {
- // 检查动态内容
- if (checkDict.keywords){
- if (checkDict.keywords.find(keyword => context.includes(keyword))) {
- reTags.add(checkDict.tag)
- return
- }
- }
-
- // 检查关注列表
- if (checkDict.followings){
- if (checkDict.followings.find(keyword => context.includes(keyword))) {
- reTags.add(checkDict.tag)
- return
- }
- }
- })
- return reTags
- }
-
- const create_tags = (elem,tags) =>{
- // 动态使用的样式
- let divModelStart = '<div class="true-love" style="width: '
- let divModelMiddle = 'px; padding-left: 2px; padding-right: 0; border-color:rgba(169, 195, 233, 0.1803921568627451); color:rgba(87, 127, 184, 1); background-image: linear-gradient(90deg, rgba(244, 109, 67, 0.2), rgba(244, 109, 67, 0.2))"><div class="tinyfont">'
- let divModelEnd = '</div></div><div class="medal-level" style="border-color:rgba(169, 195, 233, 0.1803921568627451);color:rgba(154, 176, 210, 1) background-image: linear-gradient(90deg, rgba(158, 186, 232, 0.2), rgba(158, 186, 232, 0.2))"><div class="tinyfont">乐</div></div>'
-
- // 视频评论区使用的样式
- let divModelStart2 = '<div class="composition-badge"><span class="composition-name">'
- let divModelEnd2 = '</span></div>'
-
- tags.forEach(tag =>{
- var strLength = tag.length
- var modelLength = 12*strLength
- let divStr
- // 根据父节点判断当前元素类型
- var parentNode = elem.parentNode
- var parentNodeCls = parentNode.className
- let checkContent
- let addNode
- let newNode = document.createElement("div")
- if(parentNodeCls=="user-info"){
- //视频评论区主评论
- divStr = divModelStart2 + tag + divModelEnd2
- checkContent = parentNode.textContent
- addNode = parentNode
- newNode.setAttribute("class","composition-checkable")
- newNode.style="display: inline;"
- newNode.innerHTML = divStr
- } else if(parentNodeCls=="sub-user-info"){
- // 视频评论区评论回复
- divStr = divModelStart2 + tag + divModelEnd2
- checkContent = parentNode.textContent
- addNode = parentNode
- newNode.setAttribute("class","composition-checkable")
- newNode.style="display: inline;"
- newNode.innerHTML = divStr
- } else if(parentNodeCls=="con ") {
- // 动态评论区主评论
- divStr = divModelStart2 + tag + divModelEnd2
- checkContent = parentNode.textContent
- let tmpNodeMain = document.createElement("span")
- tmpNodeMain.style="marging:5px;float:right;"
- var beforeNodeMain = elem.nextSibling
- parentNode.insertBefore(tmpNodeMain,beforeNodeMain)
- addNode = tmpNodeMain
- newNode.setAttribute("class","medal")
- newNode.style="padding-left:0px"
- newNode.innerHTML = divStr
- } else if(parentNodeCls=="reply-con") {
- // 动态评论区评论回复
- divStr = divModelStart + modelLength + divModelMiddle + tag + divModelEnd
- checkContent = elem.textContent
- let tmpNode = document.createElement("span")
- var beforeNode = elem.getElementsByTagName("span")[0]
- elem.insertBefore(tmpNode,beforeNode)
- addNode = tmpNode
- newNode.setAttribute("class","medal")
- newNode.style="padding-left:0px"
- newNode.innerHTML = divStr
- } else {
- // 其他
- console.log(parentNodeCls)
- console.log(elem.textContent)
- }
- if (checkContent.includes(tag) === false) {
- addNode.appendChild(newNode)
- }
- })
- }
-
- console.log(is_new)
-
- console.log("正常加载")
- let jiance = setInterval(()=>{
- let commentlist = get_comment_list()
- if (commentlist.length != 0){
- // clearInterval(jiance)
- commentlist.forEach(c => {
- let pid = get_pid(c)
- if (solvedPid.has(pid)){
- var nowTags = solvedDict[pid]
- create_tags(c,nowTags)
- return
- }
-
- //console.log(pid)
- let blogurl = blog + pid
- // let xhr = new XMLHttpRequest()
- 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){
- //console.log('成功')
- let st = JSON.stringify(JSON.parse(res.response).data)
- let reTags = get_tag(st,checkArr)
- //console.log(reTags)
- create_tags(c,reTags)
- solvedPid.add(pid)
- solvedDict[pid]=reTags
- }else{
- console.log('失败')
- console.log(res)
- }
- },
- });
- });
- }
- }, 4000)
- // 添加标签样式
- addGlobalStyle(`
- .composition-badge {
- display: inline-flex;
- justify-content: center;
- align-items: center;
- width: fit-content;
- background: #00AEEC26;
- border-radius: 10px;
- margin: -6px 0;
- margin: 0 5px;
- font-family: PingFang SC, HarmonyOS_Regular, Helvetica Neue, Microsoft YaHei, sans-serif;
- }
- .composition-name {
- line-height: 13px;
- font-size: 13px;
- color: #00AEEC;
- padding: 2px 8px;
- }
- .composition-icon {
- width: 25px;
- height: 25px;
- border-radius: 50%;
- border: 2px solid white;
- margin: -6px;
- margin-right: 5px;
- }
- `)
-
- function addGlobalStyle(css) {
- var head, style;
- head = document.getElementsByTagName('head')[0];
- if (!head) { return; }
- style = document.createElement('style');
- style.type = 'text/css';
- style.innerHTML = css;
- head.appendChild(style);
- }
- })();