哔哩哔哩勋章升级助手

自用脚本,不喜勿用哈~~哔哩哔哩加速勋章升级测试先行版:自动点赞(测试未能生效,暂不支持)、弹幕签到、观看获取亲密度

As of 2024-07-25. See the latest version.

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