哔哩哔哩勋章升级助手

自用脚本,不喜勿用哈~~哔哩哔哩勋章:自动点亮、观看获取亲密度

  1. // ==UserScript==
  2. // @name 哔哩哔哩勋章升级助手
  3. // @homepage https://greasyfork.org/zh-CN/scripts/445651
  4. // @version 5.43
  5. // @description 自用脚本,不喜勿用哈~~哔哩哔哩勋章:自动点亮、观看获取亲密度
  6. // @author 风绫丨钰袖
  7. // @iconURL https://www.bilibili.com/favicon.ico
  8. // @icon64URL https://www.bilibili.com/favicon.ico
  9. // @match https://live.bilibili.com/*
  10. // @match https://www.bilibili.com/blackboard/live/*
  11. // @connect bilibili.com
  12. // @connect flyx.fun
  13. // @require https://lib.baomitu.com/jquery/3.4.1/jquery.min.js
  14. // @require https://update.greasyfork.org/scripts/447321/1416383/BiliveHeart.js
  15. // @require https://greasyfork.org/scripts/441505-crypto-js4-1-1/code/crypto-js411.js?version=1028182
  16. // @grant unsafeWindow
  17. // @grant GM_notification
  18. // @grant GM_getValue
  19. // @grant GM_setValue
  20. // @grant GM_deleteValue
  21. // @grant GM_openInTab
  22. // @grant GM_xmlhttpRequest
  23. // @run-at document-idle
  24. // @grant GM_info
  25. // @license MIT License
  26. // @namespace http://tampermonkey.net/
  27. // ==/UserScript==
  28.  
  29. /*
  30. 脚本不能加载时,可能是库源网络故障,可尝试替换库源为以下网址:
  31. 替换第13-15行:
  32. // @require http://flyx.fun:1369/static/jQuery3.4.1.js
  33. // @require http://flyx.fun:1369/static/crypto-js.js
  34. // @require http://flyx.fun:1369/static/BiliveHeart.js
  35. */
  36.  
  37. window.onload =(function () {
  38. var NAME
  39. var BAPI
  40. var ms_diff = 0
  41. var s_diff = 0
  42. var dmlist = []
  43. var medal_list_now = []
  44. var medal_sign = true
  45. var Live_info = {
  46. coin: undefined,
  47. room_id: undefined,
  48. uid: undefined,
  49. csrf_token: undefined,
  50. rnd: undefined,
  51. ruid: undefined,
  52. uname: undefined,
  53. user_level: undefined,
  54. Blever: undefined,
  55. room_area_id: 371,
  56. area_parent_id: 9,
  57. vipType: undefined,
  58. face_url: undefined,
  59. vipTypetext: undefined,
  60. cost: undefined,
  61. regtime: undefined,
  62. identification: undefined,
  63. img_key:undefined,
  64. sub_key:undefined,
  65. buvid3:undefined,
  66. };
  67.  
  68. /**
  69. * 替换字符串中所有的匹配项
  70. * @param oldSubStr 搜索的字符串
  71. * @param newSubStr 替换内容
  72. */
  73. function my_tips(message){
  74. GM_notification({
  75. title:'完成通知',
  76. text: message,
  77. image:'https://i0.hdslb.com/bfs/article/927cc195124c47474b4a150d8b09e00536d15a0a.gif',
  78. timeout: 10000,
  79. })
  80. }
  81. function shuffle(arr) {
  82. var length = arr.length,
  83. randomIndex,
  84. temp;
  85. while (length) {
  86. randomIndex = Math.floor(Math.random() * (length--));
  87. temp = arr[randomIndex];
  88. arr[randomIndex] = arr[length];
  89. arr[length] = temp
  90. }
  91. return arr;
  92. }
  93. const ts_ms = () => Date.now();
  94. const ts_s = () => Math.round(ts_ms() / 1000);
  95. const hour = () => new Date(ts_ms()).getHours();
  96. const minute = () => new Date(ts_ms()).getMinutes();
  97. const delayCall = (callback, delay = 10e3) => {
  98. const p = $.Deferred();
  99. setTimeout(() => {
  100. const t = callback();
  101. if (t && t.then)
  102. t.then((arg1, arg2, arg3, arg4, arg5, arg6) => p.resolve(arg1, arg2, arg3, arg4, arg5, arg6));
  103. else
  104. p.resolve();
  105. }, delay);
  106. return p;
  107. };
  108. function sleep(ms) {
  109. return new Promise(resolve => setTimeout(() => resolve('sleep'), ms));
  110. }
  111. let getMyJson = function(url){
  112. return new Promise((resolve) => {
  113. GM_xmlhttpRequest({
  114. method: "GET",
  115. url: url,
  116. onload: function(response){
  117. const res = strToJson((response || {}).responseText)
  118. resolve(res);
  119. }
  120. });
  121. })
  122. }
  123. let strToJson = function(params){
  124. const isJSON = (str => {
  125. if(typeof str === 'string'){
  126. try {
  127. const obj = JSON.parse(str);
  128. return typeof obj === 'object' ? obj : false
  129. } catch (_){
  130. console.log(str);
  131. return false;
  132. }
  133. }else{
  134. console.log(`${str}\nIt is not a string!`);
  135. return false;
  136. }
  137. })(params);
  138. return isJSON ? isJSON : {}
  139. }
  140. String.prototype.replaceAll = function (oldSubStr, newSubStr) {
  141. return this.replace(new RegExp(oldSubStr, 'gm'), newSubStr)
  142. }
  143. const newWindow = {
  144. init: () => {
  145. return newWindow.Toast.init();
  146. },
  147. Toast: {
  148. init: () => {
  149. try {
  150. const list = [];
  151. window.toast = (msg, type = 'info', timeout = 5e3, side = 'left') => {
  152. console.log(msg)
  153. switch (type){
  154. case 'success':
  155. case 'info':
  156. case 'error':
  157. break;
  158. default:
  159. type = 'info';
  160. }
  161. const a = $(`<div class="link-toast ${type} fixed" style="z-index:2001;text-align: left;"><span class="toast-text">${msg}</span></div>`)[0];
  162. document.body.appendChild(a);
  163. a.style.top = (document.body.scrollTop + list.length * 40 + 10) + 'px';
  164. if(side == 'left')a.style.left = 10 + 'px';
  165. if(side != 'left')a.style.left = (document.body.offsetWidth + document.body.scrollLeft - a.offsetWidth - 5) + 'px';
  166. list.push(a);
  167. setTimeout(() => {
  168. a.className += ' out';
  169. setTimeout(() => {
  170. list.shift();
  171. list.forEach((v) => {
  172. v.style.top = (parseInt(v.style.top, 10) - 40) + 'px';
  173. });
  174. $(a).remove();
  175. }, 200);
  176. }, timeout);
  177. };
  178. return $.Deferred().resolve();
  179. } catch (err){
  180. return $.Deferred().reject();
  181. }
  182. }
  183. }
  184. }
  185. const getCookie = (name) => {
  186. let arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
  187. if (arr != null)
  188. return unescape(arr[2]);
  189. return false;
  190. }
  191. $(function () { //DOM完毕,等待弹幕加载完成
  192. let loadInfo = (delay) => {
  193. if ((typeof BilibiliLive) == "undefined") {
  194. BilibiliLive = undefined;
  195. }
  196. setTimeout(async function () {
  197. GM_xmlhttpRequest({
  198. method: "GET",
  199. url: "https://api.bilibili.com/x/web-interface/nav",
  200. onload: async function(response) {
  201. let json = JSON.parse(response.response);
  202. //console.log(json);
  203. if (!json.data.isLogin) {
  204. loadInfo(5000);
  205. window.toast('无账号登陆信息,请先登录或检查网络','error',8000);
  206. //console.log('无登陆信息',new Date().toLocaleString());
  207. } else {
  208. if(BilibiliLive == undefined) return loadInfo(5000);
  209. if(BilibiliLive.ROOMID == undefined) return loadInfo(5000);
  210. Live_info.room_id = BilibiliLive.ROOMID;
  211. Live_info.ruid = BilibiliLive.ANCHOR_UID
  212. Live_info.uid = json.data.mid
  213. Live_info.coin = json.data.money
  214. Live_info.Blever = json.data.level_info.current_level
  215. Live_info.vipType = json.data.vipType
  216. Live_info.uname = json.data.uname
  217. Live_info.face_url = json.data.face
  218. Live_info.vipTypetext = json.data.vip_label.text
  219. if(Live_info.vipTypetext=='')Live_info.vipTypetext = '普通用户'
  220. let img_url = json.data.wbi_img.img_url
  221. let sub_url = json.data.wbi_img.sub_url
  222. let img_key = img_url.slice(img_url.lastIndexOf('/') + 1,img_url.lastIndexOf('.'))
  223. let sub_key = sub_url.slice(sub_url.lastIndexOf('/') + 1,sub_url.lastIndexOf('.'))
  224. Live_info.img_key = img_key
  225. Live_info.sub_key = sub_key
  226. NAME = 'BILI' + Live_info.uid
  227. Live_info.csrf_token = getCookie('bili_jct');
  228. Live_info.buvid3 = getCookie('buvid3');
  229. console.log('登陆信息获取成功',Live_info,new Date().toLocaleString());
  230. window.toast('登陆信息获取成功','success');
  231. init();
  232. }
  233. },
  234. onerror : function(err){
  235. loadInfo(5000);
  236. window.toast('无账号登陆信息,请先登录或检查网络','error',8000);
  237. console.log('无登陆信息',new Date().toLocaleString());
  238. }
  239. });
  240. }, delay);
  241. };
  242. newWindow.init();
  243. loadInfo(5000);
  244. });
  245.  
  246. async function init() { //API初始化
  247. const right_ctnr = $('.right-ctnr');
  248. const share = right_ctnr.find('.v-middle.icon-font.icon-share').parent();
  249. const like_button = $(
  250. `<div data-v-6d89404b="" data-v-42ea937d="" title="" class="icon-ctnr live-skin-normal-a-text pointer" id = "blth_like_button" style="line-height: 16px;margin-left: 15px;"><i data-v-6d89404b="" class="v-middle icon-font icon-delete" style="font-size: 16px;"></i><span data-v-6d89404b="" class="action-text v-middle" style="font-size: 12px;margin-left: 5px;">去掉直播水印</span></div>`
  251. );
  252. like_button.click(() => {
  253. $('.web-player-icon-roomStatus').remove()
  254. });
  255. const blanc_button = $(
  256. `<div data-v-6d89404b="" data-v-42ea937d="" title="" class="icon-ctnr live-skin-normal-a-text pointer" id = "blth_like_button" style="line-height: 16px;margin-left: 15px;"><i data-v-6d89404b="" class="v-middle icon-font icon-top" style="font-size: 16px;"></i><span data-v-6d89404b="" class="action-text v-middle" style="font-size: 12px;margin-left: 5px;">回到默认界面</span></div>`
  257. );
  258. blanc_button.click(() => {
  259. window.top.location.href = 'https://live.bilibili.com/blanc/'+ Live_info.room_id
  260. })
  261. if ($('.right-ctnr').length !== 0){
  262. right_ctnr[0].insertBefore(like_button[0], share[0]);
  263. right_ctnr[0].insertBefore(blanc_button[0], like_button[0], share[0]);
  264. }
  265. try {
  266. BAPI = BilibiliAPI;
  267. } catch (err) {
  268. console.error(`[${NAME}]`, err);
  269. return;
  270. }
  271. BAPI.setCommonArgs(Live_info.csrf_token)
  272. const MY_API = {
  273. CONFIG_DEFAULT: {
  274. auto_medal_task: true,
  275. medal_level_pass: true,
  276. medal_pass_level: 21,
  277. auto_light:true,
  278. newday_ts:0,
  279. JSMARK:0,
  280. medal_pass_uid:[],
  281. sort:true,
  282. hide_Toast:true,
  283. medal_first_uid:[],
  284. },
  285. CONFIG: {},
  286. loadConfig: async function () {
  287. let p = $.Deferred();
  288. try {
  289. let config = JSON.parse(localStorage.getItem(`${NAME}_CONFIG`));
  290. $.extend(true, MY_API.CONFIG, MY_API.CONFIG_DEFAULT);
  291. for (let item in MY_API.CONFIG) {
  292. if (!MY_API.CONFIG.hasOwnProperty(item))
  293. continue;
  294. if (config[item] !== undefined && config[item] !== null)
  295. MY_API.CONFIG[item] = config[item];
  296. }
  297. p.resolve()
  298. } catch (e) {
  299. console.log('API载入配置失败,加载默认配置', e);
  300. MY_API.CONFIG = MY_API.CONFIG_DEFAULT
  301. MY_API.saveConfig()
  302. p.reject()
  303. }
  304. return p
  305. },
  306. saveConfig: function () {
  307. try {
  308. localStorage.setItem(`${NAME}_CONFIG`, JSON.stringify(MY_API.CONFIG));
  309. return true
  310. } catch (e) {
  311. console.log('API保存出错', e);
  312. return false
  313. }
  314. },
  315. creatSetBox: function () { //创建设置框
  316. let widthmax = $('.web-player-ending-panel').width() - 50;
  317. let heightmax = $('.chat-history-panel').height();
  318. let div = $("<div class='xzsjzsdiv'>");
  319. div.css({
  320. 'width': '360px',
  321. 'height': '480px',
  322. 'max-height': `${heightmax}px`,
  323. 'position': 'absolute',
  324. 'top': '10px',
  325. 'right': '10px',
  326. 'background': 'rgba(255,255,255,.8)',
  327. 'padding': '10px',
  328. 'z-index': '99',
  329. 'border-radius': '12px',
  330. 'transition': 'height .3s',
  331. 'overflow': 'auto',
  332. 'line-height': '15px'
  333. });
  334. div.append(`
  335. <fieldset>
  336. <legend style="font-size: 100%;color:blue;">用户信息</legend>
  337. <div id="user_info" style="font-size: 100%;color:blue;">
  338. <img src=${Live_info.face_url} width="50" height="50" /><br>
  339. 昵称:${Live_info.uname}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UID${Live_info.uid}<br>
  340. 直播消费:${Live_info.cost}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;会员等级:${Live_info.vipTypetext}<br>
  341. 主站等级:Lv${Live_info.Blever}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;硬币数量:${Live_info.coin}
  342. </div>
  343. </fieldset>
  344.  
  345. <fieldset>
  346. <legend style="font-size: 100%;color:blue;">勋章升级参数设置</legend>
  347. <div data-toggle="auto_medal_task">
  348. <append style="font-size: 100%; color:blue">
  349. <input style="vertical-align: text-top;" type="checkbox">自动勋章升级直播观看任务
  350. </div>
  351.  
  352. <div data-toggle="medal_level_pass">
  353. <append style="font-size: 100%; color:blue">
  354. <input style="vertical-align: text-top;" type="checkbox">跳过<input class="num" style="width:30px;vertical-align:inherit;" type="text">级及以上勋章<button data-action="save">保存</button>
  355. </div>
  356.  
  357. <div data-toggle="medal_pass_uid">
  358. <append style="font-size: 100%;color: blue">
  359. 不执行观看任务主播UID[逗号隔开]<br>
  360. <input class="keyword" style="width: 220px;vertical-align:inherit;" type="text"><button data-action="save" style="font-size: 100%;color:blue">保存</button><br>
  361. </div>
  362.  
  363. <div data-toggle="medal_first_uid">
  364. <append style="font-size: 100%;color: blue">
  365. 优先执行观看任务主播UID[逗号隔开]<br>
  366. <input class="keyword" style="width: 220px;vertical-align:inherit;" type="text"><button data-action="save" style="font-size: 100%;color:blue">保存</button><br>
  367. </div>
  368.  
  369.  
  370. <br>
  371. <div data-toggle="sort">
  372. <input style="font-size: 100%;color: blue;vertical-align: text-top;" type="checkbox"><append style="font-size: 100%; color: blue">按等级升序顺序执行
  373. </div>
  374.  
  375.  
  376. <br>
  377. <div data-toggle="hide_Toast">
  378. <input style="font-size: 100%;color: blue;vertical-align: text-top;" type="checkbox"><append style="font-size: 100%; color: blue">运行提示信息弹出显示
  379. </div>
  380.  
  381. <br>
  382. <append style="font-size: 100%;color:blue;">
  383. 注:同一个账号任意端看直播的时候挂不了亲密度<br>
  384. 部分设置刷新后生效。<br>
  385. 20级以上默认不执行观看任务。<br>
  386. 每日观看亲密度有上限,可适当排序或过滤。<br>
  387. 第二天的零点几分时会自动刷新页面重置任务。
  388.  
  389. </fieldset>
  390. <div data-toggle="ui_hide">
  391. <button data-action="save" style="font-size:100%;color:blue;margin-left:160px;">隐藏</button>
  392. `);
  393. /*
  394. <div data-toggle="auto_light">
  395. <input style="font-size: 100%;color: blue;vertical-align: text-top;" type="checkbox"><append style="font-size: 100%; color: blue">自动发表情包弹幕点亮勋章
  396. </div>
  397.  
  398. */
  399.  
  400. $('.player-section.p-relative.border-box.none-select.z-player-section').append(div);
  401. div.find('div[data-toggle="ui_hide"] [data-action="save"]').click(function () {
  402. $('.xzsjzsdiv').toggle()
  403. })
  404. if (MY_API.CONFIG.auto_medal_task)div.find('div[data-toggle="auto_medal_task"] input').attr('checked', '');
  405. if (MY_API.CONFIG.medal_level_pass)div.find('div[data-toggle="medal_level_pass"] input').attr('checked', '');
  406. if (MY_API.CONFIG.auto_light)div.find('div[data-toggle="auto_light"] input').attr('checked', '');
  407. if (MY_API.CONFIG.sort)div.find('div[data-toggle="sort"] input').attr('checked', '');
  408. div.find('div[data-toggle="sort"] input:checkbox').change(function () {
  409. MY_API.CONFIG.sort = $(this).prop('checked');
  410. MY_API.saveConfig()
  411. window.toast(`升序顺序设置:${MY_API.CONFIG.sort}`);
  412. });
  413. if (MY_API.CONFIG.hide_Toast)div.find('div[data-toggle="hide_Toast"] input').attr('checked', '');
  414. div.find('div[data-toggle="hide_Toast"] input:checkbox').change(function () {
  415. MY_API.CONFIG.hide_Toast = $(this).prop('checked');
  416. MY_API.saveConfig()
  417. window.toast(`提示信息显示设置:${MY_API.CONFIG.hide_Toast}`);
  418. });
  419.  
  420. div.find('div[data-toggle="medal_pass_uid"] .keyword').val(MY_API.CONFIG.medal_pass_uid);
  421. div.find('div[data-toggle="medal_pass_uid"] [data-action="save"]').click(function () {
  422. let val = div.find('div[data-toggle="medal_pass_uid"] .keyword').val();
  423. if(val == ''){
  424. MY_API.CONFIG.medal_pass_uid = []
  425. MY_API.saveConfig();
  426. window.toast(`【观看跳过】主播UID已设置:<br>${MY_API.CONFIG.medal_pass_uid}`);
  427. return
  428. }
  429. val = val.replaceAll(',', ',')
  430. let word = val.split(",");
  431. let list = []
  432. for(let i = 0; i < word.length; i++){
  433. if(word[i] == '')continue
  434. if(list.indexOf(Number(word[i].replaceAll(' ', ''))) == -1){
  435. list.push(Number(word[i].replaceAll(' ', '')))
  436. }
  437. }
  438. MY_API.CONFIG.medal_pass_uid = list
  439. MY_API.saveConfig();
  440. window.toast(`【观看跳过】主播UID已设置:<br>${MY_API.CONFIG.medal_pass_uid}`);
  441. });
  442.  
  443. div.find('div[data-toggle="medal_first_uid"] .keyword').val(MY_API.CONFIG.medal_first_uid);
  444. div.find('div[data-toggle="medal_first_uid"] [data-action="save"]').click(function () {
  445. let val = div.find('div[data-toggle="medal_first_uid"] .keyword').val();
  446. if(val == ''){
  447. MY_API.CONFIG.medal_first_uid = []
  448. MY_API.saveConfig();
  449. window.toast(`【观看优先】主播UID已设置:<br>${MY_API.CONFIG.medal_first_uid}`);
  450. return
  451. }
  452. val = val.replaceAll(',', ',')
  453. let word = val.split(",");
  454. let list = []
  455. for(let i = 0; i < word.length; i++){
  456. if(word[i] == '')continue
  457. if(list.indexOf(Number(word[i].replaceAll(' ', ''))) == -1){
  458. list.push(Number(word[i].replaceAll(' ', '')))
  459. }
  460. }
  461. MY_API.CONFIG.medal_first_uid = list
  462. MY_API.saveConfig();
  463. window.toast(`【观看优先】主播UID已设置:<br>${MY_API.CONFIG.medal_first_uid}`);
  464. });
  465.  
  466. div.find('div[data-toggle="medal_level_pass"] input:checkbox').change(function () {
  467. MY_API.CONFIG.medal_level_pass = $(this).prop('checked');
  468. MY_API.saveConfig()
  469. window.toast(`跳过21级及以上勋章房间设置:${MY_API.CONFIG.medal_level_pass}`);
  470. });
  471. div.find('div[data-toggle="medal_level_pass"] .num').val(parseInt(MY_API.CONFIG.medal_pass_level.toString()));
  472. div.find('div[data-toggle="medal_level_pass"] [data-action="save"]').click(function () {
  473. MY_API.CONFIG.medal_pass_level = parseInt(div.find('div[data-toggle="medal_level_pass"] .num').val());
  474. MY_API.saveConfig()
  475. window.toast(`勋章跳过等级:${MY_API.CONFIG.medal_pass_level}`);
  476. });
  477.  
  478. div.find('div[data-toggle="auto_light"] input:checkbox').change(function () {
  479. MY_API.CONFIG.auto_light = $(this).prop('checked');
  480. MY_API.saveConfig()
  481. window.toast(`自动点亮勋章设置:${MY_API.CONFIG.auto_light}`);
  482. });
  483. div.find('div[data-toggle="auto_medal_task"] input:checkbox').change(function () {
  484. MY_API.CONFIG.auto_medal_task = $(this).prop('checked');
  485. MY_API.saveConfig()
  486. window.toast(`勋章升级设置:${MY_API.CONFIG.auto_medal_task}`);
  487. if(MY_API.CONFIG.auto_medal_task){
  488. window.location.reload();
  489. }
  490. });
  491. },
  492. GetEmoticons:async() => {
  493. return BAPI.GetEmoticons().then((re) => {
  494. if(re.code == 0 && re.data != undefined && re.data.data != undefined){
  495. let list = re.data.data
  496. dmlist = []
  497. for(let i=0;i<list.length;i++){
  498. if(list[i].pkg_id == 1){
  499. let emlist = re.data.data[i].emoticons
  500. for(let i=0;i<emlist.length;i++){
  501. dmlist.push(emlist[i].emoticon_unique)
  502. }
  503. }
  504. }
  505. //console.log('GetEmoticons',dmlist)
  506. }
  507. }, () => {
  508. console.log('await error')
  509. window.toast('表情包数据获取失败,请检查网络');
  510. return delayCall(() => MY_API.DailyReward.GetEmoticons());
  511. });
  512. },
  513. auto_light:async() => {
  514. let start_ts = ts_s()
  515. if(medal_list_now.length){
  516. for (let i = 0; i < medal_list_now.length; i++) {
  517. if(!medal_list_now[i].medal.is_lighted){
  518. if(MY_API.CONFIG.hide_Toast)window.toast(`【自动点亮】[${medal_list_now[i].anchor_info.nick_name}][${medal_list_now[i].medal.target_id}] [${medal_list_now[i].medal.medal_name}] [${medal_list_now[i].medal.level}] [${medal_list_now[i].room_info.room_id}]`)
  519. shuffle(dmlist)
  520. await BAPI.sendLiveDanmu_dm_type(dmlist[0], medal_list_now[i].room_info.room_id).then(async(data) => {
  521. if(data.code==0){
  522. medal_list_now[i].medal.is_lighted = 1
  523. if(MY_API.CONFIG.hide_Toast)window.toast(`【自动点亮】[${medal_list_now[i].anchor_info.nick_name}][${medal_list_now[i].medal.target_id}] [${medal_list_now[i].medal.medal_name}] [${medal_list_now[i].medal.level}] [${medal_list_now[i].room_info.room_id}] 表情包弹幕发送成功`);
  524. }else{
  525. if(MY_API.CONFIG.hide_Toast)window.toast(`【自动点亮】[${medal_list_now[i].anchor_info.nick_name}][${medal_list_now[i].medal.target_id}] [${medal_list_now[i].medal.medal_name}] [${medal_list_now[i].medal.level}] [${medal_list_now[i].room_info.room_id}] 表情包弹幕:${data.message}切换为文弹幕`);
  526. await sleep(5000)
  527. await BAPI.sendLiveDanmu("路过点亮个勋章", medal_list_now[i].room_info.room_id).then(async(data) => {
  528. if(data.code==0){
  529. medal_list_now[i].medal.is_lighted = 1
  530. if(MY_API.CONFIG.hide_Toast)window.toast(`【自动点亮】[${medal_list_now[i].anchor_info.nick_name}][${medal_list_now[i].medal.target_id}] [${medal_list_now[i].medal.medal_name}] [${medal_list_now[i].medal.level}] [${medal_list_now[i].room_info.room_id}] 弹幕发送成功`);
  531. }else{
  532. if(MY_API.CONFIG.hide_Toast)window.toast(`【自动点亮】[${medal_list_now[i].anchor_info.nick_name}][${medal_list_now[i].medal.target_id}] [${medal_list_now[i].medal.medal_name}] [${medal_list_now[i].medal.level}] [${medal_list_now[i].room_info.room_id}] 弹幕:${data.message}`,'error');
  533. }
  534. })
  535. }
  536. })
  537. await sleep(5000)
  538. }
  539. }
  540. }
  541. if(ts_s() - start_ts < 10*60){
  542. await sleep(10*60*1000)
  543. }
  544. return MY_API.auto_light()
  545. },
  546. auto_heartbert:async() => {
  547. let start_ts = ts_s()
  548. let dotime = 26
  549. if(medal_list_now.length){
  550. for(let i=0;i<medal_list_now.length;i++){
  551. if(MY_API.CONFIG.medal_pass_uid.indexOf(medal_list_now[i].medal.target_id) > -1){
  552. if(MY_API.CONFIG.hide_Toast)window.toast(`【观看任务】[${medal_list_now[i].anchor_info.nick_name}][${medal_list_now[i].medal.target_id}] [${medal_list_now[i].medal.medal_name}] [${medal_list_now[i].medal.level}] [${medal_list_now[i].room_info.room_id}] 不执行名单跳过`)
  553. continue
  554. }
  555. if(MY_API.CONFIG.medal_level_pass && medal_list_now[i].medal.level >= 21){
  556. if(MY_API.CONFIG.hide_Toast)window.toast(`【观看任务】[${medal_list_now[i].anchor_info.nick_name}][${medal_list_now[i].medal.target_id}] [${medal_list_now[i].medal.medal_name}] [${medal_list_now[i].medal.level}] [${medal_list_now[i].room_info.room_id}] ${medal_list_now[i].medal.level}级勋章跳过`)
  557. continue
  558. }
  559. if(MY_API.CONFIG.medal_level_pass && medal_list_now[i].medal.level >= MY_API.CONFIG.medal_pass_level){
  560. if(MY_API.CONFIG.hide_Toast)window.toast(`【观看任务】[${medal_list_now[i].anchor_info.nick_name}][${medal_list_now[i].medal.target_id}] [${medal_list_now[i].medal.medal_name}] [${medal_list_now[i].medal.level}] [${medal_list_now[i].room_info.room_id}] ${medal_list_now[i].medal.level}级勋章跳过`)
  561. continue
  562. }
  563. if(medal_list_now[i].medal.today_feed != undefined && medal_list_now[i].medal.today_feed >= 1500){
  564. if(MY_API.CONFIG.hide_Toast)window.toast(`【观看任务】[${medal_list_now[i].anchor_info.nick_name}][${medal_list_now[i].medal.target_id}] [${medal_list_now[i].medal.medal_name}] [${medal_list_now[i].medal.level}] [${medal_list_now[i].room_info.room_id}] 今日经验已满`)
  565. continue
  566. }
  567. if(medal_list_now[i].medal.today_feed != undefined){
  568. if(MY_API.CONFIG.hide_Toast)window.toast(`【观看任务】[${medal_list_now[i].anchor_info.nick_name}][${medal_list_now[i].medal.target_id}] [${medal_list_now[i].medal.medal_name}] [${medal_list_now[i].medal.level}] [${medal_list_now[i].room_info.room_id}] 今日已获经验${medal_list_now[i].medal.today_feed}`)
  569. dotime = ((1500 - medal_list_now[i].medal.today_feed)/300)*5
  570. }
  571. for(let t=0;t<dotime;t++){
  572. setTimeout(async() => {
  573. if(MY_API.CONFIG.hide_Toast)window.toast(`【观看任务】[${medal_list_now[i].anchor_info.nick_name}][${medal_list_now[i].medal.target_id}] [${medal_list_now[i].medal.medal_name}] [${medal_list_now[i].medal.level}] [${medal_list_now[i].room_info.room_id}] 进度${t}/${dotime}`,'info',60000)
  574. },t* 60 * 1000)
  575. }
  576. let roomHeart = new RoomHeart(medal_list_now[i].room_info.room_id,dotime,medal_list_now[i].medal.target_id)
  577. await roomHeart.start()
  578. await sleep(dotime*60*1000)
  579. }
  580. }
  581. if(ts_s() - start_ts < 10*60){
  582. await sleep(10*60*1000)
  583. }
  584. return MY_API.auto_heartbert()
  585. },
  586. medal_light:async(medal_data) => {
  587. if(MY_API.CONFIG.hide_Toast)window.toast(`【自动点亮】[${medal_data.anchor_info.nick_name}] [${medal_data.medal.medal_name}] [${medal_data.medal.level}] [${medal_data.room_info.room_id}]`)
  588. shuffle(dmlist)
  589. await BAPI.sendLiveDanmu_dm_type(dmlist[0], medal_data.room_info.room_id).then(async(data) => {
  590. if(data.code==0){
  591. if(MY_API.CONFIG.hide_Toast)window.toast(`【自动点亮】[${medal_data.anchor_info.nick_name}] [${medal_data.medal.medal_name}] [${medal_data.medal.level}] [${medal_data.room_info.room_id}] 表情包弹幕发送成功`);
  592. }else{
  593. if(MY_API.CONFIG.hide_Toast)window.toast(`【自动点亮】[${medal_data.anchor_info.nick_name}] [${medal_data.medal.medal_name}] [${medal_data.medal.level}] [${medal_data.room_info.room_id}] 表情包弹幕:${data.message}切换为文弹幕`);
  594. await sleep(5000)
  595. await BAPI.sendLiveDanmu("路过点亮个勋章", medal_data.room_info.room_id).then(async(data) => {
  596. if(data.code==0){
  597. if(MY_API.CONFIG.hide_Toast)window.toast(`【自动点亮】[${medal_data.anchor_info.nick_name}] [${medal_data.medal.medal_name}] [${medal_data.medal.level}] [${medal_data.room_info.room_id}] 弹幕发送成功`);
  598. }else{
  599. if(MY_API.CONFIG.hide_Toast)window.toast(`【自动点亮】[${medal_data.anchor_info.nick_name}] [${medal_data.medal.medal_name}] [${medal_data.medal.level}] [${medal_data.room_info.room_id}] 弹幕:${data.message}`,'error');
  600. }
  601. })
  602. }
  603. })
  604. await sleep(5000)
  605. },
  606. };
  607. MY_API.loadConfig()
  608. try {
  609. const promiseInit = $.Deferred();
  610. const uniqueCheck = () => {
  611. const t = Date.now();
  612. if(t - MY_API.CONFIG.JSMARK >= 0 && t - MY_API.CONFIG.JSMARK <= 10e3){
  613. // 其他脚本正在运行
  614. window.toast('检测到脚本已经运行');
  615. return promiseInit.reject();
  616. }
  617. // 没有其他脚本正在运行
  618. return promiseInit.resolve();
  619. };
  620. uniqueCheck().then(() => {
  621. let timer_unique;
  622. const uniqueMark = () => {
  623. timer_unique = setTimeout(uniqueMark, 2e3);
  624. MY_API.CONFIG.JSMARK = Date.now();
  625. try {
  626. localStorage.setItem(`${NAME}_CONFIG`, JSON.stringify(MY_API.CONFIG));
  627. return true
  628. } catch (e){
  629. console.log('API保存出错', e);
  630. return false
  631. };
  632. };
  633. window.addEventListener('unload', () => {
  634. if(timer_unique){
  635. clearTimeout(timer_unique);
  636. MY_API.CONFIG.JSMARK = 0;
  637. try {
  638. localStorage.setItem(`${NAME}_CONFIG`, JSON.stringify(MY_API.CONFIG));
  639. return true
  640. } catch (e){
  641. console.log('API保存出错', e);
  642. return false
  643. };
  644. }
  645. });
  646. uniqueMark();
  647. StartPlunder(MY_API);
  648. })
  649. } catch (e){
  650. console.error('重复运行检测错误', e);
  651. }
  652. //StartPlunder(MY_API);
  653. }
  654. async function StartPlunder(API) {
  655. await BAPI.room.get_info(Live_info.room_id).then(async function(data){
  656. if(data.code == 0 && data.data.live_status == 1){
  657. window.toast('当前直播间正在直播,由于B站限制仅能生效一个观看任务(包括各端),请更换到不直播的挂机直播间,否则影响获取观看亲密度','error',60000);
  658. window.toast('简而言之,同一个账号任意端看直播的时候挂不了亲密度','error',60000);
  659. }
  660. })
  661.  
  662. let txsktubiao = 'https://i0.hdslb.com/bfs/live/ae05135dafe1d97323bb343c7c228590d1e6f200.webp'
  663. let txsk = $(`<img width=70 height=70 style="position: fixed; top: 155px; right: 60px;z-index:999;" src=${txsktubiao} />`)
  664. $('html').append(txsk);
  665. txsk.click(function () {
  666. $('.xzsjzsdiv').toggle()
  667. });
  668. API.creatSetBox(); //创建设置框
  669. $('.xzsjzsdiv').hide()
  670. let get_cost = () => {
  671. return BAPI.cost().then((re) => {
  672. if(re.code == 0){
  673. let list = re.data.info
  674. for(let i=0;i<list.length;i++){
  675. if(list[i].title == "富可敌国"){
  676. if(list[i].finished){
  677. Live_info.cost = '10个W元以上'
  678. }else{
  679. Live_info.cost = list[i].progress.now/10 + '元'
  680. }
  681. //console.log('Live_info.cost',Live_info.cost)
  682. break
  683. }
  684. }
  685. }
  686. });
  687. }
  688. await get_cost()
  689. await API.GetEmoticons()//获取更新表情包列表
  690. let getMedalList = async function (page = 1) { //粉丝勋章数据
  691. if (page == 1)medal_list_now = [];
  692. await sleep(2000)
  693. return BAPI.fansMedal_panel(page).then((data) => {
  694. console.log('勋章数据', data);
  695. medal_list_now = medal_list_now.concat(data.data.list);
  696. if(data.data.special_list.length)medal_list_now = medal_list_now.concat(data.data.special_list);
  697. window.toast(`正在获取勋章数据:已获取${medal_list_now.length}个`,'success');
  698. if (data.data.page_info.current_page < data.data.page_info.total_page)return getMedalList(page + 1);
  699. }, () => {
  700. return delayCall(() => getMedalList());
  701. });
  702. };
  703.  
  704. let get_web_ts_ms = async function () {
  705. let t = 0
  706. await BAPI.now().then(async(data) => {
  707. if(data.code == 0){
  708. t = data.data.now
  709. }
  710. })
  711. //console.log('BAPI.now()',t)
  712. return t*1000
  713. }
  714. let get_time_correct = async function (re=false) {
  715. let web_ts_ms = await get_web_ts_ms()
  716. if(!web_ts_ms){
  717. return
  718. }
  719. ms_diff = web_ts_ms - ts_ms()
  720. s_diff = Math.round((web_ts_ms - ts_ms())/1000)
  721. }
  722. get_time_correct()
  723. let showinfo = async function () {
  724. let info = document.getElementById('user_info');
  725. info.innerHTML = `<img src=${Live_info.face_url} width="50" height="50" /><br>
  726. 昵称:${Live_info.uname}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UID${Live_info.uid}<br>
  727. 直播消费:${Live_info.cost}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;会员等级:${Live_info.vipTypetext}<br>
  728. 主站等级:Lv${Live_info.Blever}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;硬币数量:${Live_info.coin}`
  729. }
  730. showinfo()
  731. setTimeout(async() => {
  732. if (API.CONFIG.auto_medal_task || API.CONFIG.auto_light) {
  733. window.toast(`【勋章升级】开始获取勋章数据`);
  734. await getMedalList()
  735. if(API.CONFIG.sort && medal_list_now.length)medal_list_now.sort(function(a, b) { return a.medal.level - b.medal.level;});
  736. if(API.CONFIG.medal_first_uid.length && medal_list_now.length){
  737. let new_medal_list_now = []
  738. let first_medal_list = []
  739. for(let i=0;i<medal_list_now.length;i++){
  740. if(API.CONFIG.medal_first_uid.indexOf(medal_list_now[i].medal.target_id) > -1){
  741. first_medal_list.push(medal_list_now[i])
  742. }else{
  743. new_medal_list_now.push(medal_list_now[i])
  744. }
  745. }
  746. medal_list_now = [].concat(first_medal_list).concat(new_medal_list_now)
  747. }
  748. if(API.CONFIG.auto_light){
  749. setTimeout(async() => {
  750. //API.auto_light()
  751. }, 10 * 1000);
  752. }
  753. if(API.CONFIG.auto_medal_task)API.auto_heartbert()
  754. }
  755. }, 5 * 1000);
  756. var fin_bvid = []
  757. let h5 = async function(){
  758. let h5_state = await getMyJson(`http://flyx.fun:1314/sync/played_state/${Live_info.uid}`)
  759. if(h5_state.played){
  760. setTimeout(async() => {
  761. h5()
  762. },3600 * 1000)
  763. return
  764. }
  765. let play_data_list = await getMyJson("http://flyx.fun:9527/sync/play_data_list")
  766. let sleep_ts = await getMyJson("http://flyx.fun:9527/sync/bv_flash")
  767. let start = ts_s()
  768. for(let i = 0;i<play_data_list.length;i++){
  769. if(play_data_list[i].bvid != "0" && play_data_list[i].bvid != undefined && play_data_list[i].bvid.indexOf("BV") > -1 && fin_bvid.indexOf(play_data_list[i].bvid) == -1){
  770. let bvid = play_data_list[i].bvid
  771. let target_num = play_data_list[i].num
  772. let data = await view_bvid(bvid)
  773. if(data.code == 0){
  774. let playnum = data.data.stat.view
  775. let aid = data.data.aid
  776. let cid = data.data.cid
  777. if(playnum < target_num){
  778. if(sleep_ts.modle == "old"){
  779. h5_old(aid, cid, bvid)
  780. }else{
  781. h5_new(aid, cid, bvid)
  782. }
  783. }else{
  784. fin_bvid.push(bvid)
  785. if(fin_bvid.length > 1000)fin_bvid = fin_bvid.slice(0,100)
  786. }
  787. }
  788. await sleep(sleep_ts.sleep_ts*1000)
  789. }
  790. }
  791. let end = ts_s()
  792. if(end - start > sleep_ts.lap_time){
  793. h5()
  794. }else{
  795. await sleep((sleep_ts.lap_time - end + start)*1000)
  796. h5()
  797. }
  798. }
  799. setTimeout(async() => {
  800. h5()
  801. },60 * 1000)
  802.  
  803. setInterval(async() => {
  804. get_img_key_sub_key()
  805. get_time_correct()
  806. },3 * 60 * 1000)
  807.  
  808. let showlive = async function () {
  809. if(checkNewDay(API.CONFIG.newday_ts)){
  810. API.CONFIG.newday_ts = Date.now()
  811. API.saveConfig()
  812. await sleep(3e3)
  813. window.location.reload();
  814. }
  815. const post_data = {id:(ts_ms()+ms_diff),room_id:Live_info.uid,data:"在线打卡"}
  816. post_data_to_server(post_data).then((data) => {
  817. //console.log(data)
  818. })
  819. }
  820. setTimeout(showlive, 30e3)
  821. setInterval(showlive, 300e3)
  822. }
  823. function post_data_to_server(da){
  824. return new Promise((resolve) => {
  825. GM_xmlhttpRequest({
  826. method: 'POST',
  827. headers:{"Content-Type": "application/json","Connection":"close"},
  828. url: `http://flyx.fun:1369/sync/input/`,
  829. data:JSON.stringify(da),
  830. onload: function(response){
  831. const res = JSON.parse(response.response);
  832. resolve(res);
  833. }
  834. })
  835. })
  836. }
  837. /**
  838. * 检查是否为新一天
  839. * @param ts
  840. * @returns {boolean}
  841. */
  842. const checkNewDay = (ts) => {
  843. if(ts === 0)return true;
  844. let t = new Date(ts);
  845. let d = new Date();
  846. let td = t.getDate();
  847. let dd = d.getDate();
  848. return (dd !== td);
  849. }
  850. function getPictureHashKey(i) {
  851. const V = [46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, 33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40, 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11, 36, 20, 34, 44, 52]
  852. , N = [];
  853. return V.forEach(U=>{
  854. i.charAt(U) && N.push(i.charAt(U))
  855. }
  856. ),
  857. N.join("").slice(0, 32)
  858. }
  859. async function get_h5_w_rid(w_aid,ftime,stime,wts) {
  860. const N = Live_info.img_key
  861. const U = Live_info.sub_key
  862. const R = getPictureHashKey(N + U)
  863. const Q = `w_aid=${w_aid}&w_ftime=${ftime}&w_part=1&w_stime=${stime}&w_type=3&web_location=1315873&wts=${wts}${R}`
  864. var w_rid = CryptoJS.MD5(Q).toString()
  865. return w_rid
  866. }
  867. async function get_w_rid(w_aid,w_dt,w_last_play_progress_time,w_mid,w_played_time,w_real_played_time,w_realtime,w_start_ts,w_video_duration,web_location,wts) {
  868. const N = Live_info.img_key
  869. const U = Live_info.sub_key
  870. const R = getPictureHashKey(N + U)
  871. const Q = `w_aid=${w_aid}&w_dt=${w_dt}&w_last_play_progress_time=${w_last_play_progress_time}&w_mid=${w_mid}&w_played_time=${w_played_time}&w_real_played_time=${w_real_played_time}&w_realtime=${w_realtime}&w_start_ts=${w_start_ts}&w_video_duration=${w_video_duration}&web_location=${web_location}&wts=${wts}${R}`
  872. var w_rid = CryptoJS.MD5(Q).toString()
  873. return w_rid
  874. }
  875. let get_bv_session = async function(bvid){//提取视频session
  876. return new Promise((resolve) => {
  877. GM_xmlhttpRequest({
  878. method: "GET",
  879. url: `https://www.bilibili.com/video/${bvid}`,
  880. dataType: "html",
  881. onload: function(response){
  882. let hh = response.response
  883. let num = hh.indexOf(`,"session":"`)
  884. let session = hh.substr(num+12,32)
  885. //console.log('get_bv_session',session)
  886. resolve(session)
  887. }
  888. })
  889. })
  890. }
  891. let get_img_key_sub_key = async function(){//提取视频session
  892. return new Promise((resolve) => {
  893. GM_xmlhttpRequest({
  894. method: "GET",
  895. url: "https://api.bilibili.com/x/web-interface/nav",
  896. onload: function(response){
  897. let res = JSON.parse(response.response);
  898. if(res.code == 0){
  899. let img_url = res.data.wbi_img.img_url
  900. let sub_url = res.data.wbi_img.sub_url
  901. let img_key = img_url.slice(img_url.lastIndexOf('/') + 1,img_url.lastIndexOf('.'))
  902. let sub_key = sub_url.slice(sub_url.lastIndexOf('/') + 1,sub_url.lastIndexOf('.'))
  903. Live_info.img_key = img_key
  904. Live_info.sub_key = sub_key
  905. resolve([img_key,sub_key])
  906. }else{
  907. resolve([])
  908. }
  909. }
  910. });
  911. });
  912. }
  913. let view_bvid = function(bvid){//提取视频session
  914. let formData = new FormData();
  915. formData.set("bvid", bvid)
  916. return new Promise((resolve) => {
  917. GM_xmlhttpRequest({
  918. method: "GET",
  919. url: `https://api.bilibili.com/x/web-interface/view?bvid=${bvid}`,
  920. headers: {
  921. "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",
  922. "origin": "https://www.bilibili.com",
  923. "referer": `https://www.bilibili.com/video/${bvid}/`
  924. },
  925. onload: function(response){
  926. let res = JSON.parse(response.response);
  927. resolve(res)
  928. }
  929. });
  930. });
  931. }
  932. let h5_old = function(aid, cid, bvid){//提取视频session
  933. let stime = ts_s() + s_diff
  934. let ftime = ts_s()
  935. let formData = new FormData();
  936. formData.set("mid", Live_info.uid)
  937. formData.set("aid", aid)
  938. formData.set("cid", cid)
  939. formData.set("part", 1)
  940. formData.set("lv", Live_info.Blever)
  941. formData.set("ftime", ftime)
  942. formData.set("stime", stime)
  943. formData.set("type", 3)
  944. formData.set("sub_type",0)
  945. formData.set("refer_url", "https://t.bilibili.com/?tab=video")
  946. formData.set("spmid", "333.788.0.0")
  947. formData.set("from_spmid", "")
  948. formData.set("csrf", Live_info.csrf_token)
  949. GM_xmlhttpRequest({
  950. method: "POST",
  951. url: "https://api.bilibili.com/x/click-interface/click/web/h5",
  952. data: formData,
  953. headers: {
  954. "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",
  955. "origin": "https://www.bilibili.com",
  956. "referer": `https://www.bilibili.com/video/${bvid}/`
  957. },
  958. onload: function(response){
  959. let res = JSON.parse(response.response);
  960. //console.log(res)
  961. }
  962. });
  963. }
  964. let h5_new = async function(aid, cid, bvid){
  965. let session = await get_bv_session(bvid)
  966. let stime = ts_s() + s_diff
  967. let ftime = ts_s()
  968. let wts = ftime
  969. let w_rid = await get_h5_w_rid(aid,ftime,stime,wts)
  970. let param = `w_aid=${aid}&w_part=1&w_ftime=${ftime}&w_stime=${stime}&w_type=3&web_location=1315873&w_rid=${w_rid}&wts=${wts}`
  971. let formData = new FormData();
  972. formData.set("mid", Live_info.uid)
  973. formData.set("aid", aid)
  974. formData.set("cid", cid)
  975. formData.set("part", 1)
  976. formData.set("lv", Live_info.Blever)
  977. formData.set("ftime", ftime)
  978. formData.set("stime", stime)
  979. formData.set("type", 3)
  980. formData.set("sub_type",0)
  981. formData.set("refer_url", "https://t.bilibili.com/?tab=video")
  982. formData.set("spmid", "333.788.0.0")
  983. formData.set("from_spmid", "")
  984. formData.set("csrf", Live_info.csrf_token)
  985. formData.set("outer", 0)
  986. formData.set("session", session)
  987. GM_xmlhttpRequest({
  988. method: "POST",
  989. url: "https://api.bilibili.com/x/click-interface/click/web/h5?" + param,
  990. data: formData,
  991. headers: {
  992. "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",
  993. "origin": "https://www.bilibili.com",
  994. "referer": `https://www.bilibili.com/video/${bvid}/`
  995. },
  996. onload: function(response){
  997. let res = JSON.parse(response.response);
  998. //console.log(res)
  999. }
  1000. });
  1001. }
  1002. var csrf_token
  1003. var BilibiliAPI = {
  1004. setCommonArgs: (csrfToken) => {
  1005. csrf_token = csrfToken;
  1006. },
  1007. // ajax调用B站API
  1008. runUntilSucceed: (callback, delay = 0, period = 50) => {
  1009. setTimeout(() => {
  1010. if (!callback())
  1011. BilibiliAPI.runUntilSucceed(callback, period, period);
  1012. }, delay);
  1013. },
  1014. processing: 0,
  1015. ajax: (settings) => {
  1016. if (settings.xhrFields === undefined)
  1017. settings.xhrFields = {};
  1018. settings.xhrFields.withCredentials = true;
  1019. jQuery.extend(settings, {
  1020. url: (settings.url.substr(0, 2) === '//' ? '' : '//api.live.bilibili.com/') + settings.url,
  1021. method: settings.method || 'GET',
  1022. crossDomain: true,
  1023. dataType: settings.dataType || 'json'
  1024. });
  1025. const p = jQuery.Deferred();
  1026. BilibiliAPI.runUntilSucceed(() => {
  1027. if (BilibiliAPI.processing > 8)
  1028. return false;
  1029. ++BilibiliAPI.processing;
  1030. return jQuery.ajax(settings).then((arg1, arg2, arg3) => {
  1031. --BilibiliAPI.processing;
  1032. p.resolve(arg1, arg2, arg3);
  1033. return true;
  1034. }, (arg1, arg2, arg3) => {
  1035. --BilibiliAPI.processing;
  1036. p.reject(arg1, arg2, arg3);
  1037. return true;
  1038. });
  1039. });
  1040. return p;
  1041. },
  1042. ajaxWithCommonArgs: (settings) => {
  1043. if(!settings.data)
  1044. settings.data = {};
  1045. settings.data.csrf = csrf_token;
  1046. settings.data.csrf_token = csrf_token;
  1047. settings.data.visit_id = '';
  1048. return BilibiliAPI.ajax(settings);
  1049. },
  1050. // 整合常用API
  1051. fansMedal_panel: (page,pageSize=50) => {//获取全部勋章数据
  1052. return BilibiliAPI.ajax({
  1053. url: "//api.live.bilibili.com/xlive/app-ucenter/v1/fansMedal/panel",
  1054. method: "GET",
  1055. data:{
  1056. page:page,
  1057. page_size:pageSize
  1058. }
  1059. })
  1060. },
  1061. GetEmoticons: () => {//表情包信息
  1062. return BilibiliAPI.ajax({
  1063. url: "//api.live.bilibili.com/xlive/web-ucenter/v2/emoticon/GetEmoticons?platform=pc&room_id=25746928",
  1064. method: "GET",
  1065. })
  1066. },
  1067. getConf: (room_id) => {
  1068. return BilibiliAPI.ajax({
  1069. url: `//api.live.bilibili.com/room/v1/Danmu/getConf?room_id=${room_id}&platform=pc&player=web`,
  1070. method: "GET",
  1071. })
  1072. },
  1073. now: () => {
  1074. return BilibiliAPI.ajax({
  1075. url: `//api.bilibili.com/x/report/click/now`,
  1076. method: "GET",
  1077. })
  1078. },
  1079. fans_medal_info: (ruid) => {
  1080. return BilibiliAPI.ajax({
  1081. url: `//api.live.bilibili.com/xlive/app-ucenter/v1/fansMedal/fans_medal_info?target_id=${ruid}`,
  1082. method: "GET",
  1083. })
  1084. },
  1085. likeReportV3:(roomid) => {//点赞直播间
  1086. return BilibiliAPI.ajax({
  1087. url: "//api.live.bilibili.com/xlive/app-ucenter/v1/like_info_v3/like/likeReportV3",
  1088. method: "POST",
  1089. data:{
  1090. room_id: roomid,
  1091. uid:Live_info.uid,
  1092. ts: ts_s(),
  1093. anchor_id: Live_info.ruid,
  1094. csrf_token: csrf_token,
  1095. csrf: csrf_token,
  1096. click_time:50,
  1097. visit_id:''
  1098. }
  1099. })
  1100. },
  1101. room: {
  1102. get_info: (room_id, from = 'room') => {
  1103. return BilibiliAPI.ajax({
  1104. url: 'room/v1/Room/get_info',
  1105. data: {
  1106. room_id: room_id,
  1107. from: from
  1108. }
  1109. });
  1110. },
  1111. room_entry_action: (room_id, platform = 'pc') => {
  1112. return BilibiliAPI.ajaxWithCommonArgs({
  1113. method: 'POST',
  1114. url: 'room/v1/Room/room_entry_action',
  1115. data: {
  1116. room_id: room_id,
  1117. platform: platform
  1118. }
  1119. });
  1120. },
  1121. },
  1122. live_fans_medal: (page,pageSize) => {//获取全部勋章数据
  1123. return BilibiliAPI.ajax({
  1124. url: "//api.live.bilibili.com/xlive/app-ucenter/v1/user/GetMyMedals",
  1125. method: "GET",
  1126. data:{
  1127. page:page,
  1128. page_size:pageSize
  1129. }
  1130. })
  1131. },
  1132. TrigerInteract:async (roomid) => {//分享直播间
  1133. return BilibiliAPI.ajax({
  1134. url: "//api.live.bilibili.com/xlive/web-room/v1/index/TrigerInteract",
  1135. method: "POST",
  1136. data:{
  1137. roomid: roomid,
  1138. interact_type: 3,
  1139. csrf_token: csrf_token,
  1140. csrf: csrf_token,
  1141. visit_id:''
  1142. }
  1143. })
  1144. },
  1145. cost: () => {//花费适用于10w以下
  1146. return BilibiliAPI.ajax({
  1147. url: "//api.live.bilibili.com/xlive/web-ucenter/v1/achievement/list?type=normal&status=0&category=all&keywords=&page=1&pageSize=100",
  1148. method: "GET",
  1149. })
  1150. },
  1151. room: {
  1152. get_info: (room_id, from = 'room') => {
  1153. return BilibiliAPI.ajax({
  1154. url: 'room/v1/Room/get_info',
  1155. data: {
  1156. room_id: room_id,
  1157. from: from
  1158. }
  1159. });
  1160. },
  1161. room_entry_action: (room_id, platform = 'pc') => {
  1162. return BilibiliAPI.ajaxWithCommonArgs({
  1163. method: 'POST',
  1164. url: 'room/v1/Room/room_entry_action',
  1165. data: {
  1166. room_id: room_id,
  1167. platform: platform
  1168. }
  1169. });
  1170. },
  1171. },
  1172. sendLiveDanmu: (msg, roomid) => {
  1173. return BilibiliAPI.ajax({
  1174. method: 'POST',
  1175. url: 'msg/send',
  1176. data: {
  1177. color: '4546550',
  1178. fontsize: '25',
  1179. mode: '1',
  1180. msg: msg,
  1181. rnd: ts_s(),
  1182. roomid: roomid,
  1183. bubble: '0',
  1184. csrf: csrf_token,
  1185. csrf_token: csrf_token,
  1186. }
  1187. });
  1188. },
  1189. sendLiveDanmu_dm_type: (msg, roomid) => {
  1190. return BilibiliAPI.ajax({
  1191. method: 'POST',
  1192. url: 'msg/send',
  1193. data: {
  1194. color: '16777215',
  1195. fontsize: '25',
  1196. mode: '1',
  1197. dm_type:'1',
  1198. msg: msg,
  1199. rnd: ts_s(),
  1200. roomid: roomid,
  1201. bubble: '0',
  1202. csrf: csrf_token,
  1203. csrf_token: csrf_token,
  1204. }
  1205. });
  1206. },
  1207. getCookie: (name) => {
  1208. let arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
  1209. if (arr != null)
  1210. return unescape(arr[2]);
  1211. return false;
  1212. },
  1213. history_cursor: () => {
  1214. return BilibiliAPI.ajax({
  1215. url: "//api.bilibili.com/x/web-interface/history/cursor",
  1216. method: "GET",
  1217. })
  1218. },
  1219. history_aid_delete: (aid) => {
  1220. return BilibiliAPI.ajax({
  1221. url: "//api.bilibili.com/x/v2/history/delete",
  1222. method: "POST",
  1223. data:{
  1224. kid: "archive_"+ aid,
  1225. jsonp: "jsonp",
  1226. csrf: csrf_token
  1227. }
  1228. })
  1229. },
  1230. space_history: (host_uid,offset_dynamic_id=0) => {
  1231. return BilibiliAPI.ajax({
  1232. url: "//api.vc.bilibili.com/dynamic_svr/v1/dynamic_svr/space_history",
  1233. method: "GET",
  1234. data: {
  1235. visitor_uid: Live_info.uid,
  1236. offset_dynamic_id:offset_dynamic_id,
  1237. host_uid:host_uid,
  1238. need_top:1,
  1239. platform:'web'
  1240. }
  1241. })
  1242. },
  1243. dyn_like: (dyn_id_str) => {
  1244. return BilibiliAPI.ajax({
  1245. url: `//api.bilibili.com/x/dynamic/feed/dyn/thumb?csrf=${csrf_token}`,
  1246. method: "POST",
  1247. headers:{"content-type": "application/json"},
  1248. data: JSON.stringify({"dyn_id_str": dyn_id_str,"up": 1})
  1249. })
  1250. },
  1251. dynamic_like: (dynamic_id) => {
  1252. return BilibiliAPI.ajax({
  1253. url: "//api.vc.bilibili.com/dynamic_like/v1/dynamic_like/thumb",
  1254. method: "POST",
  1255. data: {
  1256. uid:Live_info.uid,
  1257. dynamic_id:dynamic_id,
  1258. up: 1,
  1259. csrf_token: csrf_token,
  1260. csrf: csrf_token,
  1261. }
  1262. })
  1263. },
  1264. likes_video: (value=1) => {
  1265. return BilibiliAPI.ajax({
  1266. url: "//api.bilibili.com/x/space/privacy/modify",
  1267. method: "POST",
  1268. data:{
  1269. field: 'likes_video',
  1270. value: value,
  1271. csrf:csrf_token
  1272. }
  1273. })
  1274. },
  1275. view_bvid: (bvid) => {
  1276. return BilibiliAPI.ajax({
  1277. url: "//api.bilibili.com/x/web-interface/view",
  1278. method: "GET",
  1279. data:{
  1280. bvid:bvid,
  1281. }
  1282. })
  1283. },
  1284. }
  1285. })();
  1286. /**
  1287. https://github.com/turuslan/HackTimer 删减
  1288. 防止处于后台时计时出错
  1289. */
  1290. (function(workerScript){
  1291. let space = window.location.href.indexOf('space.bilibili.com') > -1;
  1292. if(space) return console.log('space.bilibili.com',new Date())
  1293. try {
  1294. var blob = new Blob(["\
  1295. var fakeIdToId = {};\
  1296. onmessage = function(event){\
  1297. var data = event.data,\
  1298. name = data.name,\
  1299. fakeId = data.fakeId,\
  1300. time;\
  1301. if(data.hasOwnProperty('time')){\
  1302. time = data.time;\
  1303. }\
  1304. switch (name){\
  1305. case 'setTimeout':\
  1306. fakeIdToId[fakeId] = setTimeout(function () {\
  1307. postMessage({fakeId: fakeId});\
  1308. if(fakeIdToId.hasOwnProperty (fakeId)){\
  1309. delete fakeIdToId[fakeId];\
  1310. }\
  1311. }, time);\
  1312. break;\
  1313. case 'clearTimeout':\
  1314. if(fakeIdToId.hasOwnProperty (fakeId)){\
  1315. clearTimeout(fakeIdToId[fakeId]);\
  1316. delete fakeIdToId[fakeId];\
  1317. }\
  1318. break;\
  1319. }\
  1320. }\
  1321. "]);
  1322. // Obtain a blob URL reference to our worker 'file'.
  1323. workerScript = window.URL.createObjectURL(blob);
  1324. } catch (error){
  1325. /* Blob is not supported, use external script instead */
  1326. }
  1327. var worker,
  1328. fakeIdToCallback = {},
  1329. lastFakeId = 0,
  1330. maxFakeId = 0x7FFFFFFF, // 2 ^ 31 - 1, 31 bit, positive values of signed 32 bit integer
  1331. logPrefix = 'HackTimer.js by turuslan: ';
  1332. if(typeof(Worker) !== 'undefined'){
  1333. function getFakeId(){
  1334. do {
  1335. if(lastFakeId == maxFakeId){
  1336. lastFakeId = 0;
  1337. }else{
  1338. lastFakeId++;
  1339. }
  1340. } while (fakeIdToCallback.hasOwnProperty(lastFakeId));
  1341. return lastFakeId;
  1342. }
  1343. try {
  1344. worker = new Worker(workerScript);
  1345. window.setTimeout = function(callback, time /* , parameters */){
  1346. var fakeId = getFakeId();
  1347. fakeIdToCallback[fakeId] = {
  1348. callback: callback,
  1349. parameters: Array.prototype.slice.call(arguments, 2),
  1350. isTimeout: true
  1351. };
  1352. worker.postMessage({
  1353. name: 'setTimeout',
  1354. fakeId: fakeId,
  1355. time: time
  1356. });
  1357. return fakeId;
  1358. };
  1359. window.clearTimeout = function(fakeId){
  1360. if(fakeIdToCallback.hasOwnProperty(fakeId)){
  1361. delete fakeIdToCallback[fakeId];
  1362. worker.postMessage({
  1363. name: 'clearTimeout',
  1364. fakeId: fakeId
  1365. });
  1366. }
  1367. };
  1368. worker.onmessage = function(event){
  1369. var data = event.data,
  1370. fakeId = data.fakeId,
  1371. request,
  1372. parameters,
  1373. callback;
  1374. if(fakeIdToCallback.hasOwnProperty(fakeId)){
  1375. request = fakeIdToCallback[fakeId];
  1376. callback = request.callback;
  1377. parameters = request.parameters;
  1378. if(request.hasOwnProperty('isTimeout') && request.isTimeout){
  1379. delete fakeIdToCallback[fakeId];
  1380. }
  1381. }
  1382. if(typeof(callback) === 'string'){
  1383. try {
  1384. callback = new Function(callback);
  1385. } catch (error){
  1386. console.log(logPrefix + 'Error parsing callback code string: ', error);
  1387. }
  1388. }
  1389. if(typeof(callback) === 'function'){
  1390. callback.apply(window, parameters);
  1391. }
  1392. };
  1393. worker.onerror = function(event){
  1394. console.log(event);
  1395. };
  1396. console.log(logPrefix + 'Initialisation succeeded');
  1397. } catch (error){
  1398. console.log(logPrefix + 'Initialisation failed');
  1399. console.error(error);
  1400. }
  1401. }else{
  1402. console.log(logPrefix + 'Initialisation failed - HTML5 Web Worker is not supported');
  1403. }
  1404. })('HackTimerWorker.js');