B站直播自动抢红包

进房间自动抢红包,抢完自动取关(需满足条件)

  1. // ==UserScript==
  2. // @name B站直播自动抢红包
  3. // @version 0.2.13
  4. // @description 进房间自动抢红包,抢完自动取关(需满足条件)
  5. // @author Pronax
  6. // @include /https:\/\/live\.bilibili\.com\/(blanc\/)?\d+/
  7. // @icon http://bilibili.com/favicon.ico
  8. // @grant GM_addStyle
  9. // @grant GM_getValue
  10. // @grant GM_setValue
  11. // @grant GM_xmlhttpRequest
  12. // @grant GM_registerMenuCommand
  13. // @grant GM_unregisterMenuCommand
  14. // @connect api.live.bilibili.com
  15. // @run-at document-end
  16. // @noframes
  17. // @require https://greasyfork.org/scripts/434638-xfgryujk-s-bliveproxy/code/xfgryujk's%20bliveproxy.js?version=983438
  18. // @require https://greasyfork.org/scripts/430098-alihesari-s-notice-js-0-4-0/code/alihesari's%20noticejs%20040.js?version=985170
  19. // @require https://greasyfork.org/scripts/439903-blive-room-info-api/code/blive_room_info_api.js?version=1037039
  20. // @namespace https://greasyfork.org/users/412840
  21. // ==/UserScript==
  22.  
  23. // todo 关闭得奖提示后,下次发送的得奖提示会继续使用之前的获奖数量(得奖提示关闭后应该清空计数)
  24. // todo 活动直播间红包第二次不会重新抽取
  25.  
  26. ; (async function () {
  27.  
  28. if (!document.cookie.match(/bili_jct=(\w*); /)) { return; }
  29.  
  30. // 抢红包门槛,只有红包价值大于等于门槛的时候才会抢
  31. // 单位是电池
  32. const doorSill = 0;
  33. // 你可以在这里枚举不想抽取的红包价值,单位是电池
  34. // e.g. const goldBlockEnumList = [16,20,100];
  35. const goldBlockEnumList = [];
  36.  
  37. const RED_PACKET_ICON = "🧧";
  38. const GIFT_ICON = "🎁";
  39. const ROOM_ID = await ROOM_INFO_API.getRid();
  40. const ROOM_USER_ID = await ROOM_INFO_API.getUid();
  41. const FOLLOWED = await getFollowStatus(ROOM_USER_ID);
  42. const Setting = {
  43. get UID() {
  44. return document.cookie.match(/DedeUserID=(\d*); /)[1]
  45. },
  46. get TOKEN() {
  47. let regex = document.cookie.match(/bili_jct=(\w*); /);
  48. return regex && regex[1];
  49. },
  50. get Beijing_date() { // eg. 2022/10/15
  51. return new Date(Setting.Beijing_ts).toLocaleDateString("zh-CN");
  52. },
  53. get Beijing_ts() {
  54. let local = new Date();
  55. let diff = (local.getTimezoneOffset() - Setting.Beijing_timezoneOffset) * 60 * 1000;
  56. return local.valueOf() + diff;
  57. },
  58. get Beijing_timezoneOffset() {
  59. return -480;
  60. }
  61. }
  62. let autoUnfollow = GM_getValue("autoUnfollow", true);
  63. let menuId = undefined;
  64.  
  65. autoUnfollow = !autoUnfollow; // 里面会翻状态,所以先翻一次
  66. autoUnfollowMenu();
  67.  
  68. window.addEventListener('focus', e => {
  69. giftCount = 0;
  70. setTimeout(() => {
  71. updateTabTitle();
  72. }, 1000);
  73. });
  74.  
  75. // 通知css
  76. GM_addStyle(".noticejs-heading{user-select:none}.noticejs-content>span{line-height:20px;font-size:14px}.noticejs-content .currency-icon{margin:-6px -4px 0 0;width:14px;height:14px;display:inline-block;vertical-align:middle;background-size:cover;background-position:center center}.noticejs-content .img{margin-left:15px;width:40px;opacity:1;float:right}.noticejs-content .coin-type{margin-left:-5px}.noticejs-link{margin-right:15px}.noticejs-top{top:0;width:100%!important}.noticejs-top .item{border-radius:0!important;margin:0!important}.noticejs-topRight{top:10px;right:10px}.noticejs-topLeft{top:10px;left:10px}.noticejs-topCenter{top:10px;left:50%;transform:translate(-50%)}.noticejs-middleLeft,.noticejs-middleRight{right:10px;top:50%;transform:translateY(-50%)}.noticejs-middleLeft{left:10px}.noticejs-middleCenter{top:50%;left:50%;transform:translate(-50%,-50%)}.noticejs-bottom{bottom:0;width:100%!important}.noticejs-bottom .item{border-radius:0!important;margin:0!important}.noticejs-bottomRight{bottom:10px;right:10px}.noticejs-bottomLeft{bottom:10px;left:10px}.noticejs-bottomCenter{bottom:10px;left:50%;transform:translate(-50%)}.noticejs{font-size:14px;font-family:Helvetica Neue,Helvetica,Arial,sans-serif}.noticejs .item{width:fit-content;margin:0 0 10px;border-radius:5px;overflow:hidden}.noticejs .item .close{cursor:pointer;width:21px;height:21px;text-align:center;margin-top:-3px;margin-right:-3px;float:right;font-size:18px;font-weight:700;line-height:1;color:#fff;text-shadow:0 1px 0 #fff;opacity:1}.noticejs .item .close:hover{opacity:.5;color:#000}.noticejs .item a{color:#fff;border-bottom:1px dashed #fff}.noticejs .item a,.noticejs .item a:hover{text-decoration:none}.noticejs .success{background-color:#64ce83b3}.noticejs .success .noticejs-heading{background-color:#3da95cb3;color:#fff;padding:5px}.noticejs .success .noticejs-body{color:#fff;padding:5px 10px}.noticejs .success .noticejs-body:hover{visibility:visible!important}.noticejs .success .noticejs-content{visibility:visible;word-break:break-all;min-width:135px}.noticejs .info{background-color:#3ea2ffb3}.noticejs .info .noticejs-heading{background-color:#067ceab3;color:#fff;padding:5px}.noticejs .info .noticejs-body{color:#fff;padding:5px 10px}.noticejs .info .noticejs-body:hover{visibility:visible!important}.noticejs .info .noticejs-content{visibility:visible;word-break:break-all}.noticejs .warning{background-color:#ff7f48b3}.noticejs .warning .noticejs-heading{background-color:#f44e06b3;color:#fff;padding:5px}.noticejs .warning .noticejs-body{color:#fff;padding:5px 10px}.noticejs .warning .noticejs-body:hover{visibility:visible!important}.noticejs .warning .noticejs-content{visibility:visible;word-break:break-all}.noticejs .error{background-color:#e74c3cb3}.noticejs .error .noticejs-heading{background-color:#ba2c1db3;color:#fff;padding:5px}.noticejs .error .noticejs-body{color:#fff;padding:5px 10px}.noticejs .error .noticejs-body:hover{visibility:visible!important}.noticejs .error .noticejs-content{visibility:visible;word-break:break-all}.noticejs .progressbar{width:100%}.noticejs .progressbar .bar{width:1%;height:30px;background-color:#4caf50b3}.noticejs .success .noticejs-progressbar{width:100%;background-color:#64ce83b3;margin-top:-1px}.noticejs .success .noticejs-progressbar .noticejs-bar{width:100%;height:5px;background:#3da95cb3}.noticejs .info .noticejs-progressbar{width:100%;background-color:#3ea2ffb3;margin-top:-1px}.noticejs .info .noticejs-progressbar .noticejs-bar{width:100%;height:5px;background:#067ceab3}.noticejs .warning .noticejs-progressbar{width:100%;background-color:#ff7f48b3;margin-top:-1px}.noticejs .warning .noticejs-progressbar .noticejs-bar{width:100%;height:5px;background:#f44e06b3}.noticejs .error .noticejs-progressbar{width:100%;background-color:#e74c3cb3;margin-top:-1px}.noticejs .error .noticejs-progressbar .noticejs-bar{width:100%;height:5px;background:#ba2c1db3}@keyframes noticejs-fadeOut{0%{opacity:1}to{opacity:0}}.noticejs-fadeOut{animation-name:noticejs-fadeOut}@keyframes noticejs-modal-in{to{opacity:.3}}@keyframes noticejs-modal-out{to{opacity:0}}.noticejs-rtl .noticejs-heading{direction:rtl}.noticejs-rtl .close{float:left!important;margin-left:7px;margin-right:0!important}.noticejs-rtl .noticejs-content{direction:rtl}.noticejs{position:fixed;z-index:10050}.noticejs ::-webkit-scrollbar{width:8px}.noticejs ::-webkit-scrollbar-button{width:8px;height:5px}.noticejs ::-webkit-scrollbar-track{border-radius:10px}.noticejs ::-webkit-scrollbar-thumb{background:hsla(0,0%,100%,.5);border-radius:10px}.noticejs ::-webkit-scrollbar-thumb:hover{background:#fff}.noticejs-modal{position:fixed;width:100%;height:100%;background-color:#000;z-index:10000;opacity:.3;left:0;top:0}.noticejs-modal-open{opacity:0;animation:noticejs-modal-in .3s ease-out}.noticejs-modal-close{animation:noticejs-modal-out .3s ease-out;animation-fill-mode:forwards}");
  77. // 新版红包CSS
  78. GM_addStyle(".join .join-main .join-envelope-sponsor .sponsor-award .award-item{width:70px!important;height:70px!important}.join .join-main .join-envelope-sponsor .sponsor-award .award-item .award-item-bg{justify-content:center!important}.join .join-main .join-envelope-sponsor .sponsor-award .award-item .award-item-num{margin-top:0!important;position:relative;top:-3px}.join .join-main .join-envelope-sponsor .sponsor-award .award-item .award-item-img{width:50px!important;height:50px!important}");
  79. // 领取按钮
  80. GM_addStyle(".draw-red-packet-btn{margin:2px 10px 0;color:#f9dc8b;padding:2px 0;background:#ed5959dd;border-radius:4px;text-align:center;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:flex;justify-content:center;align-items:center}.draw-red-packet-btn.disabled{color:#fff;background:#aaaa}");
  81.  
  82. let notice;
  83. let timeout;
  84. let giftCount = 0;
  85. let unpacking = false;
  86. // let giftList = new Map();
  87. let awards = {};
  88.  
  89. let formData = new FormData();
  90. formData.set("visit_id", "");
  91. formData.set("jump_from", "");
  92. formData.set("session_id", "");
  93. formData.set("room_id", ROOM_ID);
  94. formData.set("ruid", ROOM_USER_ID);
  95. formData.set("spm_id", "444.8.red_envelope.extract");
  96. formData.set("jump_from", "26000");
  97. formData.set("build", "6790300");
  98. formData.set("c_locale", "en_US");
  99. formData.set("channel", "360");
  100. formData.set("device", "android");
  101. formData.set("mobi_app", "android");
  102. formData.set("platform", "android");
  103. formData.set("version", "6.79.0");
  104. formData.set("statistics", "%7B%22appId%22%3A1%2C%22platform%22%3A3%2C%22version%22%3A%226.79.0%22%2C%22abtest%22%3A%22%22%7D");
  105.  
  106. bliveproxy.addCommandHandler("POPULARITY_RED_POCKET_START", async (message) => {
  107. let failed = await drawRedPacket(message);
  108. // 参数错误时重试
  109. if (failed) {
  110. setTimeout(async () => {
  111. message.data.current_time = message.data.current_time - 1000;
  112. failed = await drawRedPacket(message);
  113. if (failed) {
  114. addDrawBtn(message);
  115. }
  116. }, 1000);
  117. }
  118. });
  119. bliveproxy.addCommandHandler("POPULARITY_RED_POCKET_WINNER_LIST", redPacketWinner);
  120.  
  121. window.addEventListener('beforeunload', (event) => {
  122. if (timeout) {
  123. unfollow();
  124. clearTimeout(timeout);
  125. }
  126. });
  127.  
  128. getLottery();
  129.  
  130. function autoUnfollowMenu() {
  131. autoUnfollow = !autoUnfollow;
  132. GM_setValue("autoUnfollow", autoUnfollow);
  133. GM_unregisterMenuCommand(menuId);
  134. menuId = GM_registerMenuCommand(`自动取关功能 [${autoUnfollow ? '√' : '×'}]`, autoUnfollowMenu);
  135. }
  136.  
  137. function getLottery() {
  138. fetch(`https://api.live.bilibili.com/xlive/lottery-interface/v1/lottery/getLotteryInfoWeb?roomid=${ROOM_ID}`)
  139. .then(res => res.json())
  140. .then(async json => {
  141. if (json.data.popularity_red_pocket && json.data.popularity_red_pocket[0].user_status == 2 && json.data.popularity_red_pocket[0].end_time > json.data.popularity_red_pocket[0].current_time) {
  142. let message = {
  143. "data": json.data.popularity_red_pocket[0]
  144. };
  145. let failed = await drawRedPacket(message);
  146. if (failed) {
  147. setTimeout(async () => {
  148. message.data.current_time = message.data.current_time - 1000;
  149. failed = await drawRedPacket(message);
  150. if (failed) {
  151. addDrawBtn(message);
  152. }
  153. }, 1000);
  154. }
  155. }
  156. });
  157. }
  158.  
  159. function addDrawBtn(message, retry = 0) {
  160. if (message.data.end_time <= message.data.current_time) {
  161. return; // 防止给已开奖的红包添加按钮
  162. }
  163. let btn = document.querySelector(".draw-red-packet-btn");
  164. btn && btn.remove();
  165. let redEnvelope = document.querySelector(".popularity-red-envelope-entry.gift-left-part");
  166. if (!redEnvelope) {
  167. if (retry <= 5) {
  168. setTimeout(() => {
  169. addDrawBtn(message, retry + 1);
  170. }, 1000);
  171. }
  172. return;
  173. }
  174. let dom = document.createElement("div");
  175. if (GM_getValue(`limitWarning-${Setting.UID}`) == Setting.Beijing_date) {
  176. dom.className = "draw-red-packet-btn disabled";
  177. dom.innerHTML = "<span>上限</span>";
  178. } else {
  179. dom.className = "draw-red-packet-btn";
  180. dom.innerHTML = "<span>抽红包</span>";
  181. }
  182. dom.onclick = function (e) {
  183. e.stopPropagation();
  184. drawRedPacket(message, true);
  185. }
  186. redEnvelope.append(dom);
  187. }
  188.  
  189. function removeDrawBtn() {
  190. let drawBtn = document.querySelector(".draw-red-packet-btn");
  191. drawBtn && drawBtn.remove();
  192. }
  193.  
  194. function drawRedPacket(message, force) {
  195. if (!force) {
  196. // 每日上限
  197. if (GM_getValue(`limitWarning-${Setting.UID}`) == Setting.Beijing_date) {
  198. addDrawBtn(message);
  199. return;
  200. }
  201. // 电池门槛
  202. let gold = Math.round(message.data.total_price / 100);
  203. if (doorSill > gold || goldBlockEnumList.includes(gold)) {
  204. addDrawBtn(message);
  205. return;
  206. }
  207. }
  208.  
  209. clearTimeout(timeout);
  210. timeout = null;
  211. // 防止收不到开奖信息页面状态卡住
  212. let countdown = (message.data.end_time - message.data.current_time) * 1000;
  213. setTimeout(() => {
  214. if (unpacking) {
  215. let obj = {
  216. "data": {
  217. "winner_info": []
  218. }
  219. };
  220. redPacketWinner(obj);
  221. }
  222. }, countdown + 5000);
  223.  
  224. // if (giftList.size == 0) {
  225. // initGiftList();
  226. // }
  227.  
  228. formData.set("csrf", Setting.TOKEN);
  229. formData.set("csrf_token", formData.get("csrf"));
  230. formData.set("lot_id", message.data.lot_id);
  231.  
  232. return new Promise(resolve => {
  233. GM_xmlhttpRequest({
  234. url: `https://api.live.bilibili.com/xlive/lottery-interface/v1/popularityRedPocket/RedPocketDraw`,
  235. method: "post",
  236. headers: {
  237. "User-Agent": "Mozilla/5.0 BiliDroid/6.79.0 (bbcallen@gmail.com) os/android model/Redmi K30 Pro mobi_app/android build/6790300 channel/360 innerVer/6790310 osVer/11 network/2"
  238. },
  239. data: formData,
  240. onload: function (res) {
  241. let json = undefined;
  242. try {
  243. json = JSON.parse(res.response);
  244. } catch (error) {
  245. resolve(false);
  246. console.warn(res);
  247. throw new Error("返参错误");
  248. }
  249. if (json.code !== 0 || json.data.join_status !== 1) {
  250. console.log("红包请求返回:", JSON.stringify(json));
  251. switch (json.code) {
  252. case 1009109: // 每日上限
  253. removeDrawBtn();
  254. showMessage(json.message, "warning", null, false);
  255. GM_setValue(`limitWarning-${Setting.UID}`, Setting.Beijing_date);
  256. resolve(false);
  257. addDrawBtn(message);
  258. if (!FOLLOWED) {
  259. unfollow();
  260. }
  261. return;
  262. case 1009114: // 已抽奖
  263. removeDrawBtn();
  264. notice = showMessage(`
  265. 坐等 ${message.data.sender_name} 的红包开奖
  266. <br>
  267. 红包ID${message.data.lot_id}
  268. <br>
  269. <span>
  270. 总价值:
  271. <span class="coin-type dp-i-block v-middle none-select">
  272. <i class="currency-icon" style="background-image: url(&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAABDBJREFUaAXVWt1rFFcU/92Z3Z3sJiHRxBhNRe0ihSLSF20fBBWDL/og2Pf+A774IKGU0gXf2jcf/RMsQkXwg4IgVKxUUBB9SJssRtGQaLr52J1sZmduz93qujt752Nn713WE8jOPeeee36/O+d+zQzwiQtThZ8/K2QwZBxAzctGtmlhDVP4h7GCF1k3okIqwh7LzDmBL+Iv1NxDsRyqVKvIrtH/b2PVD6lkhNjimxaMw+A8HvgPrXJ+jhcLox+KSX/VEPC84UQA0hhK5NfkpIZAU4O9vow1Bji/auLN822B4KpsBOCB5kDDFrbz14VNqd3LcEx9v8IYC204dBbi85e+ANzLFOAo5XhOGkinkrES9ctNDOICmywsyUIFEuALl/Jw3CfUs13nqSxwRzrGijRaDrGJwobfLziFHPdnZeANC8hM+GO3l70twFmlsL6s4nw/1tlFcvjJ7xRMQKSNKjEHgaGD8Vuz54HyLNVvSX8pnpBZiMfosviYOqqZ/RzI7vO7SPGEEPD797icy8cK2L8EWBpgA5Ek+peAgG6Y/UHAfvMrSn8ew9bynUhAnVbQfgectafYXPkD3KvCeXe3U3yR9bUS4LV1VJZvNkAY1njjWtWFVgLlpRvw3I+LkpGZVIW70Y42Altrj+Fs/N0IJC4Ma2dLWUVBCwGvtorK0u02fIa1q03XrUIDAY7K4nUatLSv8ckncQeqq4/gVIo+6LQmMRMs0+eD2HNWYC//3gZeKAxLbGXU33CFLXKUF3+j1HHkBDTMQPWOkUZLoKz++wA1+2Wgp2GJKdSDV5mjFfk2PLs9zQKdQwxh54EQt1YTdzdgvw1fZZ3SQ5QeToO7lbozM3MYPXxL5FZrYx2WFBGw6cjsNkIbBIqLv6aZSIyPZmHikGPQjrNLUULAyOzA8GffQcz/qYHdMGi2WV+4gtrmYiC8XH6GbN0PQSUEBMpUbp/4aYgnzrYBYk2cQXqb9IQY4BGs7r4LZG1zh/ZAtsxS307k9l+Q2pIotRAI6n3xDGcw/wMg8l+RaCJQksKzJs8hNXpEakuq1EOABrNfzIEpZPee96u7LveEAAND7sCPlDrR7z46ZaSHgG8GssaOIzX8VafYYtXXTsCkNSE7cToWmCSV9BBw1+pYROoM7jqrZMUNIqeFQHroS4JOTwfHT8K0poJiK9ErW4mb0WTHp5EdO0GnmOgHU81+Sa613IE6EBXgefRbWH0EknRnsw9tR+jQ0KyRXvcvAcm5WsYghABbljn0RGe/AOw5fygpnrBBfJ9aoDlQgdTK9MbleXRD4gAktiHvT20tDgwCT5uEEZihZyGnlLyd5PRtgejVxMIWMIJfZO6BKcTyhVmk8DWRuEfzYftTKllrqnWMlSn+NZjpb9hY4f/V0ReD+crSYv1jjlepHVKjLiWvcezBYtQXLf8BGOoetC6LwK8AAAAASUVORK5CYII=&quot;);"></i>
  273. </span>
  274. <span class="text">${(message.data.total_price / 100).toFixed(0)}</span>
  275. </span>
  276. `, "info", "啊哈哈哈哈哈哈,红包来咯", countdown);
  277. unpacking = true;
  278. updateTabTitle();
  279. resolve(false);
  280. return;
  281. case 1009108: // 抽奖已结束
  282. removeDrawBtn();
  283. break;
  284. case 1009106: // 参数错误 ???
  285. resolve(true);
  286. return;
  287. case -352: // 当前操作异常,请升级至最新版本后重试
  288. json.message = "当前操作异常,使用手机端通过验证码后再试"
  289. addDrawBtn(message);
  290. default:
  291. }
  292. resolve(false); // false时不进行重试,也不会添加抢红包按钮
  293. showMessage(json.message, "error", "抢红包失败", false);
  294. } else {
  295. removeDrawBtn();
  296. notice = showMessage(`
  297. 坐等 ${message.data.sender_name} 的红包开奖
  298. <br>
  299. 红包ID${message.data.lot_id}
  300. <br>
  301. <span>
  302. 总价值:
  303. <span class="coin-type dp-i-block v-middle none-select">
  304. <i class="currency-icon" style="background-image: url(&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAABDBJREFUaAXVWt1rFFcU/92Z3Z3sJiHRxBhNRe0ihSLSF20fBBWDL/og2Pf+A774IKGU0gXf2jcf/RMsQkXwg4IgVKxUUBB9SJssRtGQaLr52J1sZmduz93qujt752Nn713WE8jOPeeee36/O+d+zQzwiQtThZ8/K2QwZBxAzctGtmlhDVP4h7GCF1k3okIqwh7LzDmBL+Iv1NxDsRyqVKvIrtH/b2PVD6lkhNjimxaMw+A8HvgPrXJ+jhcLox+KSX/VEPC84UQA0hhK5NfkpIZAU4O9vow1Bji/auLN822B4KpsBOCB5kDDFrbz14VNqd3LcEx9v8IYC204dBbi85e+ANzLFOAo5XhOGkinkrES9ctNDOICmywsyUIFEuALl/Jw3CfUs13nqSxwRzrGijRaDrGJwobfLziFHPdnZeANC8hM+GO3l70twFmlsL6s4nw/1tlFcvjJ7xRMQKSNKjEHgaGD8Vuz54HyLNVvSX8pnpBZiMfosviYOqqZ/RzI7vO7SPGEEPD797icy8cK2L8EWBpgA5Ek+peAgG6Y/UHAfvMrSn8ew9bynUhAnVbQfgectafYXPkD3KvCeXe3U3yR9bUS4LV1VJZvNkAY1njjWtWFVgLlpRvw3I+LkpGZVIW70Y42Altrj+Fs/N0IJC4Ma2dLWUVBCwGvtorK0u02fIa1q03XrUIDAY7K4nUatLSv8ckncQeqq4/gVIo+6LQmMRMs0+eD2HNWYC//3gZeKAxLbGXU33CFLXKUF3+j1HHkBDTMQPWOkUZLoKz++wA1+2Wgp2GJKdSDV5mjFfk2PLs9zQKdQwxh54EQt1YTdzdgvw1fZZ3SQ5QeToO7lbozM3MYPXxL5FZrYx2WFBGw6cjsNkIbBIqLv6aZSIyPZmHikGPQjrNLUULAyOzA8GffQcz/qYHdMGi2WV+4gtrmYiC8XH6GbN0PQSUEBMpUbp/4aYgnzrYBYk2cQXqb9IQY4BGs7r4LZG1zh/ZAtsxS307k9l+Q2pIotRAI6n3xDGcw/wMg8l+RaCJQksKzJs8hNXpEakuq1EOABrNfzIEpZPee96u7LveEAAND7sCPlDrR7z46ZaSHgG8GssaOIzX8VafYYtXXTsCkNSE7cToWmCSV9BBw1+pYROoM7jqrZMUNIqeFQHroS4JOTwfHT8K0poJiK9ErW4mb0WTHp5EdO0GnmOgHU81+Sa613IE6EBXgefRbWH0EknRnsw9tR+jQ0KyRXvcvAcm5WsYghABbljn0RGe/AOw5fygpnrBBfJ9aoDlQgdTK9MbleXRD4gAktiHvT20tDgwCT5uEEZihZyGnlLyd5PRtgejVxMIWMIJfZO6BKcTyhVmk8DWRuEfzYftTKllrqnWMlSn+NZjpb9hY4f/V0ReD+crSYv1jjlepHVKjLiWvcezBYtQXLf8BGOoetC6LwK8AAAAASUVORK5CYII=&quot;);"></i>
  305. </span>
  306. <span class="text">${(message.data.total_price / 100).toFixed(0)}</span>
  307. </span>
  308. `, "info", "啊哈哈哈哈哈哈,红包来咯", countdown);
  309. unpacking = true;
  310. updateTabTitle();
  311. resolve(false);
  312. }
  313. }
  314. });
  315. });
  316.  
  317. }
  318.  
  319. async function unfollow() {
  320. return new Promise((r, j) => {
  321. if (!autoUnfollow) {
  322. console.log("自动抢红包-自动取关已关闭,跳过取关");
  323. return r(false);
  324. }
  325. fetch(`https://api.bilibili.com/x/relation/tag/user?fid=${ROOM_USER_ID}&jsonp=jsonp&_=${Date.now()}`, {
  326. "credentials": "include"
  327. })
  328. .then(res => res.text())
  329. .then(result => {
  330. let json = JSON.parse(result);
  331. if (Object.keys(json.data).length == 0) {
  332. let data = new FormData();
  333. data.set("act", "2");
  334. data.set("csrf", Setting.TOKEN);
  335. data.set("re_src", "11");
  336. data.set("jsonp", "jsonp");
  337. data.set("fid", ROOM_USER_ID);
  338. data.set("spmid", "333.999.0.0");
  339. data.set("extend_content", `{ "entity": "user", "entity_id": ${ROOM_USER_ID} }`);
  340. fetch("https://api.bilibili.com/x/relation/modify", {
  341. credentials: "include",
  342. method: 'POST',
  343. body: data
  344. })
  345. .then(res => res.json())
  346. .then(json => {
  347. if (json.code == json.message) {
  348. let unfollow = awards["unfollow"] || {};
  349. unfollow.notice && unfollow.notice.remove();
  350. unfollow.notice = showMessage("已取消关注", "warning", "提示", false);
  351. }
  352. return r(json.code != json.message);
  353. });
  354. }
  355. });
  356. });
  357. }
  358.  
  359. function redPacketWinner(message) {
  360. // let tempMsg = {
  361. // "cmd": "POPULARITY_RED_POCKET_WINNER_LIST",
  362. // "data": {
  363. // "lot_id": 7561546,
  364. // "total_num": 10,
  365. // "winner_info": [
  366. // [
  367. // 383148522,
  368. // "故意de",
  369. // 5407185,
  370. // 31212
  371. // ]
  372. // ],
  373. // "awards": {
  374. // "31212": {
  375. // "award_type": 1,
  376. // "award_name": "打call",
  377. // "award_pic": "https://s1.hdslb.com/bfs/live/461be640f60788c1d159ec8d6c5d5cf1ef3d1830.png",
  378. // "award_big_pic": "https://i0.hdslb.com/bfs/live/9e6521c57f24c7149c054d265818d4b82059f2ef.png",
  379. // "award_price": 500
  380. // }
  381. // }
  382. // }
  383. // }
  384. removeDrawBtn();
  385. let follow = unpacking;
  386. unpacking = false;
  387. notice && (notice.style.display = "none");
  388. for (let winner of message.data.winner_info) {
  389. if (Setting.UID == winner[0]) {
  390. // let giftDetail = giftList.get(winner[3]);
  391. let award = awards[winner[3]] || {};
  392. award.count = (award.count >> 0) + 1;
  393. award.notice && award.notice.remove();
  394. award.notice = showMessage(`
  395. <div class="gift-frame img gift-${winner[3]}-40" height="40" style="width:40px;height:40px;display:inline-block;"></div>
  396. <span>
  397. 获得:${message.data.awards[winner[3]].award_name}${award.count > 1 ? " ×" + award.count : ""}
  398. </span>
  399. <br>
  400. <span>
  401. 价值:
  402. <span class="coin-type dp-i-block v-middle none-select">
  403. <i class="currency-icon" style="background-image: url(&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAABDBJREFUaAXVWt1rFFcU/92Z3Z3sJiHRxBhNRe0ihSLSF20fBBWDL/og2Pf+A774IKGU0gXf2jcf/RMsQkXwg4IgVKxUUBB9SJssRtGQaLr52J1sZmduz93qujt752Nn713WE8jOPeeee36/O+d+zQzwiQtThZ8/K2QwZBxAzctGtmlhDVP4h7GCF1k3okIqwh7LzDmBL+Iv1NxDsRyqVKvIrtH/b2PVD6lkhNjimxaMw+A8HvgPrXJ+jhcLox+KSX/VEPC84UQA0hhK5NfkpIZAU4O9vow1Bji/auLN822B4KpsBOCB5kDDFrbz14VNqd3LcEx9v8IYC204dBbi85e+ANzLFOAo5XhOGkinkrES9ctNDOICmywsyUIFEuALl/Jw3CfUs13nqSxwRzrGijRaDrGJwobfLziFHPdnZeANC8hM+GO3l70twFmlsL6s4nw/1tlFcvjJ7xRMQKSNKjEHgaGD8Vuz54HyLNVvSX8pnpBZiMfosviYOqqZ/RzI7vO7SPGEEPD797icy8cK2L8EWBpgA5Ek+peAgG6Y/UHAfvMrSn8ew9bynUhAnVbQfgectafYXPkD3KvCeXe3U3yR9bUS4LV1VJZvNkAY1njjWtWFVgLlpRvw3I+LkpGZVIW70Y42Altrj+Fs/N0IJC4Ma2dLWUVBCwGvtorK0u02fIa1q03XrUIDAY7K4nUatLSv8ckncQeqq4/gVIo+6LQmMRMs0+eD2HNWYC//3gZeKAxLbGXU33CFLXKUF3+j1HHkBDTMQPWOkUZLoKz++wA1+2Wgp2GJKdSDV5mjFfk2PLs9zQKdQwxh54EQt1YTdzdgvw1fZZ3SQ5QeToO7lbozM3MYPXxL5FZrYx2WFBGw6cjsNkIbBIqLv6aZSIyPZmHikGPQjrNLUULAyOzA8GffQcz/qYHdMGi2WV+4gtrmYiC8XH6GbN0PQSUEBMpUbp/4aYgnzrYBYk2cQXqb9IQY4BGs7r4LZG1zh/ZAtsxS307k9l+Q2pIotRAI6n3xDGcw/wMg8l+RaCJQksKzJs8hNXpEakuq1EOABrNfzIEpZPee96u7LveEAAND7sCPlDrR7z46ZaSHgG8GssaOIzX8VafYYtXXTsCkNSE7cToWmCSV9BBw1+pYROoM7jqrZMUNIqeFQHroS4JOTwfHT8K0poJiK9ErW4mb0WTHp5EdO0GnmOgHU81+Sa613IE6EBXgefRbWH0EknRnsw9tR+jQ0KyRXvcvAcm5WsYghABbljn0RGe/AOw5fygpnrBBfJ9aoDlQgdTK9MbleXRD4gAktiHvT20tDgwCT5uEEZihZyGnlLyd5PRtgejVxMIWMIJfZO6BKcTyhVmk8DWRuEfzYftTKllrqnWMlSn+NZjpb9hY4f/V0ReD+crSYv1jjlepHVKjLiWvcezBYtQXLf8BGOoetC6LwK8AAAAASUVORK5CYII=&quot;);"></i>
  404. </span>
  405. <span class="text">${Math.round(message.data.awards[winner[3]].award_price / 100) * award.count}</span>
  406. </span>
  407. `, "success", "中奖啦!", false, (p) => {
  408. // 关闭提示框时清空礼物计数
  409. // alert(`清空 ${message.data.awards[winner[3]]} 的计数`);
  410. // console.log(JSON.stringify(award));
  411. // award.count = 0;
  412. });
  413. if (award.count == 1) {
  414. awards[winner[3]] = award;
  415. }
  416. giftCount++;
  417. break;
  418. }
  419. }
  420. updateTabTitle();
  421. if ((!FOLLOWED) && follow) {
  422. timeout = setTimeout(async () => {
  423. let unfollowed = await unfollow();
  424. if (unfollowed) {
  425. unfollow();
  426. }
  427. }, 15000);
  428. }
  429. }
  430.  
  431. function showMessage(msg, type = "info", title, time = 3000, closeCallback) {
  432. const TITLE = {
  433. "info": "提示",
  434. "error": "错误",
  435. "success": "成功",
  436. "warning": "警告",
  437. }
  438. // type: success[green] error[red] warning[orange] info[blue]
  439. // pos: topLeft, topCenter, middleLeft, middleRight, middleCenter, bottomLeft, bottomRight, bottomCenter
  440. // timeout: timeout * 100ms 代码内部似乎还有固定0.5s的前置/后置延迟
  441. return new NoticeJs({
  442. title: title || TITLE[type],
  443. text: msg,
  444. timeout: time ? Math.round(time / 100) : time,
  445. type: type,
  446. position: "bottomLeft",
  447. callbacks: {
  448. // beforeShow: [],
  449. // onShow: [],
  450. // afterShow: [],
  451. onClose: [closeCallback],
  452. // afterClose: [],
  453. // onClick: [],
  454. // onHover: [],
  455. // onTemplate: []
  456. }
  457. }).show();
  458. }
  459.  
  460. function updateTabTitle() {
  461. let title = document.title.replace(/(🧧 🎁\*\d* )|(🧧 )|(🎁\*\d* )/, "");
  462. let header = "";
  463. if (unpacking) {
  464. header += RED_PACKET_ICON;
  465. }
  466. if (giftCount > 0) {
  467. if (header) {
  468. header += " ";
  469. }
  470. header += GIFT_ICON + "*" + giftCount;
  471. }
  472. if (header) {
  473. header += " ";
  474. }
  475. document.title = header + title;
  476. }
  477.  
  478. async function getFollowStatus(uid) {
  479. return new Promise((r, j) => {
  480. /* attribute: 0-未关注 128-拉黑 2-关注 1-悄悄关注 6-互相关注 */
  481. fetch(`https://api.bilibili.com/x/relation?fid=${uid}`, {
  482. "credentials": "include"
  483. })
  484. .then(res => res.json())
  485. .then(json => {
  486. r(json.data.attribute != 0 && json.data.attribute != 128);
  487. });
  488. });
  489. }
  490.  
  491. function initGiftList() {
  492. fetch(`https://api.live.bilibili.com/xlive/web-room/v1/giftPanel/giftConfig?platform=pc&room_id=${ROOM_ID}`)
  493. .then(res => res.json())
  494. .then(json => {
  495. if (json.code == json.message) {
  496. for (const item of json.data.list) {
  497. giftList.set(item.id, item);
  498. }
  499. }
  500. });
  501. }
  502.  
  503. })();