B站直播间自动切换粉丝牌

在进入B站直播间的时候自动切换到正确的粉丝勋章(减少尴尬之类的)

  1. // ==UserScript==
  2. // @name B站直播间自动切换粉丝牌
  3. // @namespace http://shenhaisu.cc/
  4. // @version 1.1
  5. // @description 在进入B站直播间的时候自动切换到正确的粉丝勋章(减少尴尬之类的)
  6. // @author ShenHaiSu
  7. // @match https://live.bilibili.com/*
  8. // @grant unsafeWindow
  9. // @run-at document-end
  10. // @license MIT
  11. // @noframes
  12. // ==/UserScript==
  13.  
  14. (async function () {
  15. let pluginConfig = {
  16. // 进入没有粉丝牌的直播间是否取消佩戴粉丝勋章
  17. // false 不拥有本直播间的粉丝牌,但是也不会摘下已经装备的粉丝牌
  18. // true 会摘下当前粉丝牌
  19. autoTakeOff: true,
  20. // 粉丝牌检测延迟 默认3000ms(毫秒) = 3s(秒)
  21. // 在进入直播间之后等待指定的延迟,再开始检测是否需要自动更换粉丝牌
  22. startDelay: 3000,
  23. // DEBUG模式,出现错误会使用弹窗强行提示,非使用者不要打开
  24. debug: false,
  25. };
  26. console.log("B站直播间进入自动切换粉丝勋章开始运行");
  27. setTimeout(function () {
  28. mainFunc(pluginConfig);
  29. }, pluginConfig.startDelay);
  30. })();
  31.  
  32. function mainFunc(pluginConfig) {
  33. let APIList = {
  34. nowWeared: "https://api.live.bilibili.com/live_user/v1/UserInfo/get_weared_medal", // POST source uid target_id csrf_token csrf visit_id:""
  35. getMedal: "https://api.live.bilibili.com/xlive/app-ucenter/v1/fansMedal/panel?", // GET page=1 page_size=20 target_id
  36. takeOff: "https://api.live.bilibili.com/xlive/web-room/v1/fansMedal/take_off", // POST csrf_token csrf visit_id:""
  37. wearMedal: "https://api.live.bilibili.com/xlive/web-room/v1/fansMedal/wear", // POST medal_id csrf_token csrf visit_id:""
  38. };
  39. let userID = getUserUID();
  40. let targetID = getSteamerUID();
  41. let userCSRF = getSCRF();
  42. let streamerName = getStreamerName();
  43. let targetMedal = null;
  44. let nowWearedFlag = false;
  45. function getUserUID() {
  46. let userid = getCookie()['DedeUserID'] || undefined;
  47. return userid;
  48. }
  49. function getSteamerUID() {
  50. return document.getElementsByTagName("iframe")[0].src.match(/ruid=\d+/)[0].split("=")[1];
  51. }
  52. function getCookie() {
  53. let documentCookie = document.cookie.split("; ");
  54. let output = {};
  55. documentCookie.forEach(item => {
  56. let tempObj = item.split("=");
  57. output[tempObj[0]] = tempObj[1];
  58. });
  59. return output;
  60. }
  61. function getStreamerName() {
  62. return document.getElementsByClassName("room-owner-username")[0].innerText;
  63. }
  64. function getSpecialMedalOwner(payload) {
  65. return payload['anchor_info']['nick_name'] || undefined;
  66. }
  67. function getMedalID(payload) {
  68. return payload['medal']['medal_id'] || undefined;
  69. }
  70. function getSCRF() {
  71. let cookieObj = getCookie();
  72. return cookieObj['bili_jct'] || undefined;
  73. }
  74. function sendTakeOff() {
  75. fetch(APIList.takeOff, {
  76. method: "post",
  77. headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  78. body: `csrf_token=${userCSRF}&csrf=${userCSRF}&visit_id=`,
  79. credentials: "include"
  80. }).then(async response => {
  81. let respData = response.json();
  82. updateDisplay();
  83. if (respData.code !== 0) return Promise.reject();
  84. }).catch(() => {
  85. if (pluginConfig.debug) alert("脱下粉丝牌失败.");
  86. });
  87. }
  88. function sendWearMedal() {
  89. fetch(APIList.wearMedal, {
  90. method: "post",
  91. headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  92. body: `medal_id=${getMedalID(targetMedal)}&csrf_token=${userCSRF}&csrf=${userCSRF}&visit_id=`,
  93. credentials: "include"
  94. }).then(async response => {
  95. let respData = await response.json();
  96. updateDisplay();
  97. if (respData.code !== 0) return Promise.reject();
  98. }).catch(() => {
  99. if (pluginConfig.autoTakeOff) alert("切换佩戴粉丝牌失败.");
  100. });
  101. }
  102. function updateDisplay() {
  103. document.querySelector("div.medal-section").children[0].click();
  104. setTimeout(() => {
  105. document.querySelector("div.medal-section").children[0].click();
  106. }, 500);
  107. }
  108. if (!userID || !userCSRF) return;
  109. if (pluginConfig.debug) {
  110. console.log("=".repeat(10) + "DEBUG模式显示" + "=".repeat(10));
  111. console.log(`用户UID ${userID}`);
  112. console.log(`主播UID ${targetID}`);
  113. console.log(`用户SCRF ${userCSRF}`);
  114. console.log(`主播用户名 ${streamerName}`);
  115. console.log("=".repeat(10) + "DEBUG模式显示" + "=".repeat(10));
  116. }
  117. fetch(APIList.nowWeared, {
  118. method: "post",
  119. headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  120. body: `source=1&uid=${userID}&target_id=${targetID}&csrf_token=${userCSRF}&csrf=${userCSRF}&visit_id=`,
  121. credentials: "include"
  122. }).then(async response => {
  123. let respData = await response.json();
  124. nowWearedFlag = !!respData.length || !!respData.data['medal_name'];
  125. return await fetch(`${APIList.getMedal}page=1&page_size=20&target_id=${targetID}`, {
  126. method: "get",
  127. credentials: "include"
  128. });
  129. }).then(async response => {
  130. let respData = await response.json();
  131. let special_list = respData['data']['special_list']
  132. let specialLength = special_list.length;
  133. if (pluginConfig.debug) {
  134. console.log(respData);
  135. console.log(special_list);
  136. console.log(specialLength);
  137. }
  138. if (!nowWearedFlag && specialLength === 0) {
  139. return;
  140. } else if (!nowWearedFlag && specialLength === 1) {
  141. targetMedal = special_list[0];
  142. sendWearMedal();
  143. } else if (nowWearedFlag && specialLength === 1) {
  144. let wearedMedalOwnerName = getSpecialMedalOwner(special_list[0]);
  145. if (wearedMedalOwnerName === streamerName) {
  146. return;
  147. } else if (pluginConfig.autoTakeOff) {
  148. sendTakeOff();
  149. } else return;
  150. } else if (nowWearedFlag && specialLength === 2) {
  151. targetMedal = special_list[1];
  152. sendWearMedal();
  153. }
  154. })
  155. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址