哔哩哔哩工具合集-开发中

注:练手作品,多多包涵,不接受恶意差评,有问题群内咨询(Q群1031014013):一键播放所有视频;一键拉黑。。。(友情天选群746790091 )

目前為 2021-03-05 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/422731/907352/%E5%93%94%E5%93%A9%E5%93%94%E5%93%A9%E5%B7%A5%E5%85%B7%E5%90%88%E9%9B%86-%E5%BC%80%E5%8F%91%E4%B8%AD.js

  1. // ==UserScript==
  2. // @name 哔哩哔哩工具合集-开发中
  3. // @description 注:练手作品,多多包涵,不接受恶意差评,有问题群内咨询(Q群1031014013):一键播放所有视频;一键拉黑。。。(友情天选群746790091 )
  4. // @namespace http://tampermonkey.net/
  5. // @version 1.1.6
  6. // @description try to take over the world!
  7. // @author 荒年(QQ:2019676120)
  8. // @match *://space.bilibili.com/*
  9. // @require https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js
  10. // @resource animate http://cdn.javaex.cn/javaex/pc/css/animate.css
  11. // @resource common http://cdn.javaex.cn/javaex/pc/css/common.css
  12. // @resource defaultCss http://cdn.javaex.cn/javaex/pc/css/skin/default.css
  13. // @grant unsafeWindow
  14. // @grant GM_getValue
  15. // @grant GM_setValue
  16. // @grant GM_xmlhttpRequest
  17. // @grant GM_getResourceText
  18. // @grant GM_openInTab
  19. // @grant GM_addStyle
  20. // @run-at document-idle
  21. // @license MIT License
  22. // @namespace http://tampermonkey.net/
  23. // ==/UserScript==
  24.  
  25.  
  26. GM_addStyle(`
  27. #left_navbar{
  28. z-index: 1000;
  29. position: absolute;
  30. top: 100px;
  31. left: 5px;
  32. }
  33. button[hnBtn="btn_open"] {
  34. z-index: 1001;
  35. z-index: 1000px;
  36. position: absolute;
  37. top: 58px;
  38. left: 220px;
  39. }
  40. .javaex-panel.javaex-panel-right.javaex-animated-zoom-in {
  41. top: 60px;
  42. }
  43. .javaex-menu-container {
  44. border: 1px solid #eee;
  45. }
  46. .javaex-panel-box p {
  47. text-align: center;
  48. background: #fb7299;
  49. }
  50. .fontbold{
  51. color: #00a1d6;
  52. font-weight: bold;
  53. cursor: pointer;
  54. }
  55. `);
  56.  
  57. let Live_info = {
  58. author_uid: 99439379,
  59. room_id: undefined,
  60. uid: undefined,
  61. blocked: undefined,
  62. csrf_token: undefined,
  63. visit_id: undefined,
  64. rnd: undefined,
  65. ruid: undefined,
  66. uname: undefined,
  67. user_level: undefined,
  68. ruid: undefined,
  69. };
  70.  
  71. let BILIBLI_PATH = {
  72.  
  73. "passport": "https://passport.bilibili.com",
  74. "api": "https://api.bilibili.com",
  75. "video": "https://www.bilibili.com/video/",
  76. "single_unread": "http://api.vc.bilibili.com/"
  77. }
  78. /**
  79. * 参考 https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/login/login_info.md
  80. * @type {{nav: string}}
  81. */
  82. let BILIBILI_URL = {
  83. // 导航栏用户信息
  84. "nav": BILIBLI_PATH.api + "/x/web-interface/nav",
  85. }
  86.  
  87. let BiliData = {
  88. login_code: null,
  89. login_message: "",
  90. LoginData: {},
  91. CoinLog: {},
  92. Unread: null,
  93. Video: {},
  94. replyAction: {},
  95. upCard: {},
  96. BVList: [],
  97. }
  98.  
  99.  
  100. window.onload = function () {
  101.  
  102. let script = document.createElement('script');
  103. script.setAttribute('type', 'text/javascript');
  104. script.src = "https://cdn.jsdelivr.net/gh/java-xiaoyi/HNGG-RES@main/javaex/pc/js/javaex.min.js";
  105. document.documentElement.appendChild(script);
  106.  
  107. let script2 = document.createElement('script');
  108. script2.setAttribute('type', 'text/javascript');
  109. script2.src = "https://cdn.jsdelivr.net/gh/java-xiaoyi/HNGG-RES@main/javaex/pc/js/javaex-formVerify.js";
  110. document.documentElement.appendChild(script2);
  111.  
  112.  
  113. //界面显示
  114. init();
  115.  
  116. document.getElementById("getAtMsg").click();
  117.  
  118. }
  119.  
  120.  
  121. function init() {
  122.  
  123. Live_info.csrf_token = HNTOOL.getCookie("bili_jct");
  124. Live_info.uid = HNTOOL.getCookie("DedeUserID");
  125.  
  126. addStyle();
  127. addSetPage();
  128.  
  129. $("#getCoinLog").bind("click", async function () {
  130.  
  131.  
  132. if (HNAPI.getCoinLog()) {
  133.  
  134. await HNTOOL.Sleep(500);
  135. let html = '';
  136. html += '<div class="javaex-panel-box" style="width: 250px;">';
  137. html += ' <ul>';
  138. html += ` <p style="color: #FFF;">硬币使用记录</p>`;
  139.  
  140. BiliData.CoinLog.list.forEach(function (item) {
  141.  
  142. let BV = item.reason.replace(/[^a-z0-9]+/ig, "");
  143. if (BV.indexOf("BV") != -1) {
  144. html += `<li><a href="${BILIBLI_PATH.video}${BV}">${item.reason}${item.delta}币 ${item.time}</a> </li> `;
  145. }
  146. html += `<li>${item.reason}${item.delta}币 ${item.time}</li> `;
  147.  
  148.  
  149. });
  150. html += ' <hr class="javaex-divider"></hr>';
  151. html += ' </ul>';
  152. html += '</div>';
  153.  
  154. javaex.panel(this, {
  155. position: "right",
  156. //offsetTop: "104",
  157. content: html
  158. });
  159. javaex.tip({
  160. content: "获取用户成功!",
  161. type: "success"
  162. });
  163.  
  164. } else {
  165. javaex.tip({
  166. content: "获取硬币记录失败,请稍后重试!",
  167. type: "error"
  168. });
  169. }
  170.  
  171.  
  172. });
  173.  
  174. $("#getUnread").bind("click", async function () {
  175.  
  176. javaex.tip({
  177. content: "获取中,请稍候...",
  178. type: "submit"
  179. });
  180. HNAPI.getUnread();
  181.  
  182.  
  183. });
  184.  
  185.  
  186. $("#likeInDynamicComments").bind("click", async function () {
  187.  
  188. let prid = LocalData.get("likeInDynamic_PRID") == null ? "4015599048" : LocalData.get("likeInDynamic_PRID");
  189. let oid = LocalData.get("likeInDynamic_OID") == null ? "108928314" : LocalData.get("likeInDynamic_OID");
  190.  
  191. let html = '';
  192.  
  193. html += '<div style="padding: 10px 10px 10px 0px;">'
  194. html += '<form id="likeInDynamic_form">'
  195. html += ' <div class="javaex-unit clear">'
  196. html += ' <div class="javaex-unit-left"><p class="subtitle required">评论RPID</p></div>'
  197. html += ' <div class="javaex-unit-right">'
  198. html += ' <input type="text" class="javaex-text" data-type="positive_int" error-msg="评论RPID格式错误"'
  199. html += ` id="likeInDynamic_PRID" value=${prid} placeholder="请输入评论RPID"/>`
  200. html += ' </div>'
  201. html += ' </div>'
  202. html += ' <div class="javaex-unit clear">'
  203. html += ' <div class="javaex-unit-left"><p class="subtitle required">OID</p></div>'
  204. html += ' <div class="javaex-unit-right">'
  205. html += ' <input type="text" class="javaex-text" data-type="positive_int" error-msg="OID格式错误"'
  206. html += ` id="likeInDynamic_OID" value=${oid} placeholder="请输入OID"/>`
  207. html += ' </div>'
  208. html += ' </div>'
  209. html += ' <div class="javaex-unit clear tc">'
  210. html += ' <input type="button" id="likeInDynamic_no" class="javaex-hover-pulse javaex-btn no " value="取消赞"/>'
  211. html += ' <input type="button" id="likeInDynamic_yes" class="javaex-hover-pulse javaex-btn yes" value="点赞"/>'
  212. html += ' </div>'
  213. html += '</form>';
  214. html += '<hr class="javaex-divider"></hr>';
  215. html += '</div>';
  216.  
  217.  
  218. javaex.panel(this, {
  219. position: "right",
  220. content: html
  221. });
  222.  
  223.  
  224. // 监听点击保存按钮事件
  225. $("#likeInDynamic_yes").click(async function () {
  226. // 表单验证函数
  227. if (javaexVerify()) {
  228.  
  229. HNAPI.likeInDynamicComments(+javaex.getSelectVal("#likeInDynamic_OID"), +javaex.getSelectVal("#likeInDynamic_PRID"), 1);
  230. await HNTOOL.Sleep(1000);
  231.  
  232. if (BiliData.replyAction.code == 0) {
  233.  
  234. LocalData.set("likeInDynamic_PRID", javaex.getSelectVal("#likeInDynamic_PRID"));
  235. LocalData.set("likeInDynamic_OID", javaex.getSelectVal("#likeInDynamic_OID"));
  236.  
  237. javaex.tip({content: "评论区点赞成功!", type: "success"});
  238. } else {
  239. javaex.tip({content: "评论区点赞失败!", type: "error"});
  240. }
  241. if (BiliData.replyAction.code == 65006) {
  242. javaex.tip({content: "请勿重复点赞!", type: "error"});
  243. }
  244. }
  245. });
  246.  
  247. // 监听点击返回按钮事件
  248. $("#likeInDynamic_no").click(async function () {
  249.  
  250. if (javaexVerify()) {
  251.  
  252. HNAPI.likeInDynamicComments(+javaex.getLocalStorage("#likeInDynamic_OID"), +javaex.getLocalStorage("#likeInDynamic_PRID"), 0);
  253. await HNTOOL.Sleep(500);
  254.  
  255. if (BiliData.replyAction.code == 0) {
  256.  
  257. javaex.setLocalStorage("likeInDynamic_PRID", javaex.getSelectVal("#likeInDynamic_PRID"));
  258. javaex.setLocalStorage("likeInDynamic_OID", javaex.getSelectVal("#likeInDynamic_OID"));
  259.  
  260. javaex.tip({content: "评论区取消点赞成功!", type: "success"});
  261. } else {
  262. javaex.tip({content: "评论区取消点赞失败!", type: "error"});
  263. }
  264. if (BiliData.replyAction.code == 65006) {
  265. javaex.tip({content: "请勿重复取消点赞!", type: "error"});
  266. }
  267. }
  268. });
  269.  
  270. });
  271.  
  272. $("#biliUserMsg").bind("click", async function () {
  273.  
  274.  
  275. //刷新信息
  276. HNAPI.getUserNav();
  277. await HNTOOL.Sleep(500);
  278.  
  279. let isLogin = "未登录";
  280. let vipType = "无";
  281. //判断是否成功
  282. if (BiliData.login_code == 0) {
  283.  
  284.  
  285. if (BiliData.LoginData.isLogin) {
  286. isLogin = "已登录";
  287. }
  288.  
  289. if (BiliData.LoginData.vipType == 1) {
  290. vipType = "月度大会员";
  291. } else if (BiliData.LoginData.vipType == 2) {
  292. vipType = "年度大会员";
  293. }
  294.  
  295. let html = '';
  296. html += '<div class="javaex-panel-box" style="width: 250px;">';
  297. html += ' <ul>';
  298. html += ` <p style="color: #FFF;">用户信息</p>`;
  299. html += ` <li><a href="https://account.bilibili.com/account/home">当前用户:${BiliData.LoginData.uname}</a> </li> `;
  300. html += ` <li>用户状态:${isLogin} </li> `;
  301. html += ` <li>用户等级:${BiliData.LoginData.level_info.current_level}</li> `;
  302. html += ` <li>升级下一等级需:${BiliData.LoginData.level_info.next_exp - BiliData.LoginData.level_info.current_exp} 经验</li> `;
  303. html += ` <li>UID${BiliData.LoginData.mid} </li> `;
  304. html += ` <li><a href="https://account.bilibili.com/account/coin">硬币:${BiliData.LoginData.money}</a> </li> `;
  305. html += ` <li>节操值:${BiliData.LoginData.moral} </li> `;
  306. html += ` <li>会员:${vipType} </li> `;
  307. html += ' <hr class="javaex-divider"></hr>';
  308. html += ' </ul>';
  309. html += '</div>';
  310.  
  311.  
  312. javaex.panel(this, {
  313. position: "right",
  314. content: html
  315. });
  316.  
  317. javaex.tip({
  318. content: "获取用户成功!",
  319. type: "success"
  320. });
  321.  
  322. } else {
  323. javaex.tip({
  324. content: "获取用户信息失败!",
  325. type: "error"
  326. });
  327. }
  328.  
  329.  
  330. });
  331.  
  332. $("#getAtMsg").bind("click", async function () {
  333.  
  334. if (HNAPI.getMsgfeed("at") && typeof (HNAPI.getMsgfeed("at")) != "undefined") {
  335.  
  336. javaex.tip({
  337. content: "可能中奖了!!!",
  338. type: "success"
  339. });
  340. }
  341. });
  342.  
  343.  
  344. $("#disUser").bind("click", async function () {
  345.  
  346. let html = '';
  347. html += '<div class="javaex-panel-box" style="width: 500px;">';
  348. html += ' <div class="javaex-unit clear">';
  349. html += ' <div class="javaex-unit-left ml-10 mt-10">*拉黑列表</div>';
  350. html += ' <div class="javaex-unit-right mr-10 mt-10">';
  351. html += ' <textarea id="disUser_uidList" class="javaex-desc" placeholder="请填写用户UID,多个用英文逗号,隔开"></textarea>';
  352. html += ' </div>';
  353. html += ' </div>';
  354. html += ' <div class="javaex-unit clear tc">';
  355. html += ' <input type="button" id="disUser_beg" class="javaex-btn yes" value="开始" />';
  356. html += ' </div>';
  357. html += '</div>';
  358.  
  359. javaex.panel(this, {
  360. position: "right",
  361. content: html
  362. });
  363.  
  364. $("#disUser_beg").bind("click", async function () {
  365.  
  366. let disUser_str = javaex.getSelectVal("#disUser_uidList");
  367. let disUser_uidList = disUser_str.split(",");
  368.  
  369. for (const vmid of disUser_uidList) {
  370.  
  371. HNAPI.disUserByUid(vmid);
  372.  
  373. await HNTOOL.Sleep(1500);
  374.  
  375. }
  376.  
  377. });
  378.  
  379. });
  380.  
  381. //
  382. $("#getUpMassage").bind("click", async function () {
  383.  
  384.  
  385. let html = '';
  386.  
  387. html += '<div style="padding: 10px 10px 10px 0px;">'
  388. html += '<form id="getUpMassage_form">'
  389. html += ' <div class="javaex-unit clear">'
  390. html += ' <div class="javaex-unit-left mr-10"><p class="subtitle required">用户uid</p></div>'
  391. html += ' <div class="javaex-unit-left mr-10">'
  392. html += ' <input type="text" class="javaex-text javaex-grid-4" data-type="positive_int" error-msg="用户uid"'
  393. html += ` id="up_uid" value="4578433" placeholder="请输入评论uid"/>`
  394. html += ' </div>'
  395. html += ' <div class="javaex-unit-right mr-10">'
  396. html += ' <input type="button" id="getUpMsg" class="javaex-btn blue" value="查询"/>'
  397. html += ' </div>'
  398. html += ' </div>'
  399. html += ' <div class="javaex-unit clear tc" style="width: 500px;">'
  400. html += ' <table id="upMsgTable" class="javaex-table td-c-1">'
  401. html += ' <thead>'
  402. html += ' <tr><th>内容</th><th>详情</th></tr>'
  403. html += ' </thead>'
  404. html += ' <tbody id="upMsgTbody">'
  405.  
  406. html += ' </tbody>'
  407. html += '</table> '
  408. html += '</div>'
  409. html += '</form>';
  410. html += '<hr class="javaex-divider"></hr>';
  411. html += '</div>';
  412.  
  413.  
  414. javaex.panel(this, {
  415. position: "right",
  416. content: html
  417. });
  418.  
  419. javaex.table({
  420. id: "upMsgTable",
  421. isDragColWidth: true, // 是否允许拖动改变列宽
  422. mode: "overflow", // overflow表示允许使用父容器溢出来调整列的大小
  423. leftFixedColNum: 2, // 左侧固定列数
  424. rightFixedColNum: 1, // 右侧固定列数
  425. sort: {
  426. "1": "create_time", // 4表示第几列(从1开始计)。create_time表示排序字段,回调函数会返回该值
  427. "2": "update_time"
  428. },
  429. sortCallback: function (rtn) {
  430. //console.log(rtn.sortArr);
  431. }
  432. });
  433.  
  434. //
  435. $("#getUpMsg").click(async function () {
  436.  
  437. let temp = HNAPI.getUpCard(parseInt(javaex.getSelectVal("#up_uid")));
  438.  
  439.  
  440. await HNTOOL.Sleep(500);
  441.  
  442.  
  443. if (temp != false) {
  444. let data = BiliData.upCard.data;
  445.  
  446. let html = ``;
  447. html += `<tr><td>用户UID</td><td>${data.card.mid}</td></tr> `
  448. html += `<tr><td>用户等级</td><td>lv${data.card.level_info.current_level}</td></tr> `
  449. html += `<tr><td>用户昵称</td><td>${data.card.name}</td></tr> `
  450. html += `<tr><td>用户性别</td><td>${data.card.sex}</td></tr> `
  451. html += `<tr><td>用户头像</td><td><a href="javascript:;"><img src= ${data.card.face} width="50%"></a></td></tr> `
  452. html += `<tr><td>粉丝数</td><td>${data.follower}</td></tr> `
  453. html += `<tr><td>关注数</td><td>${data.card.friend}</td></tr> `
  454. html += `<tr><td>是否关注此用户</td><td>${data.following}</td></tr> `
  455. html += `<tr><td>用户稿件数</td><td>${data.archive_count}</td></tr> `
  456. html += `<tr><td>用户勋章</td><td>${data.card.nameplate.name}<a href="javascript:;"><img src= ${data.card.nameplate.image} width="50%"></a> </td></tr> `
  457. html += `<tr><td>用户勋章等级</td><td>${data.card.nameplate.level}</td></tr> `
  458. html += `<tr><td>认证信息</td><td>${data.card.Official.title}</td></tr> `
  459.  
  460.  
  461. $("#upMsgTbody").empty();
  462. $("#upMsgTbody").append(html);
  463. }
  464.  
  465.  
  466. });
  467. //点击放大
  468. /* $("img").click(function() {
  469. javaex.dialog({
  470. type : "image", // 弹出层类型
  471. url : $(this).attr("src") // 图片地址
  472. });
  473. });*/
  474.  
  475. });
  476.  
  477.  
  478. $("#addPlay").bind("click", async function () {
  479.  
  480.  
  481. let html = '';
  482.  
  483. html += '<div style="padding: 10px 10px 10px 0px;">'
  484. html += '<form id="getUpMassage_form">'
  485.  
  486. html += ' <div class="javaex-unit clear">'
  487. html += ' <div class="javaex-unit-left"><p class="subtitle required">UID</p></div>'
  488. html += ` <div class="javaex-unit-right" tooltip="请输入用户UID,默认自己" tooltip-pos="up"> `
  489. html += ' <input type="text" class="javaex-text" data-type="positive_int|required" error-msg="请正确输入uid"'
  490. html += ` id="addPlay_uid" value="${Live_info.uid}" placeholder="默认${Live_info.author_uid}"/>`
  491. html += ' </div>'
  492. html += ' </div>'
  493. html += ' <div class="javaex-unit clear">'
  494. html += ' <div class="javaex-unit-left"><p class="subtitle required">BV</p></div>'
  495. html += ' <div class="javaex-unit-right" tooltip="请输入视频BV号 例如BV14r4y1A7Q9 (0表示全部)" tooltip-pos="up">'
  496. html += ' <input type="text" class="javaex-text" data-type="required|english_number" error-msg=""'
  497. html += ` id="addPlay_bv" value="0" placeholder="请输入视频BV号 例如BV14r4y1A7Q9 (0表示全部)"/>`
  498. html += ' </div>'
  499. html += ' </div>'
  500. html += '</form>';
  501. html += ' <div class="javaex-unit clear tc">'
  502. html += ' <button id="addPlay_bgn" class="javaex-btn blue radius-3">开始</button> '
  503. html += ' </div>'
  504. html += '<hr class="javaex-divider"></hr>';
  505. html += '</div>';
  506.  
  507.  
  508. javaex.panel(this, {
  509. position: "right",
  510. content: html
  511. });
  512.  
  513. $("#addPlay_bgn").click(async function () {
  514.  
  515. let MID = javaex.getSelectVal("#addPlay_uid")
  516. let BV = javaex.getSelectVal("#addPlay_bv");
  517. let bvArr = [];
  518. let bvArr2 = [];
  519.  
  520. MID = javaex.ifnull(MID, Live_info.author_uid);
  521.  
  522.  
  523. if (BV == "0") {
  524.  
  525. //1.查询up所有视频BV号 2.发送心跳间隔2s
  526. HNAPI.getUpAllBV(Live_info.author_uid, 1, 2);
  527. await HNTOOL.Sleep(500);
  528. bvArr2 = BiliData.BVList;
  529.  
  530. for (let i = 1; i > 0; i++) {
  531.  
  532. HNAPI.getUpAllBV(MID, i);
  533.  
  534. await HNTOOL.Sleep(500);
  535.  
  536. if (BiliData.BVList.length == 0) {
  537. if (bvArr.length == 0) {
  538. javaex.tip({
  539. content: "该用户无投稿视频,请确认是否有误!",
  540. type: "success"
  541. });
  542. await HNTOOL.Sleep(2000);
  543. }
  544. //bvArr = bvArr.ifnull(bvArr2, bvArr.concat(bvArr2));
  545. bvArr = bvArr.concat(bvArr2);
  546. break;
  547. }
  548.  
  549. bvArr = bvArr.concat(BiliData.BVList);
  550. }
  551.  
  552.  
  553. if (bvArr.length != 0) {
  554.  
  555. for (const emt of bvArr) {
  556.  
  557. HNAPI.playOneVideo(emt.bvid,MID);
  558.  
  559. await HNTOOL.Sleep(2000);
  560.  
  561. }
  562.  
  563. alert("播放完成!!!");
  564.  
  565. }
  566.  
  567.  
  568. } else {
  569. //1.调用点击播放接口
  570. //2.发送心跳
  571.  
  572. await HNTOOL.Sleep(500);
  573.  
  574. HNAPI.playOneVideo(BV);
  575. }
  576.  
  577.  
  578. });
  579.  
  580.  
  581. });
  582.  
  583. }
  584.  
  585.  
  586. let showUnreadMsg = function () {
  587.  
  588. var html = '';
  589. html += '<div class="javaex-panel-box" style="width: 250px;">';
  590. html += ' <ul>';
  591. html += ` <p style="color: #FFF;">用户消息</p>`;
  592. html += ` <li><a href="https://message.bilibili.com/#/at">未读艾特数:${BiliData.Unread.at}</a> </li> `;
  593. html += ` <li><a href="https://message.bilibili.com/#/love">未读点赞数:${BiliData.Unread.like}</a> </li> `;
  594. html += ` <li><a href="https://message.bilibili.com/#/reply">未读回复数:${BiliData.Unread.reply}</a> </li> `;
  595. html += ` <li><a href="https://message.bilibili.com/#/system">未读系统通知数:${BiliData.Unread.sys_msg}</a> </li> `;
  596. html += ` <li><a href="">UP主助手信息数:${BiliData.Unread.up}</a> </li> `;
  597. html += ' <hr class="javaex-divider"></hr>';
  598. html += ' </ul>';
  599. html += '</div>';
  600.  
  601.  
  602. javaex.panel(document.getElementById("getUnread"), {
  603. position: "right",
  604. content: html
  605. });
  606.  
  607. javaex.tip({
  608. content: "查询用户通知成功!",
  609. type: "success"
  610. });
  611.  
  612. }
  613.  
  614. /**
  615. * 检查 艾特信息
  616. * @returns {Promise<void>}
  617. */
  618. let chackAtMsg = async function (items) {
  619.  
  620. await HNTOOL.Sleep(500);
  621.  
  622. if (items != false && typeof (items) != "undefined") {
  623.  
  624.  
  625. var html = '';
  626. html += '<div class="javaex-panel-box" style="width: auto;">';
  627. html += ' <ul>';
  628. html += ` <p style="color: #FFF;">@信息</p>`;
  629. items.forEach(function (item) {
  630.  
  631. var atTime = javaex.dateFormat(item.at_time, 'yyyy-MM-dd HH:mm:ss');
  632.  
  633. html += ` <li>${atTime} <a class="fontbold" href="https://space.bilibili.com/${item.user.mid}">:${item.user.nickname}</a>在动态中艾特了你!</li> `
  634. html += ` <li class="fontbold">内容:${item.item.source_content}</li> `;
  635. html += ` <li><a href="${item.item.uri}">---点击查看详情---</a> </li> `;
  636. html += ' <hr class="javaex-divider"></hr>';
  637. });
  638. html += ' </ul>';
  639. html += '</div>';
  640.  
  641. if (($("#chackList").attr("class")).indexOf("hover") > -1) {
  642. javaex.panel(document.getElementById("getAtMsg"), {
  643. position: "right",
  644. content: html
  645. });
  646. } else {
  647. javaex.panel(document.getElementById("chackList"), {
  648. position: "right",
  649. content: html
  650. });
  651. }
  652.  
  653.  
  654. }
  655.  
  656. }
  657.  
  658.  
  659. let addSetPage = async function () {
  660.  
  661. HNTOOL.Sleep(1000);
  662.  
  663. $('body').append('' +
  664. '<div id="left_navbar">' +
  665. '<div class="javaex-menu-container"> ' +
  666. ' <div id="menu" class="javaex-menu"> ' +
  667. ' <ul> ' +
  668. ' <li class="javaex-menu-item alone hover" > ' +
  669. ' <a href="javaScript:;" style="background: #fb7299;padding-left: 0px;text-align: center;color: #ffffff;font-weight: bold;border-bottom: 1px solid #eee;" ' +
  670. ` tooltip="我是来测试的" tooltip-pos="right">管理中心 v${GM_info.script.version}</a> ` +
  671. ' </li> ' +
  672. ' </ul> ' +
  673. ' <ul> ' +
  674. ' <li class="javaex-menu-item"> ' +
  675. ' <a href="javascript:;">个人中心<i class="icon-angle-down"></i></a> ' +
  676. ' <ul> ' +
  677. ' <li id="biliUserMsg" class="javaex-hover-pulse"><a href="javaScript:;">用户信息</a></li> ' +
  678. ' </ul> ' +
  679. ' </li> ' +
  680. ' <li id="chackList" class="javaex-menu-item"> ' +
  681. ' <a href="javaScript:;">查询<i class="icon-angle-down"></i></a> ' +
  682. ' <ul> ' +
  683. ' <li id="getUpMassage" ><a href="javaScript:;">查询用户详细信息</a></li> ' +
  684. ' <li><a href="javaScript:;">查询每日最热视频【禁用】</a></li> ' +
  685. ' <li id="getAtMsg"><a href="javaScript:;">查询动态艾特信息</a></li> ' +
  686. ' <li id="getCoinLog" class="javaex-hover-pulse"><a href="javaScript:;">查询硬币变化</a></li> ' +
  687. ' <li id="getUnread" class="javaex-hover-pulse"><a href="javaScript:;">查询消息</a></li> ' +
  688. ' </ul> ' +
  689. ' </li> ' +
  690. ' <li class="javaex-menu-item"> ' +
  691. ' <a href="javascript:;">工具<i class="icon-angle-down"></i></a> ' +
  692. ' <ul> ' +
  693. ' <li class="javaex-hover-pulse"><a href="javaScript:;" >移动粉丝勋章【禁用】</a></li> ' +
  694. ' <li id="addPlay" class="javaex-hover-pulse"><a href="javaScript:;" >一键批量播放视频</a></li> ' +
  695. ' <li id="disUser" class="javaex-hover-pulse"><a href="javaScript:;" >一键批量拉黑</a></li> ' +
  696. ' <li id="" class="javaex-hover-pulse" ><a href="javaScript:;">动态评论区点赞【禁用】</a></li> ' +//likeInDynamicComments
  697. ' <li id="HNSetup" class="javaex-hover-pulse" ><span class="icon-cogs" style="font-size:50px;color:#ff0000;"></span><a href="javaScript:;">设置【禁用】</a></li> ' +
  698. ' </ul> ' +
  699. ' </li> ' +
  700.  
  701.  
  702. ' </ul> ' +
  703. ' </div> ' +
  704. '</div>' +
  705. '</div>');
  706. //$("#left_navbar").before('<button hnBtn="btn_open" class="javaex-btn green" onclick="openBar()">点我关闭</button>')
  707.  
  708. javaex.menu({
  709. id: "menu",
  710. isShowAll: false
  711. });
  712.  
  713. }
  714.  
  715.  
  716. let addStyle = function () {
  717. const animate = GM_getResourceText('animate');
  718. const common = GM_getResourceText('common');
  719. const defaultCss = GM_getResourceText('defaultCss');
  720. //const icomoonex = GM_getResourceText('icomoonex');
  721. //const AllCss = animate + common + defaultCss + icomoonex;
  722. const AllCss = animate + common + defaultCss;
  723. const style = document.createElement('style');
  724. style.innerHTML = AllCss;
  725. return document.getElementsByTagName('head')[0].appendChild(style);
  726. }
  727.  
  728. /*-----------------------------------------------点击事件绑定--------------------------------------------------*/
  729.  
  730.  
  731. /*-----------------------------------------------常用API--------------------------------------------------*/
  732.  
  733. let HNAPI = {
  734.  
  735.  
  736. /**
  737. * //https://api.bilibili.com/x/relation/modify
  738. *
  739. * @param UID
  740. */
  741. disUserByUid:function (vmid) {
  742.  
  743. Ajax.post({
  744. url: BILIBLI_PATH.api + '/x/relation/modify',
  745. data: {
  746. fid: parseInt(vmid),
  747. re_src: 11,
  748. act: 5,
  749. jsonp: "jsonp",
  750. csrf: Live_info.csrf_token,
  751. },
  752. hasCookies: true,
  753. dataType: 'application/x-www-form-urlencoded; charset=UTF-8',
  754. success: responseText => {
  755.  
  756. var json = JSON.parse(responseText);
  757.  
  758. if (json.code != 0) {
  759.  
  760. console.log("拉黑用户失败uid:" + vmid + " 错误信息"+ json.message);
  761. javaex.tip({
  762. content: "拉黑用户失败uid:" + vmid + " 错误信息"+ json.message,
  763. type: "error"
  764. });
  765.  
  766. }else{
  767. console.log("拉黑用户成功 uid:" + vmid);
  768. javaex.tip({
  769. content: "拉黑用户成功 uid:" + vmid,
  770. type: "success"
  771. });
  772. }
  773. }
  774. });
  775.  
  776. },
  777. /**
  778. * http://api.bilibili.com/x/web-interface/view
  779. * @param BV
  780. * 心跳间隔15秒
  781. */
  782. playOneVideo: function (BV,MID) {
  783.  
  784. //1.调用点击播放接口 https://api.bilibili.com/x/click-interface/click/web/h5
  785. Ajax.post({
  786. url: BILIBLI_PATH.api + "/x/click-interface/click/web/h5",
  787. hasCookies: true,
  788. dataType: 'application/x-www-form-urlencoded; charset=UTF-8',
  789. data: {
  790.  
  791. "bvid": BV,
  792. "part": 1,
  793. "mid": Live_info.uid,
  794. "lv": 2,
  795. "jsonp": "jsonp",
  796. "type": 3,
  797. "sub_type": 0
  798. },
  799. success: responseText => {
  800.  
  801. let json = JSON.parse(responseText);
  802.  
  803. if (/^{"code":0/.test(responseText)) {
  804. //发送一次心跳
  805. HNAPI.sendHeartbeat(BV,MID);
  806.  
  807. } else {
  808. javaex.tip({
  809. content: "视频" + data.bvid + "播放失败!" + json.message,
  810. type: "error"
  811. });
  812. }
  813. }
  814. })
  815.  
  816.  
  817. },
  818.  
  819. //上报视频播放心跳(web端)
  820. /**
  821. * http://api.bilibili.com/x/click-interface/web/heartbeat
  822. * @param json
  823. */
  824. sendHeartbeat: function (bvid,MID) {
  825.  
  826. Ajax.post({
  827. url: BILIBLI_PATH.api + "/x/click-interface/web/heartbeat",
  828. hasCookies: true,
  829. dataType: 'application/x-www-form-urlencoded; charset=UTF-8',
  830. //aid=756988764&bvid=BV1wr4y1P782&cid=304166326&page=1
  831. data: {
  832. "bvid": bvid,
  833. "type": 3,
  834. "dt": 2,
  835. "played_time": HNTOOL.random(12, 40),
  836. "realtime": HNTOOL.random(12, 40),
  837. "play_type": 0
  838. },
  839. success: responseText => {
  840.  
  841. if (/^{"code":0/.test(responseText) && MID != Live_info.author_uid) {
  842.  
  843. javaex.tip({
  844. content: "视频BV" + bvid + "播放一次!",
  845. type: "success"
  846. });
  847. }
  848. }
  849. })
  850.  
  851. },
  852.  
  853. //获取up所有投稿视频
  854. /**
  855. * https://api.bilibili.com/x/space/arc/search?mid=99439379&ps=30&tid=0&pn=1&keyword=&order=pubdate&jsonp=jsonp
  856. * @param mid
  857. */
  858. getUpAllBV: function (mid, pn, ps) {
  859. ps = (ps === undefined ? 30 : ps); // a默认值为1
  860. Ajax.get({
  861. url: BILIBLI_PATH.api + '/x/space/arc/search',
  862. queryStringsObj: {
  863. mid: mid,
  864. tid: 0,
  865. order: 'pubdate',
  866. jsonp: 'jsonp',
  867. pn: pn,
  868. ps: ps
  869. },
  870. hasCookies: true,
  871. success: responseText => {
  872.  
  873. var json = JSON.parse(responseText);
  874.  
  875. if (json.code != 0) {
  876.  
  877. javaex.tip({
  878. content: "获取up所有投稿视频失败!" + json.message,
  879. type: "success"
  880. });
  881.  
  882. } else {
  883. BiliData.BVList = json.data.list.vlist;
  884.  
  885. }
  886. }
  887. });
  888.  
  889. },
  890.  
  891.  
  892. /**
  893. *
  894. * @param path
  895. * @param data
  896. * @param saveObj
  897. * @param Func
  898. */
  899. publicGet: function (path, queryStringsObj) {
  900.  
  901. if (typeof (queryStringsObj) != "undefined") {
  902. queryStringsObj = {};
  903. }
  904. Ajax.get({
  905. url: BILIBLI_PATH.api + path,
  906. queryStringsObj: queryStringsObj,
  907. hasCookies: true,
  908. success: responseText => {
  909.  
  910. let json = JSON.parse(responseText);
  911. if (chackCode(json.code) && json.code == 0) {
  912.  
  913. return json.data;
  914. }
  915.  
  916. return false;
  917.  
  918. }
  919. })
  920.  
  921. },
  922.  
  923. /**
  924. * 导航栏用户信息
  925. */
  926. getUserNav: async function () {
  927.  
  928. GM_xmlhttpRequest({
  929. method: "GET",
  930. url: BILIBLI_PATH.api + "/x/web-interface/nav",
  931. //timeout:3000,
  932. onload: function (response) {
  933.  
  934. let json = JSON.parse(response.response);
  935. console.log(json);
  936. BiliData.login_code = json.code;
  937. BiliData.login_message = json.message;
  938. BiliData.LoginData = json.data;
  939.  
  940. }
  941. });
  942.  
  943. },
  944.  
  945. /**
  946. * 获取某up详细信息
  947. * http://api.bilibili.com/x/web-interface/card
  948. */
  949. getUpCard: function (mid) {
  950.  
  951. Ajax.get({
  952. url: BILIBLI_PATH.api + '/x/web-interface/card',
  953. queryStringsObj: {
  954. mid: mid,
  955. photo: false
  956. },
  957. hasCookies: true,
  958. success: responseText => {
  959.  
  960. var json = JSON.parse(responseText);
  961.  
  962. if (json.code != 0) {
  963.  
  964. javaex.tip({
  965. content: "查询失败!" + json.message,
  966. type: "success"
  967. });
  968. return false;
  969. } else {
  970. BiliData.upCard = json;
  971.  
  972. }
  973.  
  974.  
  975. }
  976. })
  977.  
  978. },
  979.  
  980. /**
  981. *
  982. * @param uid 用户uid
  983. * @param ps 每页视频个数 默认30个
  984. * @param pn 第几页
  985. */
  986. getUpAllVideo: function (uid, ps, pn) {
  987.  
  988. },
  989. getChallenge: async function () {
  990.  
  991.  
  992. },
  993. /**
  994. * 硬币记录
  995. * @returns {Promise<void>}
  996. */
  997. getCoinLog: async function () {
  998.  
  999. GM_xmlhttpRequest({
  1000. method: "GET",
  1001. url: BILIBLI_PATH.api + "/x/member/web/coin/log",
  1002. //url: "http://api.bilibili.com/x/member/web/coin/log",
  1003. onload: function (response) {
  1004.  
  1005. let json = JSON.parse(response.response);
  1006. if (json.code == 0) {
  1007.  
  1008. console.log("硬币记录" + json);
  1009. BiliData.CoinLog = json.data;
  1010.  
  1011. return true;
  1012. }
  1013.  
  1014. }
  1015. });
  1016. },
  1017. /**
  1018. * 未读消息数 http://api.bilibili.com/x/msgfeed/unread
  1019. * @returns {Promise<void>}
  1020. */
  1021. getUnread: async function () {
  1022.  
  1023. Ajax.get({
  1024. url: BILIBLI_PATH.api + "/x/msgfeed/unread",
  1025. hasCookies: true,
  1026. success: responseText => {
  1027.  
  1028. let json = JSON.parse(responseText);
  1029. if (chackCode(json.code) && json.code == 0) {
  1030.  
  1031. BiliData.Unread = json.data;
  1032. showUnreadMsg();
  1033. }
  1034.  
  1035. return false;
  1036.  
  1037. }
  1038. })
  1039.  
  1040. /* GM_xmlhttpRequest({
  1041. method: "GET",
  1042. url: BILIBLI_PATH.api + "/x/msgfeed/unread",
  1043. onload: function (response) {
  1044.  
  1045. let json = JSON.parse(response.response);
  1046.  
  1047. if (chackCode(json.code) && json.code == 0) {
  1048.  
  1049. BiliData.Unread = json.code;
  1050. showUnreadMsg();
  1051.  
  1052. }
  1053.  
  1054. }
  1055. });*/
  1056. },
  1057. /**
  1058. *
  1059. * @param type reply:回复我的 at @我的
  1060. */
  1061. getMsgfeed: function (type) {
  1062. Ajax.get({
  1063. url: BILIBLI_PATH.api + '/x/msgfeed/' + type,
  1064. queryStringsObj: {
  1065. build: 0,
  1066. mobi_app: 'web'
  1067. },
  1068. hasCookies: true,
  1069. success: responseText => {
  1070.  
  1071. var json = JSON.parse(responseText);
  1072.  
  1073. if (json.code != 0 || !json.data.cursor.is_end || json.data.items == null) {
  1074. return false;
  1075. } else {
  1076. chackAtMsg(json.data.items);
  1077.  
  1078. return true;
  1079. }
  1080.  
  1081.  
  1082. }
  1083. })
  1084.  
  1085. },
  1086.  
  1087. /** 未读消息数 http://api.bilibili.com/x/space/arc/search?mid=99439379&pn=1&ps=5
  1088. * @returns {Promise<void>}
  1089. */
  1090. getUnrewad: async function () {
  1091.  
  1092. GM_xmlhttpRequest({
  1093. method: "GET",
  1094. data: {
  1095. "mid": 99439379,
  1096. "pn": 1,
  1097. "ps": 5,
  1098. },
  1099. url: BILIBLI_PATH.api + "/x/space/arc/search",
  1100. onload: function (response) {
  1101.  
  1102. let json = JSON.parse(response.response);
  1103. if (json.code == 0) {
  1104.  
  1105. BiliData.Video = json.data;
  1106. console.log("未读消息数" + json);
  1107. }
  1108.  
  1109. }
  1110. });
  1111. },
  1112.  
  1113. /** 动态评论区点赞 https://api.bilibili.com/x/v2/reply/action
  1114. * @param {number} oid
  1115. * @param {nbumber} rpid
  1116. * @param {number} action
  1117. * @returns {Promise<void>}
  1118. * type: 11
  1119. * ordering: heat
  1120. * jsonp: jsonp
  1121. * csrf: 54a******* CSRF Token(位于cookie)
  1122. */
  1123.  
  1124. likeInDynamicComments: async function (oid, rpid, action) {
  1125.  
  1126.  
  1127. Ajax.post({
  1128. url: BILIBLI_PATH.api + "/x/v2/reply/action",
  1129. hasCookies: true,
  1130. dataType: 'application/x-www-form-urlencoded; charset=UTF-8',
  1131. data: {
  1132. "oid": oid,
  1133. "type": 11,
  1134. "rpid": rpid,
  1135. "action": action,
  1136. "ordering": "heat",
  1137. "jsonp": "jsonp",
  1138. "csrf": Live_info.csrf_token,
  1139. },
  1140. success: responseText => {
  1141.  
  1142. if (/^{"code":0/.test(responseText)) {
  1143.  
  1144. BiliData.replyAction = JSON.parse(responseText);
  1145. console.log("点赞成功!" + responseText);
  1146. }
  1147. }
  1148. })
  1149.  
  1150. },
  1151.  
  1152.  
  1153. }
  1154.  
  1155. /*-----------------------------------------------常用工具函数--------------------------------------------------*/
  1156.  
  1157.  
  1158. let HNTOOL = {
  1159.  
  1160. /**
  1161. * 获取cookie 中某个键对应的值
  1162. * @param name
  1163. */
  1164.  
  1165. getCookie: function (name) {
  1166. let arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
  1167. if (arr != null) return unescape(arr[2]);
  1168. return false;
  1169. },
  1170. /**
  1171. * 得到一个字符串数组的中随机一个
  1172. * @param {List} list
  1173. */
  1174. getRandomWordOfList: function (list) {
  1175. var L = list.length;
  1176. var i = Math.ceil(Math.random() * L);
  1177.  
  1178. return list[i];
  1179. },
  1180. random: function (min, max) {
  1181.  
  1182. return Math.floor(Math.random() * (max - min)) + min;
  1183. },
  1184.  
  1185. Sleep: function (ms) {
  1186. return new Promise(resolve => setTimeout(() => resolve('sleep'), ms));
  1187. }
  1188.  
  1189. }
  1190.  
  1191. let errorMsg = {
  1192. "-1": "应用程序不存在或已被封禁!",
  1193. "-2": "Access Key错误!",
  1194. "-3": "API校验密匙错误!",
  1195. "-4": "调用方对该Method没有权限!",
  1196. "-101": "账号未登录!",
  1197. "-102": "账号被封停!",
  1198. "-103": "积分不足!",
  1199. "-104": "硬币不足!",
  1200. "-105": "验证码错误!",
  1201. "-106": "账号非正式会员或在适应期!",
  1202. "-107": "应用不存在或者被封禁!",
  1203. "-108": "未绑定手机!",
  1204. "-109": "未知!",
  1205. "-110": "未绑定手机!",
  1206. "-111": "csrf 校验失败!",
  1207. "-112": "系统升级中!",
  1208. "-113": "账号尚未实名认证!",
  1209. "-114": "请先绑定手机!",
  1210. "-115": "请先完成实名认证!",
  1211. "-304": "木有改动!",
  1212. "-307": "撞车跳转!",
  1213. "-400": "请求错误!",
  1214. "-401": "未认证!",
  1215. "-403": "访问权限不足!",
  1216. "-404": "啥都木有!",
  1217. }
  1218.  
  1219. /*-----------------------------------------------CODE 统一检查--------------------------------------------------*/
  1220. /**
  1221. *
  1222. * @param code
  1223. * @constructor
  1224. */
  1225. let chackCode = function (code) {
  1226.  
  1227. let emsg = errorMsg[code + ""];
  1228. if (emsg != null) {
  1229. javaex.tip({content: emsg, type: "error"});
  1230.  
  1231. return false;
  1232. }
  1233.  
  1234. return true;
  1235. }
  1236.  
  1237.  
  1238. /*-----------------------------------------------localStorage封装 (本地存储信息)--------------------------------------------------*/
  1239. //javaex.setLocalStorage(key, value); var str = javaex.getLocalStorage(key); javaex.deleteLocalStorage(key);
  1240.  
  1241. /*window.onbeforeunload = function() {
  1242. if (!canLeavePage()) {
  1243. return ('确认离开当前页面吗?未保存的数据将会丢失!');
  1244. }
  1245. };*/
  1246.  
  1247.  
  1248. /**
  1249. * Ajax请求对象
  1250. */
  1251. const Ajax = (() => {
  1252. /**
  1253. * 检查options是否符合要求
  1254. * @param {object} options
  1255. * @returns {boolean}
  1256. */
  1257. function checkOptions(options) {
  1258. let result = false;
  1259. if (typeof options !== 'object') {
  1260. console.warn('类型错误: typeof Options !== Object');
  1261. return result;
  1262. } else {
  1263. if (typeof options.url !== 'string') {
  1264. console.warn('类型错误: typeof Link !== Strings');
  1265. return result;
  1266. } else {
  1267. const reg = /^https?:\/\/(?:\w+\.?)+(?:\/.*)*\/?$/i;
  1268. if (!reg.test(options.url)) {
  1269. console.warn('url字符串须为完整http链接');
  1270. return result;
  1271. }
  1272. result = true;
  1273. }
  1274. }
  1275. return result;
  1276. }
  1277.  
  1278. /**
  1279. * 对象转URL编码
  1280. * @param {object} data
  1281. */
  1282. function objToURLCode(data) {
  1283. var _result = [];
  1284. for (var key in data) {
  1285. var value = data[key];
  1286. if (value instanceof Array) {
  1287. value.forEach(function (_value) {
  1288. _result.push(key + "=" + _value);
  1289. });
  1290. } else {
  1291. _result.push(key + '=' + value);
  1292. }
  1293. }
  1294. return _result.join('&');
  1295. }
  1296.  
  1297. /**
  1298. * 请求
  1299. * @param {string} method
  1300. * @param {object} options
  1301. */
  1302. function request(method, options) {
  1303. if (checkOptions(options)) {
  1304. let xhr = new XMLHttpRequest();
  1305. const {url: _url, queryStringsObj, data, dataType, hasCookies} = options
  1306. , url = typeof queryStringsObj === 'object' ?
  1307. _url + '?' + objToURLCode(queryStringsObj) : _url;
  1308. switch (method) {
  1309. case 'GET':
  1310. xhr.open("GET", url);
  1311. break;
  1312. case 'POST':
  1313. xhr.open("POST", url);
  1314. xhr.setRequestHeader('Content-Type', dataType);
  1315. break;
  1316. default:
  1317. break;
  1318. }
  1319. if (hasCookies) xhr.withCredentials = true;
  1320. xhr.timeout = 3000;
  1321. xhr.addEventListener('load', () => {
  1322. if (xhr.status === 200) {
  1323. options.success(xhr.responseText)
  1324. } else {
  1325. console.error(`status:${xhr.status}`);
  1326. options.success(`{"code":${xhr.status},"msg":"频繁访问"}`);
  1327. }
  1328. })
  1329. xhr.addEventListener('error', () => {
  1330. console.error('ajax请求出错')
  1331. options.success('{"code":-1,"msg":"ajax请求出错"}');
  1332. })
  1333. xhr.addEventListener('timeout', () => {
  1334. console.error('请求超时')
  1335. options.success('{"code":-1,"msg":"请求超时"}');
  1336. })
  1337. switch (method) {
  1338. case 'GET':
  1339. xhr.send()
  1340. break;
  1341. case 'POST':
  1342. xhr.send((/urlencoded/.test(dataType)) ? objToURLCode(data) : data)
  1343. break;
  1344. default:
  1345. break;
  1346. }
  1347. }
  1348. }
  1349.  
  1350. return {
  1351. /**
  1352. * 发送Get请求
  1353. * @param {Object} options
  1354. */
  1355. get(options) {
  1356. request("GET", options);
  1357. },
  1358. /**
  1359. * 发送Post请求
  1360. * @param {object} options
  1361. */
  1362. post(options) {
  1363. request("POST", options);
  1364. }
  1365. }
  1366. })()