您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
在进入B站直播间的时候自动切换到正确的粉丝勋章(减少尴尬之类的)
// ==UserScript== // @name B站直播间自动切换粉丝牌 // @namespace http://shenhaisu.cc/ // @version 1.1 // @description 在进入B站直播间的时候自动切换到正确的粉丝勋章(减少尴尬之类的) // @author ShenHaiSu // @match https://live.bilibili.com/* // @grant unsafeWindow // @run-at document-end // @license MIT // @noframes // ==/UserScript== (async function () { let pluginConfig = { // 进入没有粉丝牌的直播间是否取消佩戴粉丝勋章 // false 不拥有本直播间的粉丝牌,但是也不会摘下已经装备的粉丝牌 // true 会摘下当前粉丝牌 autoTakeOff: true, // 粉丝牌检测延迟 默认3000ms(毫秒) = 3s(秒) // 在进入直播间之后等待指定的延迟,再开始检测是否需要自动更换粉丝牌 startDelay: 3000, // DEBUG模式,出现错误会使用弹窗强行提示,非使用者不要打开 debug: false, }; console.log("B站直播间进入自动切换粉丝勋章开始运行"); setTimeout(function () { mainFunc(pluginConfig); }, pluginConfig.startDelay); })(); function mainFunc(pluginConfig) { let APIList = { nowWeared: "https://api.live.bilibili.com/live_user/v1/UserInfo/get_weared_medal", // POST source uid target_id csrf_token csrf visit_id:"" getMedal: "https://api.live.bilibili.com/xlive/app-ucenter/v1/fansMedal/panel?", // GET page=1 page_size=20 target_id takeOff: "https://api.live.bilibili.com/xlive/web-room/v1/fansMedal/take_off", // POST csrf_token csrf visit_id:"" wearMedal: "https://api.live.bilibili.com/xlive/web-room/v1/fansMedal/wear", // POST medal_id csrf_token csrf visit_id:"" }; let userID = getUserUID(); let targetID = getSteamerUID(); let userCSRF = getSCRF(); let streamerName = getStreamerName(); let targetMedal = null; let nowWearedFlag = false; function getUserUID() { let userid = getCookie()['DedeUserID'] || undefined; return userid; } function getSteamerUID() { return document.getElementsByTagName("iframe")[0].src.match(/ruid=\d+/)[0].split("=")[1]; } function getCookie() { let documentCookie = document.cookie.split("; "); let output = {}; documentCookie.forEach(item => { let tempObj = item.split("="); output[tempObj[0]] = tempObj[1]; }); return output; } function getStreamerName() { return document.getElementsByClassName("room-owner-username")[0].innerText; } function getSpecialMedalOwner(payload) { return payload['anchor_info']['nick_name'] || undefined; } function getMedalID(payload) { return payload['medal']['medal_id'] || undefined; } function getSCRF() { let cookieObj = getCookie(); return cookieObj['bili_jct'] || undefined; } function sendTakeOff() { fetch(APIList.takeOff, { method: "post", headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `csrf_token=${userCSRF}&csrf=${userCSRF}&visit_id=`, credentials: "include" }).then(async response => { let respData = response.json(); updateDisplay(); if (respData.code !== 0) return Promise.reject(); }).catch(() => { if (pluginConfig.debug) alert("脱下粉丝牌失败."); }); } function sendWearMedal() { fetch(APIList.wearMedal, { method: "post", headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `medal_id=${getMedalID(targetMedal)}&csrf_token=${userCSRF}&csrf=${userCSRF}&visit_id=`, credentials: "include" }).then(async response => { let respData = await response.json(); updateDisplay(); if (respData.code !== 0) return Promise.reject(); }).catch(() => { if (pluginConfig.autoTakeOff) alert("切换佩戴粉丝牌失败."); }); } function updateDisplay() { document.querySelector("div.medal-section").children[0].click(); setTimeout(() => { document.querySelector("div.medal-section").children[0].click(); }, 500); } if (!userID || !userCSRF) return; if (pluginConfig.debug) { console.log("=".repeat(10) + "DEBUG模式显示" + "=".repeat(10)); console.log(`用户UID ${userID}`); console.log(`主播UID ${targetID}`); console.log(`用户SCRF ${userCSRF}`); console.log(`主播用户名 ${streamerName}`); console.log("=".repeat(10) + "DEBUG模式显示" + "=".repeat(10)); } fetch(APIList.nowWeared, { method: "post", headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `source=1&uid=${userID}&target_id=${targetID}&csrf_token=${userCSRF}&csrf=${userCSRF}&visit_id=`, credentials: "include" }).then(async response => { let respData = await response.json(); nowWearedFlag = !!respData.length || !!respData.data['medal_name']; return await fetch(`${APIList.getMedal}page=1&page_size=20&target_id=${targetID}`, { method: "get", credentials: "include" }); }).then(async response => { let respData = await response.json(); let special_list = respData['data']['special_list'] let specialLength = special_list.length; if (pluginConfig.debug) { console.log(respData); console.log(special_list); console.log(specialLength); } if (!nowWearedFlag && specialLength === 0) { return; } else if (!nowWearedFlag && specialLength === 1) { targetMedal = special_list[0]; sendWearMedal(); } else if (nowWearedFlag && specialLength === 1) { let wearedMedalOwnerName = getSpecialMedalOwner(special_list[0]); if (wearedMedalOwnerName === streamerName) { return; } else if (pluginConfig.autoTakeOff) { sendTakeOff(); } else return; } else if (nowWearedFlag && specialLength === 2) { targetMedal = special_list[1]; sendWearMedal(); } }) }