Biliplus Evolved

简单的B+增强脚本

当前为 2024-08-03 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Biliplus Evolved
  3. // @version 0.11.8
  4. // @description 简单的B+增强脚本
  5. // @author DeltaFlyer
  6. // @copyright 2023, DeltaFlyer(https://github.com/DeltaFlyerW)
  7. // @license MIT
  8. // @match https://*.biliplus.com/*
  9. // @run-at document-end
  10. // @grant unsafeWindow
  11. // @grant GM_xmlhttpRequest
  12. // @grant GM_setValue
  13. // @grant GM_getValue
  14. // @connect api.bilibili.com
  15. // @connect comment.bilibili.com
  16. // @connect bangumi.bilibili.com
  17. // @connect www.bilibili.com
  18. // @connect delflare505.win
  19. // @icon https://www.biliplus.com/favicon.ico
  20. // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.9.1/jszip.min.js
  21. // @namespace https://greasyfork.org/users/927887
  22. // ==/UserScript==
  23.  
  24.  
  25. 'use strict';
  26. let toastText = (function () {
  27. let html = `
  28. <style>
  29. .df-bubble-container {
  30. position: fixed;
  31. bottom: 20px;
  32. right: 20px;
  33. z-index: 1000;
  34. display: block !important;
  35. }
  36.  
  37. .df-bubble {
  38. background-color: #333;
  39. color: white;
  40. padding: 10px 20px;
  41. border-radius: 5px;
  42. margin-bottom: 10px;
  43. opacity: 0;
  44. transition: opacity 0.5s ease-in-out;
  45. max-width: 300px;
  46. box-shadow: 0px 3px 6px rgba(0, 0, 0, 0.2);
  47. display: block !important;
  48. }
  49.  
  50. .df-show-bubble {
  51. opacity: 1;
  52. }
  53. </style>
  54. <div class="df-bubble-container" id="bubbleContainer"></div>`
  55. document.body.insertAdjacentHTML("beforeend", html)
  56. let bubbleContainer = document.querySelector('.df-bubble-container')
  57.  
  58. function createToast(text) {
  59. console.log('toast', text)
  60. const bubble = document.createElement('div');
  61. bubble.classList.add('df-bubble');
  62. bubble.textContent = text;
  63.  
  64. bubbleContainer.appendChild(bubble);
  65. setTimeout(() => {
  66. bubble.classList.add('df-show-bubble');
  67. setTimeout(() => {
  68. bubble.classList.remove('df-show-bubble');
  69. setTimeout(() => {
  70. bubbleContainer.removeChild(bubble);
  71. }, 500); // Remove the bubble after fade out
  72. }, 3000); // Show bubble for 3 seconds
  73. }, 100); // Delay before showing the bubble
  74. }
  75.  
  76. return createToast
  77. })();
  78.  
  79. async function sleep(time) {
  80. await new Promise((resolve) => setTimeout(resolve, time));
  81. }
  82.  
  83.  
  84. async function xhrGet(url) {
  85. function isCors(url) {
  86. if (url[0] === '/') return false
  87. // Extract the domain from the URL
  88. const urlDomain = new URL(url).hostname;
  89.  
  90. // Extract the domain from the current page's URL
  91. const currentDomain = window.location.hostname;
  92.  
  93. // Check if the domains are different (CORS request)
  94. return urlDomain !== currentDomain;
  95. }
  96.  
  97. console.log('Get', url);
  98. if (isCors(url)) {
  99. // Use GM_xmlhttpRequest for cross-origin requests
  100. return new Promise((resolve) => {
  101. GM_xmlhttpRequest({
  102. method: 'GET', url: url, withCredentials: true, onload: (response) => {
  103. if (response.status === 200) {
  104. resolve(response.responseText);
  105. } else {
  106. resolve(null);
  107. }
  108. }, onerror: (error) => {
  109. console.error('GM_xmlhttpRequest error:', error);
  110. resolve(null);
  111. },
  112. });
  113. });
  114. } else {
  115. // Use XMLHttpRequest for same-origin requests
  116. return new Promise((resolve) => {
  117. const xhr = new XMLHttpRequest();
  118. xhr.open('GET', url, true);
  119. xhr.withCredentials = true;
  120.  
  121. xhr.send();
  122.  
  123. xhr.onreadystatechange = async () => {
  124. if (xhr.readyState === 4) {
  125. if (xhr.status === 200) {
  126. resolve(xhr.responseText);
  127. } else {
  128. resolve(null);
  129. }
  130. }
  131. };
  132. });
  133. }
  134. }
  135.  
  136. function downloadFile(fileName, content, type = 'text/plain;charset=utf-8') {
  137. let aLink = document.createElement('a');
  138. let blob = content
  139. if (typeof (content) == 'string') blob = new Blob([content], {'type': type})
  140. aLink.download = fileName;
  141. let url = URL.createObjectURL(blob)
  142. aLink.href = url
  143. aLink.click()
  144. URL.revokeObjectURL(url)
  145. }
  146.  
  147. let bv2av = (function bv2av() {
  148. //https://github.com/TGSAN/bv2av.js/tree/master
  149.  
  150. let s = (` const table = 'FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf';
  151. const max_avid = 1n << 51n;
  152. const base = 58n;
  153. const bvid_len = 12n;
  154. const xor = 23442827791579n;
  155. const mask = 2251799813685247n;
  156.  
  157. let tr = [];
  158. for (let i = 0; i < base; i++) {
  159. tr[table[i]] = i;
  160. }
  161.  
  162. /**
  163. * avid to bvid
  164. * @param {bigint} avid
  165. * @returns {string} bvid
  166. */
  167. function enc(avid) {
  168. let r = ['B', 'V'];
  169. let idx = bvid_len - 1n;
  170. let tmp = (max_avid | avid) ^ xor;
  171. while (tmp !== 0n) {
  172. r[idx] = table[tmp % base];
  173. tmp /= base;
  174. idx -= 1n;
  175. }
  176. [r[3], r[9]] = [r[9], r[3]];
  177. [r[4], r[7]] = [r[7], r[4]];
  178. return r.join('');
  179. }
  180.  
  181. /**
  182. * bvid to avid
  183. * @param {string} bvid
  184. * @returns {bigint} avid
  185. */
  186. function dec(bvid) {
  187. let r = bvid.split('');
  188. [r[3], r[9]] = [r[9], r[3]];
  189. [r[4], r[7]] = [r[7], r[4]];
  190. let tmp = 0n;
  191. for (let char of r.slice(3)) {
  192. console.log(char)
  193. let idx = BigInt(tr[char]);
  194. tmp = tmp * base + idx;
  195. }
  196. let avid = (tmp & mask) ^ xor;
  197. return avid;
  198. }`)
  199.  
  200. eval(s)
  201.  
  202. return dec
  203. })();
  204.  
  205. async function aidQuery(event, init) {
  206. function transform(src) {
  207. let dst = {}
  208. dst.id = src.id
  209. dst.ver = 1
  210. dst.aid = src.id
  211. dst.lastupdatets = Math.floor(new Date().getTime() / 1000)
  212. dst.lastupdate = new Date().toLocaleString();
  213. if (src.title === "已失效视频") {
  214. let pic = document.querySelector('.detail_cover')
  215. if (pic) {
  216. dst.title = document.title.slice(0, document.title.indexOf(" - "))
  217. dst.pic = pic.src
  218. }
  219. } else {
  220. dst.pic = src.cover
  221. dst.title = src.title
  222. }
  223. dst.description = src.intro
  224.  
  225. dst.tid = src.tid
  226. dst.typename = "tid_" + src.tid
  227. dst.created = src.pubtime
  228. dst.created_at = new Date(src.pubtime * 1000).toLocaleString()
  229. dst.author = src.upper.name
  230. dst.mid = src.upper.mid
  231. dst.play = src.cnt_info.play.toString()
  232. dst.coins = src.cnt_info.coin
  233. dst.review = src.cnt_info.reply
  234. dst.video_review = src.cnt_info.danmaku
  235. dst.favorites = src.cnt_info.collect
  236. dst.tag = "tag_undefined"
  237. let list = []
  238. for (let page of src.pages) {
  239. list.push({
  240. "page": page.page,
  241. "type": page.from,
  242. "cid": page.id,
  243. "vid": undefined,
  244. "part": page.title + "_时长" + page.duration + "秒",
  245. "duration": page.duration
  246. })
  247. }
  248. dst.list = list
  249. return dst
  250. }
  251.  
  252. let aid
  253. let href = new URL(window.location.href)
  254. if (href.searchParams.has("get_info") || init) {
  255. aid = unsafeWindow.av
  256. } else {
  257. aid = window.prompt("请输入要查询的aid或bvid", unsafeWindow.av)
  258. console.log('input', aid)
  259. if (!/^\d+$/.exec(aid)) {
  260. if (/^av\d+$/.exec(aid) || /^AV\d+$/.exec(aid)) {
  261. aid = aid.substring(2)
  262. } else if (/^BV/.exec(aid)) {
  263. aid = bv2av(aid)
  264. } else {
  265. alert("请输入正确的视频号,bv号请以BV开头")
  266. return
  267. }
  268. }
  269. if (href.toString().indexOf(`/all/video/av${aid}/`) === -1) {
  270. href = new URL(href.origin + `/all/video/av${aid}/`)
  271. }
  272. href.searchParams.set("get_info", '1')
  273. window.location.href = href.toString()
  274. }
  275. let url = `https://delflare505.win/getVideoInfo?aid=` + aid
  276.  
  277. let response = await xhrGet(url)
  278. let body = JSON.parse(await response)
  279. console.log(body)
  280. let videoInfo = transform(body.data)
  281. unsafeWindow.videoInfo = videoInfo
  282. if (unsafeWindow.cloudmoe) {
  283. let cacheInfo = JSON.parse(JSON.stringify(videoInfo))
  284. cacheInfo.isDetailed = true
  285. cacheInfo.keywords = ""
  286. cacheInfo = {
  287. code: 0, data: {
  288. id: cacheInfo.id, info: cacheInfo, parts: cacheInfo.list,
  289. },
  290. }
  291. unsafeWindow.cloudmoe(cacheInfo)
  292. } else {
  293. unsafeWindow.view(videoInfo)
  294. }
  295. }
  296.  
  297. sleep(200).then(() => {
  298. if (new URL(window.location.href).searchParams.has("get_info")) {
  299. aidQuery(undefined, true)
  300. }
  301. })
  302.  
  303.  
  304. class CustomEventEmitter {
  305. constructor() {
  306. this.eventListeners = {};
  307. }
  308.  
  309. addEventListener(event, callback) {
  310. if (!this.eventListeners[event]) {
  311. this.eventListeners[event] = [];
  312. }
  313. this.eventListeners[event].push(callback);
  314. }
  315.  
  316. removeEventListener(event, callback) {
  317. if (this.eventListeners[event]) {
  318. const index = this.eventListeners[event].indexOf(callback);
  319. if (index !== -1) {
  320. this.eventListeners[event].splice(index, 1);
  321. }
  322. }
  323. }
  324.  
  325. postMessage(data) {
  326. const event = 'message'
  327. console.log(data)
  328. if (this.eventListeners[event]) {
  329. this.eventListeners[event].forEach(callback => {
  330. callback({data: data});
  331. });
  332. }
  333. }
  334. }
  335.  
  336. class ObjectRegistry {
  337. constructor() {
  338. this.registeredObjects = new Set();
  339. }
  340.  
  341. register(obj) {
  342. if (this.registeredObjects.has(obj)) {
  343. throw new Error('Object is already registered.');
  344. }
  345. this.registeredObjects.add(obj);
  346. }
  347. }
  348.  
  349. const broadcastChannel = new CustomEventEmitter()
  350.  
  351. function validateTitle(title) {
  352. if (!title) return ''
  353. return title.replace(/[\/\\\:\*\?\"\<\>\|]/g, '_')
  354. }
  355.  
  356. function getPartTitle(partInfo) {
  357. let partTitle = /^\d+$/.test(partInfo.page) ? 'p' : ''
  358. partTitle += partInfo.page + ' ' + validateTitle(partInfo.part) + '_' + partInfo.cid
  359. return partTitle
  360. }
  361.  
  362. function panel() {
  363. function getLocalSetting(key) {
  364. let value = GM_getValue(key)
  365. console.log('get', key, value)
  366. if (value) {
  367.  
  368. return value
  369. } else {
  370. return {}
  371. }
  372. }
  373.  
  374. function setDefaultValue(currentSetting, settingPanelOptions) {
  375. for (let option of settingPanelOptions) {
  376. if (option.id) {
  377. if (!currentSetting[option.id]) {
  378. currentSetting[option.id] = option.default
  379. }
  380. } else if (option.children) {
  381. for (let child of option.children) {
  382. if (child.id) {
  383. if (!currentSetting[child.id]) {
  384. currentSetting[child.id] = child.default
  385. }
  386. }
  387. }
  388. }
  389. }
  390. }
  391.  
  392. function saveLocalSetting(key, value) {
  393. console.log('save', key, value)
  394. GM_setValue(key, value)
  395. }
  396.  
  397. let settingPanelOptions = [{type: 'section', 'label': '抓取时段:'}, {
  398. type: 'row', children: [{
  399. 'type': 'numberInput',
  400. 'id': 'capturePeriodStart',
  401. label: "从视频发布起第",
  402. default: 0,
  403. suffixLabel: '天开始, ',
  404. splitter: ' '
  405. }, {
  406. 'type': 'numberInput',
  407. 'id': 'capturePeriodEnd',
  408. label: "至第",
  409. default: -1,
  410. suffixLabel: '天结束',
  411. splitter: ' '
  412. },]
  413. }, {type: 'sectionEnd'}, {
  414. type: 'row', children: [{type: 'checkbox', id: 'splitFileByTime', label: '按时间段分割弹幕文件'}]
  415. },]
  416.  
  417. let currentSetting = getLocalSetting("danmakuSetting")
  418. setDefaultValue(currentSetting, settingPanelOptions)
  419. let showSettingPanel = (function (settingPanelOptions, changeHandle) {
  420. let panelStyles = `
  421. <style>
  422. .section {
  423. font-size: 16px;
  424. margin-bottom: 10px;
  425. }
  426. .sectionEnd {
  427. border-top: 1px solid #ccc;
  428. margin-top: 10px;
  429. }
  430.  
  431. #panel {
  432. position: fixed;
  433. top: 50%;
  434. left: 50%;
  435. transform: translate(-50%, -50%);
  436. background-color: #333;
  437. color: #fff;
  438. padding: 20px;
  439. border-radius: 5px;
  440. box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);
  441. z-index: 999999;
  442. }
  443. .slider-label{
  444. width: 12ch;
  445. }
  446.  
  447. .apply-button {
  448. display: flex;
  449. justify-content: center;
  450. align-items: center;
  451. background-color: #555;
  452. color: white;
  453. border: none;
  454. padding: 8px 12px;
  455. cursor: pointer;
  456. border-radius: 4px;
  457. text-decoration: none;
  458. margin-top: 10px;
  459. margin-left: auto;
  460. }
  461.  
  462. .row {
  463. display: flex;
  464. align-items: center;
  465. margin-bottom: 10px;
  466. }
  467.  
  468. .slider {
  469. flex: 1;
  470. }
  471.  
  472. .slider-value {
  473. margin-left: 10px;
  474. font-size: 14px;
  475. color: #bbb;
  476. width: 4ch;
  477. }
  478.  
  479. .selector {
  480. flex: 1;
  481. margin-right: 10px;
  482. padding: 5px;
  483. border: 1px solid #555;
  484. border-radius: 3px;
  485. background-color: #444;
  486. color: #fff;
  487. }
  488.  
  489. .number-input {
  490. width: 6ch;
  491. padding: 5px;
  492. border: 1px solid #555;
  493. border-radius: 3px;
  494. background-color: #444;
  495. color: #fff;
  496. margin-right: 10px;
  497. margin-left: 5px;
  498. }
  499.  
  500. .text-selector {
  501. width: 10ch;
  502. padding: 5px;
  503. border: 1px solid #555;
  504. border-radius: 3px;
  505. background-color: #444;
  506. color: #fff;
  507. margin-left: 5px;
  508. }
  509.  
  510. .equal-row {
  511. display: flex;
  512. justify-content: space-between;
  513. align-items: center;
  514. }
  515.  
  516. .checkbox-group {
  517. flex: 1;
  518. display: flex;
  519. justify-content: center;
  520. }
  521. </style>
  522. `
  523.  
  524. // Create the setting panel HTML string based on the provided options
  525. function createPanelHTML(options) {
  526. let html = '<div id="panel" style="display: none;">'
  527. options.forEach(option => {
  528. if (option.type === 'section') {
  529. html += `<div class="section">${option.label}</div>`;
  530. } else if (option.type === 'sectionEnd') {
  531. html += `<div class="sectionEnd"></div>`;
  532. } else if (option.type === 'slider') {
  533. html += `<div class="row">
  534. <label class="slider-label" for="${option.id}">${option.label}:</label>
  535. <input type="range" class="slider" id="${option.id}" min="${option.range[0]}" max="${option.range[1]}" step="0.01" value="${currentSetting[option.id] || option.default}">
  536. <span class="slider-value" id="${option.id}Value">${currentSetting[option.id] || option.default}</span>
  537. </div>`;
  538. } else if (option.type === 'equal-row' || option.type === 'row') {
  539. html += `<div class="${option.type}">`;
  540. option.children.forEach(child => {
  541. // Handle checkboxes
  542. if (child.type === 'checkbox') {
  543. const checked = currentSetting[child.id] !== undefined ? currentSetting[child.id] : child.default;
  544. html += `<div class="checkbox-group">
  545. <label for="${child.id}">${child.label}:</label>
  546. <input type="checkbox" id="${child.id}" ${checked ? 'checked' : ''}>
  547. </div>`;
  548. }
  549. // Handle number input
  550. else if (child.type === 'numberInput') {
  551. html += `<label for="${child.id}">${child.label}${child.splitter || ':'}</label>
  552. <input type="number" class="number-input" id="${child.id}" value="${currentSetting[child.id] || child.default}">
  553. `;
  554. if (child.suffixLabel) {
  555. html += `<span>${child.suffixLabel}</span>`
  556. }
  557. }
  558. // Handle text selector
  559. else if (child.type === 'textSelector') {
  560. let currentValue = currentSetting[child.id] || child.default
  561. html += `<label for="${child.id}">${child.label}:</label>
  562. <select class="selector text-selector" id="${child.id}">`;
  563. child.optionText.forEach((text, index) => {
  564. const value = child.optionValue[index];
  565. const selected = currentValue === value ? 'selected' : '';
  566. html += `<option value="${value}" ${selected}>${text}</option>`;
  567. });
  568. html += `</select>`;
  569. }
  570. });
  571. html += `</div>`;
  572. }
  573. });
  574. html += '<button class="apply-button" id="applyButton">应用</button></div>';
  575. return html;
  576. }
  577.  
  578. function createSettingPanel(settingPanelOptions, changeHandle) {
  579.  
  580. document.body.insertAdjacentHTML('beforeend', panelStyles);
  581. const panelHTML = createPanelHTML(settingPanelOptions);
  582. document.body.insertAdjacentHTML('beforeend', panelHTML);
  583.  
  584. const panel = document.getElementById('panel');
  585.  
  586. panel.querySelector('#applyButton').addEventListener('click', () => {
  587. panel.style.display = 'none';
  588. saveLocalSetting('danmakuSetting', currentSetting)
  589. });
  590.  
  591. const sliders = panel.querySelectorAll('.slider');
  592. const sliderValues = panel.querySelectorAll('.slider-value');
  593.  
  594. sliders.forEach((slider, index) => {
  595. slider.addEventListener('input', () => {
  596. sliderValues[index].textContent = slider.value;
  597. changeHandle[slider.id](parseFloat(slider.value), slider.id);
  598. });
  599. });
  600.  
  601. // Handle checkbox changes
  602. const checkboxes = panel.querySelectorAll('input[type="checkbox"]');
  603. checkboxes.forEach(checkbox => {
  604. checkbox.addEventListener('change', () => {
  605. changeHandle[checkbox.id](Number(checkbox.checked), checkbox.id);
  606. });
  607. });
  608.  
  609. // Handle number input changes
  610. const numberInputs = panel.querySelectorAll('.number-input');
  611. numberInputs.forEach(input => {
  612. input.addEventListener('input', () => {
  613. const value = parseFloat(input.value);
  614. if (!isNaN(value)) {
  615. changeHandle[input.id](value, input.id);
  616. }
  617. });
  618. });
  619.  
  620. // Handle text selector changes
  621. const textSelectors = panel.querySelectorAll('.text-selector');
  622. textSelectors.forEach(selector => {
  623. selector.addEventListener('change', () => {
  624. changeHandle[selector.id](selector.value, selector.id);
  625. });
  626. });
  627.  
  628. return panel
  629. }
  630.  
  631.  
  632. let panel = createSettingPanel(settingPanelOptions, changeHandle)
  633. panel.style.display = 'none'
  634. return function () {
  635. if (panel.style.display !== 'block') {
  636. panel.style.display = 'block'
  637. } else {
  638. panel.style.display = 'none'
  639. }
  640. }
  641. })(settingPanelOptions, {
  642. capturePeriodStart(value, id) {
  643. currentSetting[id] = value;
  644. }, capturePeriodEnd(value, id) {
  645. currentSetting[id] = value;
  646. }, splitFileByTime(value, id) {
  647. currentSetting[id] = value;
  648. },
  649. });
  650.  
  651. async function findCidInfo() {
  652. let cid = window.prompt("请输入要查询的cid")
  653. if (!/^\d+$/.exec(cid)) {
  654. alert("请输入一个数字")
  655. return
  656. }
  657. let response = await fetch(`/api/cidinfo?cid=${cid}`)
  658. let body = await response.json()
  659. window.alert((JSON.stringify(body.data)))
  660.  
  661. }
  662.  
  663.  
  664. (function createToolbar(config) {
  665. let html = `
  666. <style>
  667.  
  668. #triggerArea {
  669. position: fixed;
  670. top: 45%;
  671. left: 0;
  672. width: max(5%,50px);
  673. height: 30%;
  674. cursor: pointer;
  675. z-index: 999998;
  676. }
  677.  
  678. #toolbar {
  679. position: fixed;
  680. top: 50%;
  681. left: -250px;
  682. transform: translateY(-50%);
  683. background-color: #333;
  684. color: #fff;
  685. padding: 10px;
  686. border-top-right-radius: 5px;
  687. border-bottom-right-radius: 5px;
  688. cursor: grab;
  689. transition: left 0.3s;
  690. z-index: 999999;
  691. }
  692.  
  693. #toolbar:active {
  694. cursor: grabbing;
  695. }
  696.  
  697. #toolbar button {
  698. display: block;
  699. margin: 5px 0;
  700. padding: 8px;
  701. background-color: #555;
  702. border: none;
  703. color: #fff;
  704. cursor: pointer;
  705. border-radius: 3px;
  706. }
  707. </style>
  708. <div id="triggerArea"></div>
  709. <div id="toolbar"></div>
  710. `
  711. document.body.insertAdjacentHTML('beforeend', html)
  712. const triggerArea = document.getElementById('triggerArea');
  713. const toolbar = document.getElementById('toolbar');
  714. let isDragging = false;
  715. let isExpanded = false;
  716. let startY = 0;
  717. let initialTop = 0;
  718. let currentSetting = getLocalSetting('dfToolbar')
  719. if (currentSetting['offsetTopPercent']) {
  720. toolbar.setAttribute('offsetTop', currentSetting['offsetTopPercent'] * window.innerHeight)
  721. }
  722. console.log('createToolbar', config)
  723. for (let option of Object.keys(config.options)) {
  724. let button = document.createElement("button")
  725. button.innerText = option
  726. button.addEventListener('click', config.options[option])
  727. toolbar.appendChild(button)
  728. }
  729.  
  730.  
  731. function expandToolbar() {
  732. if (!isExpanded) {
  733. toolbar.style.left = '0';
  734. isExpanded = true;
  735. }
  736. }
  737.  
  738. function collapseToolbar() {
  739. if (isExpanded) {
  740. toolbar.style.left = '-250px';
  741. isExpanded = false;
  742. }
  743. }
  744.  
  745. triggerArea.addEventListener('mouseenter', () => {
  746. expandToolbar();
  747. });
  748.  
  749. triggerArea.addEventListener('mouseleave', () => {
  750. collapseToolbar();
  751. if (isDragging) {
  752. isDragging = false
  753. dragEndHandle()
  754. }
  755. });
  756.  
  757. toolbar.addEventListener('mouseenter', () => {
  758. expandToolbar();
  759. });
  760.  
  761. toolbar.addEventListener('mouseleave', () => {
  762. if (!isDragging) {
  763. collapseToolbar();
  764. }
  765. });
  766.  
  767. toolbar.addEventListener('mousedown', (e) => {
  768. if (e.target === toolbar) {
  769. console.log(e.type, e)
  770. isDragging = true;
  771. startY = e.clientY;
  772. initialTop = toolbar.offsetTop;
  773. }
  774. });
  775.  
  776.  
  777. let draggingHandle = (e) => {
  778. if (!isDragging) return;
  779. const deltaY = e.clientY - startY;
  780. toolbar.style.top = `${initialTop + deltaY}px`;
  781. }
  782.  
  783. let dragEndHandle = (e) => {
  784. if (isDragging) {
  785. isDragging = false;
  786. currentSetting.offsetTopPercent = toolbar.offsetTop / window.innerHeight
  787. saveLocalSetting('dfToolbar', currentSetting)
  788. }
  789. }
  790.  
  791. window.addEventListener('mousemove', draggingHandle);
  792. window.addEventListener('mouseup', dragEndHandle);
  793.  
  794. expandToolbar()
  795. setTimeout(collapseToolbar, 3000)
  796. })({
  797. options: {
  798. "下载选项": showSettingPanel, "CID 反查": findCidInfo, "AID 查询": aidQuery
  799. }
  800. });
  801. return currentSetting
  802. }
  803.  
  804. function client() {
  805. let registeredTimestamp = new Date().getTime()
  806.  
  807.  
  808. console.log('biliplus script running')
  809.  
  810. function getPageAid() {
  811. let aid
  812. if (/\/BV/.exec(window.location.href)) {
  813. aid = bv2av(/BV[a-zA-Z0-9]+/.exec(window.location.href)[0])
  814. } else {
  815. aid = /av(\d+)/.exec(window.location.href)[1]
  816. }
  817. return Number(aid)
  818. }
  819.  
  820. function xmlunEscape(content) {
  821. return content.replace(/, /g, ';')
  822. .replace(/&amp;/g, '&')
  823. .replace(/&lt;/g, '<')
  824. .replace(/&gt;/g, '>')
  825. .replace(/&apos;/g, "'")
  826. .replace(/&quot;/g, '"')
  827. }
  828.  
  829. let createElement = function (sHtml) {
  830. // 创建一个可复用的包装元素
  831. let recycled = document.createElement('div'), // 创建标签简易匹配
  832. reg = /^<([a-zA-Z]+)(?=\s|\/>|>)[\s\S]*>$/, // 某些元素HTML标签必须插入特定的父标签内,才能产生合法元素
  833. // 另规避:ie7-某些元素innerHTML只读
  834. // 创建这些需要包装的父标签hash
  835. hash = {
  836. 'colgroup': 'table',
  837. 'col': 'colgroup',
  838. 'thead': 'table',
  839. 'tfoot': 'table',
  840. 'tbody': 'table',
  841. 'tr': 'tbody',
  842. 'th': 'tr',
  843. 'td': 'tr',
  844. 'optgroup': 'select',
  845. 'option': 'optgroup',
  846. 'legend': 'fieldset'
  847. };
  848. // 闭包重载方法(预定义变量避免重复创建,调用执行更快,成员私有化)
  849. createElement = function (sHtml) {
  850. // 若不包含标签,调用内置方法创建并返回元素
  851. if (!reg.test(sHtml)) {
  852. return document.createElement(sHtml);
  853. }
  854. // hash中是否包含匹配的标签名
  855. let tagName = hash[RegExp.$1.toLowerCase()];
  856. // 若无,向包装元素innerHTML,创建/截取并返回元素
  857. if (!tagName) {
  858. recycled.innerHTML = sHtml;
  859. return recycled.removeChild(recycled.firstChild);
  860. }
  861. // 若匹配hash标签,迭代包装父标签,并保存迭代层次
  862. let deep = 0, element = recycled;
  863. do {
  864. sHtml = '<' + tagName + '>' + sHtml + '</' + tagName + '>';
  865. deep++;
  866. } while (tagName = hash[tagName]);
  867. element.innerHTML = sHtml;
  868. // 根据迭代层次截取被包装的子元素
  869. do {
  870. element = element.removeChild(element.firstChild);
  871. } while (--deep > -1);
  872. // 最终返回需要创建的元素
  873. return element;
  874. }
  875. // 执行方法并返回结果
  876. return createElement(sHtml);
  877. }
  878.  
  879. async function parseVideoInfo(aid) {
  880. let videoInfo
  881. if (unsafeWindow.videoInfo && window.location.href.includes('/video/')) {
  882. return unsafeWindow.videoInfo
  883. }
  884. if (aid === undefined) {
  885. aid = getPageAid()
  886. }
  887. try {
  888. let videoPage = await xhrGet('https://www.biliplus.com/video/av' + aid + '/')
  889. videoInfo = JSON.parse(xmlunEscape(/({"id":.*?})\);/.exec(videoPage)[1]))
  890. videoInfo['aid'] = videoInfo['id']
  891. if (!videoInfo.list || videoInfo.list.length === 0) {
  892. throw ["No part found in videoInfo Normal, try cidHistory",
  893. JSON.stringify(videoInfo, undefined, "\t")]
  894. }
  895. } catch (e) {
  896. console.log(e)
  897. let videoPage = await xhrGet('https://www.biliplus.com/all/video/av' + aid + '/')
  898. let url = /(\/api\/view_all\?.*?)'/.exec(videoPage)[1]
  899. url = 'https://www.biliplus.com' + url
  900. let data = JSON.parse(xmlunEscape(await xhrGet(url)))['data']
  901. videoInfo = data['info']
  902. videoInfo['list'] = data['parts']
  903. }
  904. if (videoInfo.created) {
  905. videoInfo.videoPublishDate = videoInfo.created
  906. }
  907. console.log(videoInfo)
  908. if (window.location.href.includes('/video/')) {
  909. unsafeWindow.videoInfo = videoInfo
  910. }
  911. return videoInfo
  912. }
  913.  
  914. (function searchFix() {
  915. if (window.location.href.indexOf('api/do.php') === -1) return
  916.  
  917. function searchOption() {
  918. let searchField = document.querySelector("#searchField > fieldset")
  919. let searchDiv = document.querySelector("#searchField > fieldset > div:nth-child(1)")
  920. searchDiv.insertAdjacentHTML('afterend', `
  921. <style>
  922. .dropdown {
  923. background-color: #f2f2f2;
  924. padding: 4px;
  925. border-radius: 2px;
  926. }
  927.  
  928. .dropdown option {
  929. padding: 10px;
  930. font-size: 14px;
  931. color: #333;
  932. }
  933.  
  934. .dropdown option:hover {
  935. background-color: #e5e5e5;
  936. }
  937. </style>
  938. <select id="alive-section" class="dropdown">
  939. <option value="连载动画">连载动画</option>
  940. <option value="完结动画">完结动画</option>
  941. <option value="国产动画">国产动画</option>
  942. <option value="欧美电影">欧美电影</option>
  943. <option value="日本电影">日本电影</option>
  944. <option value="国产电影">国产电影</option>
  945. <option value="布袋戏">布袋戏</option>
  946. <option value="国产剧">国产剧</option>
  947. <option value="海外剧">海外剧</option>
  948. <option value="" selected="">视频分区</option>
  949. </select>
  950. <select id="dead-section" class="dropdown">
  951. <option value="连载剧集">连载剧集</option>
  952. <option value="完结剧集">完结剧集</option>
  953. <option value="国产">国产</option>
  954. <option value="日剧">日剧</option>
  955. <option value="美剧">美剧</option>
  956. <option value="其他">其他</option>
  957. <option value="特摄">特摄</option>
  958. <option value="剧场版">剧场版</option>
  959. <option value="" selected="">下架分区</option>
  960. </select>
  961. <select id="poster" class="dropdown">
  962. <option value="928123">哔哩哔哩番剧</option>
  963. <option value="11783021">哔哩哔哩番剧出差</option>
  964. <option value="15773384">哔哩哔哩电影</option>
  965. <option value="4856007">迷影社</option>
  966. <option value="" selected="">UP主</option>
  967. </select>
  968. `)
  969. let aliveSection = searchField.querySelector("select[id='alive-section']")
  970. let deadSection = searchField.querySelector("select[id='dead-section']")
  971. let poster = searchField.querySelector("select[id='poster']")
  972. let searchInput = document.querySelector("#searchField > fieldset > div:nth-child(1) > input[type=search]")
  973.  
  974. function setSection(section) {
  975. let content = searchInput.value
  976. if (section !== "") {
  977. section = ' @' + section
  978. }
  979. if (/ @\S+/.exec(content)) {
  980. content = content.replace(/ @\S+/, section)
  981. } else content += section
  982. searchInput.value = content
  983. }
  984.  
  985. function setPoster(uid) {
  986. if (uid !== "") {
  987. uid = ' @m=' + uid
  988. }
  989. let content = searchInput.value
  990. if (/ @m=\d+/.exec(content)) {
  991. content = content.replace(/ @m=\d+/, uid)
  992. } else content += uid
  993. searchInput.value = content
  994. }
  995.  
  996. aliveSection.addEventListener('change', (event) => {
  997. if (deadSection.value !== "") {
  998. deadSection.value = ""
  999. }
  1000. setSection(event.target.value)
  1001. })
  1002. deadSection.addEventListener('change', (event) => {
  1003. if (aliveSection.value !== "") {
  1004. aliveSection.value = ""
  1005. }
  1006. setSection(event.target.value)
  1007. })
  1008. poster.addEventListener('change', (event) => {
  1009. setPoster(event.target.value)
  1010. })
  1011. }
  1012.  
  1013. searchOption()
  1014. unsafeWindow.openOrigin = unsafeWindow.open
  1015. unsafeWindow.open = function (link) {
  1016. console.log('window.open', link)
  1017. if (link) {
  1018. unsafeWindow.openOrigin(link)
  1019. }
  1020. }
  1021. let getjson = unsafeWindow.parent.getjsonReal = unsafeWindow.parent.getjson
  1022. let aidList = []
  1023. let irrelevantArchive = []
  1024. let allArchive = []
  1025.  
  1026. async function joinCallback(url, callback, n) {
  1027. if (url[0] === '/') url = 'https:' + url
  1028. let word = /word=(.*?)(&|$)/.exec(url)[1]
  1029. let wordList = []
  1030. for (let keyword of decodeURIComponent(word).replace(/([^ ])@/, '$1 @').split(' ')) {
  1031. if (keyword[0] !== '@') {
  1032. wordList.push(keyword)
  1033. }
  1034. }
  1035. let pn = /p=(\d+)/.exec(url)
  1036. pn = pn ? pn[1] : '1'
  1037. if (pn === '1') {
  1038. aidList = []
  1039. irrelevantArchive = []
  1040. allArchive = []
  1041. }
  1042.  
  1043. let searchResult = JSON.parse(await xhrGet(url))
  1044. let archive = []
  1045. searchResult['data']['items']['archive'].forEach(function (item) {
  1046. if (item.goto === 'av') {
  1047. if (aidList.indexOf(item.param) === -1) {
  1048. aidList.push(item.param)
  1049. let isRelevant = false
  1050. for (let keyword of wordList) {
  1051. for (let key of ['title', 'desc']) {
  1052. if (item[key].indexOf(keyword) !== -1) {
  1053. isRelevant = true
  1054. }
  1055. }
  1056. }
  1057. if (isRelevant) {
  1058. archive.push(item)
  1059. } else {
  1060. irrelevantArchive.push(item)
  1061. }
  1062. allArchive.push(item)
  1063. }
  1064. } else {
  1065. archive.push(item)
  1066. }
  1067. })
  1068.  
  1069. try {
  1070. let aidSearchUrl = '/api/search?word=' + word + '&page=' + pn
  1071. let aidSearchResult = JSON.parse((await xhrGet(aidSearchUrl)))['result']
  1072. aidSearchResult.forEach(function (video) {
  1073. if (aidList.indexOf(video.aid) === -1) {
  1074. let item = {
  1075. author: video.author,
  1076. cover: video.pic,
  1077. created: new Date(video.created.replace(/-/g, '/')).getTime() / 1000,
  1078. review: video.review,
  1079. desc: video.description,
  1080. goto: "av",
  1081. param: video.aid,
  1082. play: video.play,
  1083. title: video.title,
  1084. }
  1085.  
  1086. let isRelevant = false
  1087. for (let keyword of wordList) {
  1088. for (let key of ['title', 'desc']) {
  1089. if (item[key].indexOf(keyword) !== -1) {
  1090. isRelevant = true
  1091. }
  1092. }
  1093. }
  1094. if (isRelevant) {
  1095. archive.push(item)
  1096. } else {
  1097. irrelevantArchive.push(item)
  1098. }
  1099. allArchive.push(item)
  1100. }
  1101. })
  1102. } catch (e) {
  1103. console.log(e)
  1104. }
  1105.  
  1106. if (archive.length === 0) {
  1107. archive = irrelevantArchive
  1108. irrelevantArchive = []
  1109. }
  1110. searchResult['data']['items']['archive'] = archive
  1111. callback(searchResult, n)
  1112. return
  1113. }
  1114.  
  1115.  
  1116. unsafeWindow.getjson = unsafeWindow.parent.getjson = function (url, callback, n) {
  1117. if (url.indexOf("search_api") !== -1 && url.indexOf("source=biliplus") !== -1) {
  1118. try {
  1119.  
  1120. return joinCallback(url, callback, n)
  1121. } catch (e) {
  1122. console.log(e)
  1123. return getjson(url, callback, n)
  1124. }
  1125. } else return getjson(url, callback, n)
  1126.  
  1127. };
  1128. unsafeWindow.doSearch()
  1129.  
  1130.  
  1131. broadcastChannel.addEventListener('message', function (event) {
  1132. console.log(event.data)
  1133. if (event.data.type === 'aidComplete') {
  1134. let elem = document.querySelector('[id="av' + event.data.aid + '"]')
  1135. if (elem) elem.textContent = '下载完成'
  1136. }
  1137. if (event.data.type === 'aidDownloaded') {
  1138. let elem = document.querySelector('[id="av' + event.data.aid + '"]')
  1139. if (elem) elem.textContent = '已下载'
  1140. }
  1141. if (event.data.type === 'aidStart') {
  1142. let elem = document.querySelector('[id="av' + event.data.aid + '"]')
  1143. if (elem) elem.textContent = '开始下载'
  1144. }
  1145. if (event.data.type === 'cidComplete') {
  1146. let elem = document.querySelector('[id="av' + event.data.aid + '"]')
  1147. if (elem) elem.textContent = event.data.progress + "%"
  1148. }
  1149. })
  1150.  
  1151. document.addEventListener("DOMNodeInserted", async (msg) => {
  1152. if (msg.target.nodeName === '#text') {
  1153. let aidElem = msg.target.parentElement.parentElement
  1154. .querySelector('div[class="video-card-desc"]')
  1155. if (!aidElem) {
  1156. return
  1157. }
  1158. console.log(aidElem)
  1159. let link = msg.target.parentElement.parentElement.parentElement.getAttribute("data-link")
  1160. if (link) {
  1161. console.log(link)
  1162. msg.target.parentElement.parentElement.parentElement.removeAttribute("data-link")
  1163. msg.target.parentElement.parentElement.parentElement.addEventListener('click', async function (event) {
  1164. console.log(event)
  1165. event.preventDefault()
  1166. if (event.target.className !== 'download') {
  1167. unsafeWindow.openOrigin(link)
  1168. }
  1169. })
  1170. }
  1171.  
  1172. let aid = parseInt(aidElem.textContent.slice(2))
  1173. if (!aidElem.querySelector('[class="download"]')) {
  1174. let downloadButton = createElement('<div class="download" style="display:inline-block;float:right;border-radius:5px;border:1px solid #AAA;' + 'background:#DDD;padding:8px 20px;cursor:pointer" id="av' + aid + '">下载弹幕</div>')
  1175. window.moved = true
  1176.  
  1177. downloadButton.addEventListener('click', async function (event) {
  1178. event.preventDefault()
  1179. console.log('download', aid)
  1180. if (downloadButton.textContent !== '下载弹幕') return
  1181. downloadButton.textContent = '等待下载'
  1182. let videoInfo = await parseVideoInfo(aid)
  1183. broadcastChannel.postMessage({
  1184. type: 'biliplusDownloadDanmakuVideo',
  1185. videoInfo: videoInfo,
  1186. timestamp: registeredTimestamp
  1187. })
  1188. })
  1189. aidElem.appendChild(downloadButton)
  1190. }
  1191. let timeago = msg.target.parentElement
  1192. for (let video of allArchive) {
  1193. if (video.param === aid && video.goto === 'av') {
  1194. let text = timeago.getAttribute('title') + ' 播放:' + video['play']
  1195. if (video['danmaku']) text += ' 弹幕:' + video['danmaku']
  1196. if (video['review']) text += ' 评论:' + video['review']
  1197. timeago.textContent = text
  1198. }
  1199. }
  1200. }
  1201. })
  1202.  
  1203. })();
  1204.  
  1205. (function historyFix() {
  1206.  
  1207. if (window.location.href.indexOf('/video/') === -1) return
  1208. const registry = new ObjectRegistry();
  1209. let aid = getPageAid()
  1210.  
  1211. unsafeWindow.downloadVideoDanmaku = async function (aid, videoInfo) {
  1212. registry.register('downloadVideoDanmaku')
  1213. if (!videoInfo) {
  1214. videoInfo = await parseVideoInfo(aid)
  1215. }
  1216. console.log('downloadVideoDanmaku', videoInfo)
  1217.  
  1218. broadcastChannel.postMessage({
  1219. type: 'biliplusDownloadDanmakuVideo', videoInfo: videoInfo, timestamp: registeredTimestamp
  1220. })
  1221. }
  1222.  
  1223. function getEpisodePublishDate(episode) {
  1224. let dateTimeString = episode.pub_real_time || episode.ctime
  1225. if (!dateTimeString) {
  1226. return null
  1227. }
  1228. const unixTimestamp = Date.parse(dateTimeString);
  1229. return Math.floor(unixTimestamp / 1000); // Convert milliseconds to seconds
  1230. }
  1231.  
  1232. async function popupPageSelector() {
  1233. async function builder(aid) {
  1234. if (!aid) {
  1235. aid = getPageAid()
  1236. }
  1237. let videoInfo = await parseVideoInfo(aid)
  1238. let partHtml = ''
  1239.  
  1240. for (let partInfo of videoInfo.list) {
  1241. let partTitle = getPartTitle(partInfo)
  1242. let idPrefix = `part_cid_${partInfo.cid}`
  1243. partHtml += `<tr draggable="true"><td>
  1244. <input type="checkbox" checked id="${idPrefix}"></td><td>${partTitle}</td>
  1245. <td><div class="front-black" style="display: none">
  1246. <label for="${idPrefix}_front">前黑</label>
  1247. <input type="number" class="p-number-input" name="${idPrefix}_front" id="${idPrefix}_front" />
  1248. </div>
  1249. <div class="back-black" style="display: none">
  1250. <label for="${idPrefix}_back">后黑</label>
  1251. <input type="number" class="p-number-input" name="${idPrefix}_back" id="${idPrefix}_back" />
  1252. </div>
  1253. </td>
  1254. </tr>`
  1255. }
  1256. let html = `
  1257. <style>
  1258. .popup {
  1259. position: fixed;
  1260. z-index: 1;
  1261. left: 0;
  1262. top: 0;
  1263. width: 100%;
  1264. height: 100%;
  1265. overflow: auto;
  1266. background-color: rgb(0,0,0);
  1267. background-color: rgba(0,0,0,0.4);
  1268. }
  1269.  
  1270. .front-black, .back-black{
  1271. display: flex;
  1272. flex-direction: row;
  1273. align-items: baseline;
  1274. font-size: 10px;
  1275. }
  1276.  
  1277. .p-number-input {
  1278. margin-left: 1px;
  1279. width: 25px;
  1280. border: 1px solid #aaa; /* Black solid border with 2px width */
  1281. border-radius: 4px; /* Optional: add rounded corners */
  1282. text-align: center; /* Center align the text */
  1283. }
  1284. .p-number-input::-webkit-outer-spin-button,
  1285. .p-number-input::-webkit-inner-spin-button {
  1286. -webkit-appearance: none;
  1287. margin: 0;
  1288. }
  1289.  
  1290.  
  1291.  
  1292.  
  1293.  
  1294. #draggableTable {
  1295. display: block;
  1296. max-height: 80vh;
  1297. overflow-y: auto;
  1298. border-collapse: collapse;
  1299. width: 100%;
  1300. }
  1301.  
  1302. .popup-content {
  1303. background-color: #fefefe;
  1304.  
  1305. display: block;
  1306. max-height: 90vh;
  1307. overflow-y: auto;
  1308. margin: 5vh auto;
  1309. padding: 20px;
  1310. border: 1px solid #888;
  1311. width: min(80%, 400px);
  1312. }
  1313.  
  1314.  
  1315. .close-btn {
  1316. color: #aaa;
  1317. float: right;
  1318. font-size: 28px;
  1319. font-weight: bold;
  1320. }
  1321.  
  1322. .close-btn:hover,
  1323. .close-btn:focus {
  1324. color: black;
  1325. text-decoration: none;
  1326. cursor: pointer;
  1327. }
  1328.  
  1329.  
  1330. input[type="checkbox"] {
  1331. transform: scale(1.5);
  1332. margin-right: 10px;
  1333. cursor: pointer;
  1334. }
  1335.  
  1336. #draggableTable td {
  1337. padding: 10px;
  1338. }
  1339.  
  1340. </style>
  1341. <body>
  1342. <div id="popup" class="popup" style="display: none">
  1343. <div class="popup-content">
  1344. <span class="close-btn">&times;</span>
  1345. <div class="button-row mb-3">
  1346. <button type="button" class="btn btn-primary" id="p-download">下载0项</button>
  1347. <button type="button" class="btn btn-primary" id="p-reverse">反选</button>
  1348. <button type="button" class="btn btn-primary" id="p-section" disabled>区间选择</button>
  1349. <button type="button" class="btn btn-primary" id="p-concat" disabled>拼接</button>
  1350. <button type="button" class="btn btn-primary" id="p-front-black" disabled title="无视视频前段的时长及弹幕">
  1351. 前黑
  1352. </button>
  1353. <button type="button" class="btn btn-primary" id="p-back-black" disabled "无视视频后段的时长及弹幕">
  1354. 后黑
  1355. </button>
  1356. </div>
  1357.  
  1358. <table id="draggableTable" class="table">
  1359. <tbody>
  1360. ${partHtml}
  1361. </tbody>
  1362. </table>
  1363. </div>
  1364. </div>
  1365. </body>
  1366. </html>
  1367.  
  1368.  
  1369. `
  1370.  
  1371. document.body.insertAdjacentHTML("beforeend", html)
  1372.  
  1373. for (let elemId of ['p-concat', "p-front-black", 'p-back-black']) {
  1374. if (videoInfo.list[0].duration) {
  1375. document.getElementById(elemId).removeAttribute("disabled")
  1376. } else {
  1377. document.getElementById(elemId).title = "仅限AID查询功能"
  1378. }
  1379. }
  1380.  
  1381.  
  1382. let popup = document.getElementById('popup')
  1383.  
  1384. function js() {
  1385. document.querySelector(".close-btn").onclick = function () {
  1386. document.getElementById("popup").style.display = "none";
  1387. }
  1388.  
  1389. let dragSrcEl = null;
  1390.  
  1391. function handleDragStart(e) {
  1392. dragSrcEl = this;
  1393. e.dataTransfer.effectAllowed = 'move';
  1394. e.dataTransfer.setData('text/html', this.innerHTML);
  1395. }
  1396.  
  1397. function handleDragOver(e) {
  1398. if (e.preventDefault) {
  1399. e.preventDefault(); // Necessary. Allows us to drop.
  1400. }
  1401. e.dataTransfer.dropEffect = 'move';
  1402. return false;
  1403. }
  1404.  
  1405. function handleDrop(e) {
  1406. if (e.stopPropagation) {
  1407. e.stopPropagation(); // stops the browser from redirecting.
  1408. }
  1409. if (dragSrcEl !== this) {
  1410. dragSrcEl.innerHTML = this.innerHTML;
  1411. registerItem(dragSrcEl)
  1412. this.innerHTML = e.dataTransfer.getData('text/html');
  1413. registerItem(this)
  1414. }
  1415. return false;
  1416. }
  1417.  
  1418. function handleDragEnd(e) {
  1419. this.style.opacity = '1';
  1420. }
  1421.  
  1422.  
  1423. function updateSelectedCount() {
  1424. const selectedCount =
  1425. document.querySelectorAll(
  1426. '#draggableTable input[type="checkbox"]:checked').length;
  1427. document.getElementById('p-download').innerText = `下载${selectedCount}项`
  1428. }
  1429.  
  1430. updateSelectedCount()
  1431.  
  1432. let lastClick = null
  1433. let currentClick = null
  1434.  
  1435.  
  1436. function registerItem(item) {
  1437. let checkbox = item.querySelector('input[type="checkbox"]');
  1438. item.addEventListener('dragstart', handleDragStart, false);
  1439. item.addEventListener('dragover', handleDragOver, false);
  1440. item.addEventListener('drop', handleDrop, false);
  1441. item.addEventListener('dragend', handleDragEnd, false);
  1442. item.addEventListener('click', function (e) {
  1443. if (e.target.type !== 'checkbox') {
  1444. checkbox.checked = !checkbox.checked
  1445. }
  1446. if (checkbox.checked) {
  1447. lastClick = currentClick
  1448. currentClick = item
  1449. if (lastClick !== null) {
  1450. document.getElementById('p-section').removeAttribute('disabled')
  1451. }
  1452. }
  1453.  
  1454. updateSelectedCount()
  1455. })
  1456. }
  1457.  
  1458. document.querySelectorAll('#draggableTable tr').forEach(registerItem)
  1459.  
  1460. document.getElementById('p-reverse').addEventListener('click', () => {
  1461. document.querySelectorAll('#draggableTable input[type="checkbox"]').forEach(checkbox => {
  1462. checkbox.checked = !checkbox.checked;
  1463. });
  1464. updateSelectedCount()
  1465. })
  1466. document.getElementById('p-section').addEventListener('click', () => {
  1467. let parent = lastClick.parentElement
  1468. let sectionStart = false
  1469. for (let child of parent.childNodes) {
  1470. if (child === lastClick || child === currentClick) {
  1471. if (!sectionStart) {
  1472. sectionStart = true
  1473. } else {
  1474. break
  1475. }
  1476. }
  1477. if (sectionStart) {
  1478. child.querySelector("input").checked = true
  1479. }
  1480. }
  1481. updateSelectedCount()
  1482. })
  1483. document.getElementById('p-reverse').addEventListener('click', () => {
  1484. })
  1485. document.getElementById('p-front-black').addEventListener('click', () => {
  1486. let time = Number(window.prompt("请输入前黑的秒数,拼接时将无视该时段的时长及弹幕"))
  1487. if (isNaN(time)) {
  1488. alert("请输入数字")
  1489. } else {
  1490. popup.querySelectorAll(".front-black").forEach(elem => {
  1491. elem.style.display = 'flex'
  1492. })
  1493. popup.querySelectorAll(`input[id$="_front"]`).forEach((elem) => {
  1494. elem.value = time
  1495. })
  1496. toastText(`应用前黑: ${time}秒`)
  1497. pageSetting.frontBlack = time
  1498. }
  1499. })
  1500. document.getElementById('p-back-black').addEventListener('click', () => {
  1501. let time = Number(window.prompt("请输入后黑的秒数,拼接时将无视该时段的时长及弹幕"))
  1502. if (isNaN(time)) {
  1503. alert("请输入数字")
  1504. } else {
  1505. popup.querySelectorAll(".back-black").forEach(elem => {
  1506. elem.style.display = 'flex'
  1507. })
  1508. popup.querySelectorAll(`input[id$="_back"]`).forEach((elem) => {
  1509. elem.value = time
  1510. })
  1511. toastText(`应用后黑: ${time}秒`)
  1512. pageSetting.backBlack = time
  1513. }
  1514. })
  1515. document.getElementById('popup').addEventListener('click', function (event) {
  1516. if (!event.target.closest('.popup-content')) {
  1517. document.getElementById('popup').style.display = 'none';
  1518. }
  1519. });
  1520. }
  1521.  
  1522. js()
  1523. return popup
  1524. }
  1525.  
  1526. let popup = document.getElementById('popup')
  1527. if (!popup) {
  1528. popup = await builder(aid)
  1529. }
  1530. if (popup.style.display === 'none') {
  1531. popup.style.display = 'block'
  1532. }
  1533. popup.querySelector('#p-download').addEventListener('click', async (e) => {
  1534. let videoInfo = await parseVideoInfo(aid)
  1535. videoInfo = JSON.parse(JSON.stringify(videoInfo))
  1536. let cidMap = {}
  1537. videoInfo.list.forEach((partInfo) => {
  1538. cidMap[partInfo.cid] = partInfo
  1539. })
  1540. videoInfo.list = []
  1541. for (let checkBox of document.querySelectorAll(
  1542. '#draggableTable input[type="checkbox"]:checked')) {
  1543. videoInfo.list.push(cidMap[Number(checkBox.id.substring(9))])
  1544. }
  1545. videoInfo.isCache = true
  1546. await unsafeWindow.downloadVideoDanmaku(aid, videoInfo)
  1547. })
  1548.  
  1549. popup.querySelector('#p-concat').addEventListener('click', async (e) => {
  1550. let videoInfo = await parseVideoInfo(aid)
  1551. videoInfo = JSON.parse(JSON.stringify(videoInfo))
  1552. let cidMap = {}
  1553. videoInfo.list.forEach((partInfo) => {
  1554. cidMap[partInfo.cid] = partInfo
  1555. })
  1556. videoInfo.list = []
  1557. for (let checkBox of document.querySelectorAll(
  1558. '#draggableTable input[type="checkbox"]:checked')) {
  1559. let partInfo = cidMap[Number(checkBox.id.substring(9))]
  1560. let tr = checkBox.parentNode.parentNode
  1561. let frontBlack = Number(tr.querySelector("input[id$='_front']").value)
  1562. let backBlack = Number(tr.querySelector("input[id$='_back']").value)
  1563. if (frontBlack) {
  1564. partInfo.frontBlack = frontBlack
  1565. }
  1566. if (backBlack) {
  1567. partInfo.backBlack = backBlack
  1568. }
  1569. videoInfo.list.push(partInfo)
  1570. }
  1571. console.log("concat", videoInfo)
  1572.  
  1573. if (pageSetting.frontBlack) {
  1574. toastText(`应用前黑: ${pageSetting.frontBlack}秒`)
  1575. }
  1576. if (pageSetting.backBlack) {
  1577. toastText(`应用后黑: ${pageSetting.backBlack}秒`)
  1578. }
  1579.  
  1580. broadcastChannel.postMessage({
  1581. type: 'concatDanmaku', videoInfo: videoInfo, timestamp: registeredTimestamp
  1582. })
  1583. })
  1584. }
  1585.  
  1586. unsafeWindow.popupPageSelector = popupPageSelector
  1587. document.addEventListener("DOMNodeInserted", async (msg) => {
  1588. if (msg.target.id) {
  1589. switch (msg.target.id) {
  1590. case 'danmaku_container': {
  1591. let historyButton = msg.target.querySelector('a[href^="/open/moepus.powered"]')
  1592. let cid = /#(\d+)/.exec(historyButton.getAttribute('href'))[1]
  1593. historyButton.onclick = async function () {
  1594.  
  1595. console.log('biliplusDownloadDanmaku', {
  1596. 'cid': cid,
  1597. 'title': document.querySelector('[class="videotitle"]').textContent + ' ' + document.querySelector('[id="cid_' + cid + '"]').innerText,
  1598. 'timestamp': registeredTimestamp
  1599. })
  1600. broadcastChannel.postMessage({
  1601. type: 'biliplusDownloadDanmaku',
  1602. cid: cid,
  1603. title: document.querySelector('[class="videotitle"]').textContent + ' ' + document.querySelector('[id="cid_' + cid + '"]').innerText,
  1604.  
  1605. timestamp: registeredTimestamp
  1606. })
  1607. }
  1608. historyButton.removeAttribute('href')
  1609.  
  1610. let commentButton = msg.target.querySelector('a[href^="https://comment.bilibili.com"]')
  1611. commentButton.removeAttribute('href')
  1612. commentButton.removeAttribute('onClick')
  1613. commentButton.addEventListener('click', async function () {
  1614. registry.register('commentButton' + cid)
  1615. let commentText = await xhrGet("/danmaku/" + cid + ".xml")
  1616. if (!commentText || commentText.indexOf("<state>2</state>") !== -1) {
  1617. broadcastChannel.postMessage({
  1618. type: 'biliplusDownloadDanmaku',
  1619. ndanmu: /<maxlimit>(\d+)<\/maxlimit>/.exec(commentText)?.[1],
  1620. cid: cid,
  1621. title: document.querySelector('[class="videotitle"]').textContent + ' ' + document.querySelector('[id="cid_' + cid + '"]').innerText,
  1622. history: false,
  1623. timestamp: registeredTimestamp
  1624. })
  1625. } else {
  1626. downloadFile(cid + '.xml', commentText)
  1627. }
  1628. })
  1629. break
  1630. }
  1631. case 'favorite': {
  1632. msg.target.parentElement.firstChild.insertBefore(
  1633. createElement('<span id="downloadDanmaku"><a href="javascript:" ' +
  1634. 'onclick="window.downloadVideoDanmaku()">' +
  1635. '<div class="solidbox pink" id="av' + getPageAid() + '">下载视频弹幕</div></a></span>'))
  1636. break
  1637. }
  1638. case 'part1': {
  1639. msg.target.insertAdjacentHTML(
  1640. 'beforebegin',
  1641. '<div class="solidbox pointer" onclick="window.downloadVideoDanmaku()">下载视频弹幕</div>' +
  1642. '<div class="solidbox pointer" onclick="window.popupPageSelector()">选择分P下载或拼接</div>')
  1643. break
  1644. }
  1645. case 'bgBlur': {
  1646. let bangumi = unsafeWindow.bangumi
  1647. if (!bangumi.isBangumi) break
  1648. let bangumiList = document.querySelector("#bangumi_list")
  1649. bangumiList.insertAdjacentHTML('beforeend', '' +
  1650. '<div class="solidbox pointer">下载剧集弹幕</div>')
  1651. bangumiList.lastChild.addEventListener('click', function (event) {
  1652. registry.register('downloadBangumiDanmaku')
  1653. console.log(event.target)
  1654. if (event.target.textContent !== '下载中') {
  1655. event.target.textContent = "下载中"
  1656. } else {
  1657. return
  1658. }
  1659. let apiCache = bangumi.apiCache
  1660. let response = apiCache[Object.keys(apiCache)[0]].result
  1661. let videoInfo = {
  1662. aid: 'ss' + response.season_id, title: response.title, list: [], detail: response,
  1663. }
  1664. for (let episode of response.episodes) {
  1665. if (episode.episode_type === -1 || episode.section_type === 1 || episode.section_type === 2) continue
  1666. let partInfo = {
  1667. page: episode.index ? episode.index : episode.title,
  1668. part: episode.index_title ? episode.index_title : episode.long_title,
  1669. cid: episode.cid,
  1670. duration: episode.duration,
  1671. videoPublishDate: getEpisodePublishDate(episode)
  1672. }
  1673. videoInfo.list.push(partInfo)
  1674. }
  1675. unsafeWindow.downloadVideoDanmaku(null, videoInfo)
  1676. })
  1677. }
  1678. }
  1679. }
  1680. })
  1681. if (unsafeWindow.cloudmoe) {
  1682. unsafeWindow._cloudmoe = unsafeWindow.cloudmoe
  1683. unsafeWindow.cloudmoe = function (json) {
  1684. if (json.code !== 0 || !json.data) {
  1685. toastText("使用AID查询信息")
  1686. return aidQuery(undefined, true)
  1687. } else {
  1688. return unsafeWindow._cloudmoe(json)
  1689. }
  1690. }
  1691. }
  1692. })();
  1693.  
  1694. (async function mediaLinkFix() {
  1695. function blockRefresh() {
  1696. // Select the meta refresh tag
  1697. let metaRefresh = document.querySelector('meta[http-equiv="refresh"]');
  1698.  
  1699. // If the meta tag exists, remove it
  1700. if (metaRefresh) {
  1701. metaRefresh.parentNode.removeChild(metaRefresh);
  1702. console.log('Auto-refresh blocked.');
  1703. }
  1704. }
  1705.  
  1706.  
  1707. let url = window.location.href
  1708. if (url.includes('media/md')) {
  1709. let html = await xhrGet(url.replace("biliplus", "bilibili"))
  1710. console.log(html)
  1711. let seasonId = /"season_id":(\d+)/.exec(html)
  1712. if (seasonId) {
  1713. window.location.href = 'https://www.biliplus.com/bangumi/play/ss' + seasonId[1]
  1714. }
  1715. } else if (url.includes('anime/v/')
  1716. && document.body.childNodes[0].textContent.includes('未能识别此地址')) {
  1717. document.addEventListener("DOMContentLoaded", blockRefresh);
  1718. blockRefresh()
  1719. let episodeId = /\/anime\/v\/(\d+)/.exec(url)[1]
  1720. let html = await xhrGet('https://www.bilibili.com/bangumi/play/ep' + episodeId)
  1721. console.log(html)
  1722. let seasonId = /"season_id":(\d+)/.exec(html)
  1723. console.log(seasonId)
  1724. if (seasonId) {
  1725. window.location.href = 'https://www.biliplus.com/bangumi/play/ss' + seasonId[1]
  1726. }
  1727. }
  1728.  
  1729. })();
  1730. }
  1731.  
  1732. function server() {
  1733.  
  1734. let videoPublishDate = null
  1735.  
  1736. let [downloadDanmaku, downloadDanmakuToZip, allProtobufDanmu, concatDanmaku] = (function () {
  1737. !function (z) {
  1738. var y = {
  1739. 1: [function (p, w) {
  1740. w.exports = function (h, m) {
  1741. for (var n = Array(arguments.length - 1), e = 0, d = 2, a = !0; d < arguments.length;) n[e++] = arguments[d++];
  1742. return new Promise(function (b, c) {
  1743. n[e] = function (k) {
  1744. if (a) if (a = !1, k) c(k); else {
  1745. for (var l = Array(arguments.length - 1), q = 0; q < l.length;) l[q++] = arguments[q];
  1746. b.apply(null, l)
  1747. }
  1748. };
  1749. try {
  1750. h.apply(m || null, n)
  1751. } catch (k) {
  1752. a && (a = !1, c(k))
  1753. }
  1754. })
  1755. }
  1756. }, {}], 2: [function (p, w, h) {
  1757. h.length = function (e) {
  1758. var d = e.length;
  1759. if (!d) return 0;
  1760. for (var a = 0; 1 < --d % 4 && "=" === e.charAt(d);) ++a;
  1761. return Math.ceil(3 * e.length) / 4 - a
  1762. };
  1763. var m = Array(64), n = Array(123);
  1764. for (p = 0; 64 > p;) n[m[p] = 26 > p ? p + 65 : 52 > p ? p + 71 : 62 > p ? p - 4 : p - 59 | 43] = p++;
  1765. h.encode = function (e, d, a) {
  1766. for (var b, c = null, k = [], l = 0, q = 0; d < a;) {
  1767. var f = e[d++];
  1768. switch (q) {
  1769. case 0:
  1770. k[l++] = m[f >> 2];
  1771. b = (3 & f) << 4;
  1772. q = 1;
  1773. break;
  1774. case 1:
  1775. k[l++] = m[b | f >> 4];
  1776. b = (15 & f) << 2;
  1777. q = 2;
  1778. break;
  1779. case 2:
  1780. k[l++] = m[b | f >> 6], k[l++] = m[63 & f], q = 0
  1781. }
  1782. 8191 < l && ((c || (c = [])).push(String.fromCharCode.apply(String, k)), l = 0)
  1783. }
  1784. return q && (k[l++] = m[b], k[l++] = 61, 1 === q && (k[l++] = 61)), c ? (l && c.push(String.fromCharCode.apply(String, k.slice(0, l))), c.join("")) : String.fromCharCode.apply(String, k.slice(0, l))
  1785. };
  1786. h.decode = function (e, d, a) {
  1787. for (var b, c = a, k = 0, l = 0; l < e.length;) {
  1788. var q = e.charCodeAt(l++);
  1789. if (61 === q && 1 < k) break;
  1790. if ((q = n[q]) === z) throw Error("invalid encoding");
  1791. switch (k) {
  1792. case 0:
  1793. b = q;
  1794. k = 1;
  1795. break;
  1796. case 1:
  1797. d[a++] = b << 2 | (48 & q) >> 4;
  1798. b = q;
  1799. k = 2;
  1800. break;
  1801. case 2:
  1802. d[a++] = (15 & b) << 4 | (60 & q) >> 2;
  1803. b = q;
  1804. k = 3;
  1805. break;
  1806. case 3:
  1807. d[a++] = (3 & b) << 6 | q, k = 0
  1808. }
  1809. }
  1810. if (1 === k) throw Error("invalid encoding");
  1811. return a - c
  1812. };
  1813. h.test = function (e) {
  1814. return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(e)
  1815. }
  1816. }, {}], 3: [function (p, w) {
  1817. function h() {
  1818. this.t = {}
  1819. }
  1820.  
  1821. (w.exports = h).prototype.on = function (m, n, e) {
  1822. return (this.t[m] || (this.t[m] = [])).push({fn: n, ctx: e || this}), this
  1823. };
  1824. h.prototype.off = function (m, n) {
  1825. if (m === z) this.t = {}; else if (n === z) this.t[m] = []; else for (var e = this.t[m], d = 0; d < e.length;) e[d].fn === n ? e.splice(d, 1) : ++d;
  1826. return this
  1827. };
  1828. h.prototype.emit = function (m) {
  1829. var n = this.t[m];
  1830. if (n) {
  1831. for (var e = [], d = 1; d < arguments.length;) e.push(arguments[d++]);
  1832. for (d = 0; d < n.length;) n[d].fn.apply(n[d++].ctx, e)
  1833. }
  1834. return this
  1835. }
  1836. }, {}], 4: [function (p, w) {
  1837. function h(a) {
  1838. return "undefined" != typeof Float32Array ? function () {
  1839. function b(v, g, t) {
  1840. q[0] = v;
  1841. g[t] = f[0];
  1842. g[t + 1] = f[1];
  1843. g[t + 2] = f[2];
  1844. g[t + 3] = f[3]
  1845. }
  1846.  
  1847. function c(v, g, t) {
  1848. q[0] = v;
  1849. g[t] = f[3];
  1850. g[t + 1] = f[2];
  1851. g[t + 2] = f[1];
  1852. g[t + 3] = f[0]
  1853. }
  1854.  
  1855. function k(v, g) {
  1856. return f[0] = v[g], f[1] = v[g + 1], f[2] = v[g + 2], f[3] = v[g + 3], q[0]
  1857. }
  1858.  
  1859. function l(v, g) {
  1860. return f[3] = v[g], f[2] = v[g + 1], f[1] = v[g + 2], f[0] = v[g + 3], q[0]
  1861. }
  1862.  
  1863. var q = new Float32Array([-0]), f = new Uint8Array(q.buffer), u = 128 === f[3];
  1864. a.writeFloatLE = u ? b : c;
  1865. a.writeFloatBE = u ? c : b;
  1866. a.readFloatLE = u ? k : l;
  1867. a.readFloatBE = u ? l : k
  1868. }() : function () {
  1869. function b(k, l, q, f) {
  1870. var u = 0 > l ? 1 : 0;
  1871. if (u && (l = -l), 0 === l) k(0 < 1 / l ? 0 : 2147483648, q, f); else if (isNaN(l)) k(2143289344, q, f); else if (3.4028234663852886E38 < l) k((u << 31 | 2139095040) >>> 0, q, f); else if (1.1754943508222875E-38 > l) k((u << 31 | Math.round(l / 1.401298464324817E-45)) >>> 0, q, f); else {
  1872. var v = Math.floor(Math.log(l) / Math.LN2);
  1873. k((u << 31 | v + 127 << 23 | 8388607 & Math.round(l * Math.pow(2, -v) * 8388608)) >>> 0, q, f)
  1874. }
  1875. }
  1876.  
  1877. function c(k, l, q) {
  1878. q = k(l, q);
  1879. k = 2 * (q >> 31) + 1;
  1880. l = q >>> 23 & 255;
  1881. q &= 8388607;
  1882. return 255 === l ? q ? NaN : 1 / 0 * k : 0 === l ? 1.401298464324817E-45 * k * q : k * Math.pow(2, l - 150) * (q + 8388608)
  1883. }
  1884.  
  1885. a.writeFloatLE = b.bind(null, m);
  1886. a.writeFloatBE = b.bind(null, n);
  1887. a.readFloatLE = c.bind(null, e);
  1888. a.readFloatBE = c.bind(null, d)
  1889. }(), "undefined" != typeof Float64Array ? function () {
  1890. function b(v, g, t) {
  1891. q[0] = v;
  1892. g[t] = f[0];
  1893. g[t + 1] = f[1];
  1894. g[t + 2] = f[2];
  1895. g[t + 3] = f[3];
  1896. g[t + 4] = f[4];
  1897. g[t + 5] = f[5];
  1898. g[t + 6] = f[6];
  1899. g[t + 7] = f[7]
  1900. }
  1901.  
  1902. function c(v, g, t) {
  1903. q[0] = v;
  1904. g[t] = f[7];
  1905. g[t + 1] = f[6];
  1906. g[t + 2] = f[5];
  1907. g[t + 3] = f[4];
  1908. g[t + 4] = f[3];
  1909. g[t + 5] = f[2];
  1910. g[t + 6] = f[1];
  1911. g[t + 7] = f[0]
  1912. }
  1913.  
  1914. function k(v, g) {
  1915. return f[0] = v[g], f[1] = v[g + 1], f[2] = v[g + 2], f[3] = v[g + 3], f[4] = v[g + 4], f[5] = v[g + 5], f[6] = v[g + 6], f[7] = v[g + 7], q[0]
  1916. }
  1917.  
  1918. function l(v, g) {
  1919. return f[7] = v[g], f[6] = v[g + 1], f[5] = v[g + 2], f[4] = v[g + 3], f[3] = v[g + 4], f[2] = v[g + 5], f[1] = v[g + 6], f[0] = v[g + 7], q[0]
  1920. }
  1921.  
  1922. var q = new Float64Array([-0]), f = new Uint8Array(q.buffer), u = 128 === f[7];
  1923. a.writeDoubleLE = u ? b : c;
  1924. a.writeDoubleBE = u ? c : b;
  1925. a.readDoubleLE = u ? k : l;
  1926. a.readDoubleBE = u ? l : k
  1927. }() : function () {
  1928. function b(k, l, q, f, u, v) {
  1929. var g = 0 > f ? 1 : 0;
  1930. if (g && (f = -f), 0 === f) k(0, u, v + l), k(0 < 1 / f ? 0 : 2147483648, u, v + q); else if (isNaN(f)) k(0, u, v + l), k(2146959360, u, v + q); else if (1.7976931348623157E308 < f) k(0, u, v + l), k((g << 31 | 2146435072) >>> 0, u, v + q); else if (2.2250738585072014E-308 > f) k((f /= 4.9E-324) >>> 0, u, v + l), k((g << 31 | f / 4294967296) >>> 0, u, v + q); else {
  1931. var t = Math.floor(Math.log(f) / Math.LN2);
  1932. 1024 === t && (t = 1023);
  1933. k(4503599627370496 * (f *= Math.pow(2, -t)) >>> 0, u, v + l);
  1934. k((g << 31 | t + 1023 << 20 | 1048576 * f & 1048575) >>> 0, u, v + q)
  1935. }
  1936. }
  1937.  
  1938. function c(k, l, q, f, u) {
  1939. l = k(f, u + l);
  1940. f = k(f, u + q);
  1941. k = 2 * (f >> 31) + 1;
  1942. q = f >>> 20 & 2047;
  1943. l = 4294967296 * (1048575 & f) + l;
  1944. return 2047 === q ? l ? NaN : 1 / 0 * k : 0 === q ? 4.9E-324 * k * l : k * Math.pow(2, q - 1075) * (l + 4503599627370496)
  1945. }
  1946.  
  1947. a.writeDoubleLE = b.bind(null, m, 0, 4);
  1948. a.writeDoubleBE = b.bind(null, n, 4, 0);
  1949. a.readDoubleLE = c.bind(null, e, 0, 4);
  1950. a.readDoubleBE = c.bind(null, d, 4, 0)
  1951. }(), a
  1952. }
  1953.  
  1954. function m(a, b, c) {
  1955. b[c] = 255 & a;
  1956. b[c + 1] = a >>> 8 & 255;
  1957. b[c + 2] = a >>> 16 & 255;
  1958. b[c + 3] = a >>> 24
  1959. }
  1960.  
  1961. function n(a, b, c) {
  1962. b[c] = a >>> 24;
  1963. b[c + 1] = a >>> 16 & 255;
  1964. b[c + 2] = a >>> 8 & 255;
  1965. b[c + 3] = 255 & a
  1966. }
  1967.  
  1968. function e(a, b) {
  1969. return (a[b] | a[b + 1] << 8 | a[b + 2] << 16 | a[b + 3] << 24) >>> 0
  1970. }
  1971.  
  1972. function d(a, b) {
  1973. return (a[b] << 24 | a[b + 1] << 16 | a[b + 2] << 8 | a[b + 3]) >>> 0
  1974. }
  1975.  
  1976. w.exports = h(h)
  1977. }, {}], 5: [function (p, w, h) {
  1978. w.exports = function (m) {
  1979. try {
  1980. var n = eval("require")(m);
  1981. if (n && (n.length || Object.keys(n).length)) return n
  1982. } catch (e) {
  1983. }
  1984. return null
  1985. }
  1986. }, {}], 6: [function (p, w) {
  1987. w.exports = function (h, m, n) {
  1988. var e = n || 8192, d = e >>> 1, a = null, b = e;
  1989. return function (c) {
  1990. if (1 > c || d < c) return h(c);
  1991. e < b + c && (a = h(e), b = 0);
  1992. c = m.call(a, b, b += c);
  1993. return 7 & b && (b = 1 + (7 | b)), c
  1994. }
  1995. }
  1996. }, {}], 7: [function (p, w, h) {
  1997. h.length = function (m) {
  1998. for (var n = 0, e = 0, d = 0; d < m.length; ++d) 128 > (e = m.charCodeAt(d)) ? n += 1 : 2048 > e ? n += 2 : 55296 == (64512 & e) && 56320 == (64512 & m.charCodeAt(d + 1)) ? (++d, n += 4) : n += 3;
  1999. return n
  2000. };
  2001. h.read = function (m, n, e) {
  2002. if (1 > e - n) return "";
  2003. for (var d, a = null, b = [], c = 0; n < e;) 128 > (d = m[n++]) ? b[c++] = d : 191 < d && 224 > d ? b[c++] = (31 & d) << 6 | 63 & m[n++] : 239 < d && 365 > d ? (d = ((7 & d) << 18 | (63 & m[n++]) << 12 | (63 & m[n++]) << 6 | 63 & m[n++]) - 65536, b[c++] = 55296 + (d >> 10), b[c++] = 56320 + (1023 & d)) : b[c++] = (15 & d) << 12 | (63 & m[n++]) << 6 | 63 & m[n++], 8191 < c && ((a || (a = [])).push(String.fromCharCode.apply(String, b)), c = 0);
  2004. return a ? (c && a.push(String.fromCharCode.apply(String, b.slice(0, c))), a.join("")) : String.fromCharCode.apply(String, b.slice(0, c))
  2005. };
  2006. h.write = function (m, n, e) {
  2007. for (var d, a, b = e, c = 0; c < m.length; ++c) 128 > (d = m.charCodeAt(c)) ? n[e++] = d : (2048 > d ? n[e++] = d >> 6 | 192 : (55296 == (64512 & d) && 56320 == (64512 & (a = m.charCodeAt(c + 1))) ? (d = 65536 + ((1023 & d) << 10) + (1023 & a), ++c, n[e++] = d >> 18 | 240, n[e++] = d >> 12 & 63 | 128) : n[e++] = d >> 12 | 224, n[e++] = d >> 6 & 63 | 128), n[e++] = 63 & d | 128);
  2008. return e - b
  2009. }
  2010. }, {}], 8: [function (p, w, h) {
  2011. function m() {
  2012. n.Reader.n(n.BufferReader);
  2013. n.util.n()
  2014. }
  2015.  
  2016. var n = h;
  2017. n.build = "minimal";
  2018. n.Writer = p(16);
  2019. n.BufferWriter = p(17);
  2020. n.Reader = p(9);
  2021. n.BufferReader = p(10);
  2022. n.util = p(15);
  2023. n.rpc = p(12);
  2024. n.roots = p(11);
  2025. n.configure = m;
  2026. n.Writer.n(n.BufferWriter);
  2027. m()
  2028. }, {10: 10, 11: 11, 12: 12, 15: 15, 16: 16, 17: 17, 9: 9}], 9: [function (p, w) {
  2029. function h(f, u) {
  2030. return RangeError("index out of range: " + f.pos + " + " + (u || 1) + " > " + f.len)
  2031. }
  2032.  
  2033. function m(f) {
  2034. this.buf = f;
  2035. this.pos = 0;
  2036. this.len = f.length
  2037. }
  2038.  
  2039. function n() {
  2040. var f = new c(0, 0), u = 0;
  2041. if (!(4 < this.len - this.pos)) {
  2042. for (; 3 > u; ++u) {
  2043. if (this.pos >= this.len) throw h(this);
  2044. if (f.lo = (f.lo | (127 & this.buf[this.pos]) << 7 * u) >>> 0, 128 > this.buf[this.pos++]) return f
  2045. }
  2046. return f.lo = (f.lo | (127 & this.buf[this.pos++]) << 7 * u) >>> 0, f
  2047. }
  2048. for (; 4 > u; ++u) if (f.lo = (f.lo | (127 & this.buf[this.pos]) << 7 * u) >>> 0, 128 > this.buf[this.pos++]) return f;
  2049. if (f.lo = (f.lo | (127 & this.buf[this.pos]) << 28) >>> 0, f.hi = (f.hi | (127 & this.buf[this.pos]) >> 4) >>> 0, 128 > this.buf[this.pos++]) return f;
  2050. if (u = 0, 4 < this.len - this.pos) for (; 5 > u; ++u) {
  2051. if (f.hi = (f.hi | (127 & this.buf[this.pos]) << 7 * u + 3) >>> 0, 128 > this.buf[this.pos++]) return f
  2052. } else for (; 5 > u; ++u) {
  2053. if (this.pos >= this.len) throw h(this);
  2054. if (f.hi = (f.hi | (127 & this.buf[this.pos]) << 7 * u + 3) >>> 0, 128 > this.buf[this.pos++]) return f
  2055. }
  2056. throw Error("invalid varint encoding");
  2057. }
  2058.  
  2059. function e(f, u) {
  2060. return (f[u - 4] | f[u - 3] << 8 | f[u - 2] << 16 | f[u - 1] << 24) >>> 0
  2061. }
  2062.  
  2063. function d() {
  2064. if (this.pos + 8 > this.len) throw h(this, 8);
  2065. return new c(e(this.buf, this.pos += 4), e(this.buf, this.pos += 4))
  2066. }
  2067.  
  2068. w.exports = m;
  2069. var a, b = p(15), c = b.LongBits, k = b.utf8, l,
  2070. q = "undefined" != typeof Uint8Array ? function (f) {
  2071. if (f instanceof Uint8Array || Array.isArray(f)) return new m(f);
  2072. throw Error("illegal buffer");
  2073. } : function (f) {
  2074. if (Array.isArray(f)) return new m(f);
  2075. throw Error("illegal buffer");
  2076. };
  2077. m.create = b.Buffer ? function (f) {
  2078. return (m.create = function (u) {
  2079. return b.Buffer.isBuffer(u) ? new a(u) : q(u)
  2080. })(f)
  2081. } : q;
  2082. m.prototype.i = b.Array.prototype.subarray || b.Array.prototype.slice;
  2083. m.prototype.uint32 = (l = 4294967295, function () {
  2084. if ((l = (127 & this.buf[this.pos]) >>> 0, 128 > this.buf[this.pos++]) || (l = (l | (127 & this.buf[this.pos]) << 7) >>> 0, 128 > this.buf[this.pos++]) || (l = (l | (127 & this.buf[this.pos]) << 14) >>> 0, 128 > this.buf[this.pos++]) || (l = (l | (127 & this.buf[this.pos]) << 21) >>> 0, 128 > this.buf[this.pos++]) || (l = (l | (15 & this.buf[this.pos]) << 28) >>> 0, 128 > this.buf[this.pos++])) return l;
  2085. if ((this.pos += 5) > this.len) throw this.pos = this.len, h(this, 10);
  2086. return l
  2087. });
  2088. m.prototype.int32 = function () {
  2089. return 0 | this.uint32()
  2090. };
  2091. m.prototype.sint32 = function () {
  2092. var f = this.uint32();
  2093. return f >>> 1 ^ -(1 & f) | 0
  2094. };
  2095. m.prototype.bool = function () {
  2096. return 0 !== this.uint32()
  2097. };
  2098. m.prototype.fixed32 = function () {
  2099. if (this.pos + 4 > this.len) throw h(this, 4);
  2100. return e(this.buf, this.pos += 4)
  2101. };
  2102. m.prototype.sfixed32 = function () {
  2103. if (this.pos + 4 > this.len) throw h(this, 4);
  2104. return 0 | e(this.buf, this.pos += 4)
  2105. };
  2106. m.prototype["float"] = function () {
  2107. if (this.pos + 4 > this.len) throw h(this, 4);
  2108. var f = b["float"].readFloatLE(this.buf, this.pos);
  2109. return this.pos += 4, f
  2110. };
  2111. m.prototype["double"] = function () {
  2112. if (this.pos + 8 > this.len) throw h(this, 4);
  2113. var f = b["float"].readDoubleLE(this.buf, this.pos);
  2114. return this.pos += 8, f
  2115. };
  2116. m.prototype.bytes = function () {
  2117. var f = this.uint32(), u = this.pos, v = this.pos + f;
  2118. if (v > this.len) throw h(this, f);
  2119. return this.pos += f, Array.isArray(this.buf) ? this.buf.slice(u, v) : u === v ? new this.buf.constructor(0) : this.i.call(this.buf, u, v)
  2120. };
  2121. m.prototype.string = function () {
  2122. var f = this.bytes();
  2123. return k.read(f, 0, f.length)
  2124. };
  2125. m.prototype.skip = function (f) {
  2126. if ("number" == typeof f) {
  2127. if (this.pos + f > this.len) throw h(this, f);
  2128. this.pos += f
  2129. } else {
  2130. do if (this.pos >= this.len) throw h(this); while (128 & this.buf[this.pos++])
  2131. }
  2132. return this
  2133. };
  2134. m.prototype.skipType = function (f) {
  2135. switch (f) {
  2136. case 0:
  2137. this.skip();
  2138. break;
  2139. case 1:
  2140. this.skip(8);
  2141. break;
  2142. case 2:
  2143. this.skip(this.uint32());
  2144. break;
  2145. case 3:
  2146. for (; 4 != (f = 7 & this.uint32());) this.skipType(f);
  2147. break;
  2148. case 5:
  2149. this.skip(4);
  2150. break;
  2151. default:
  2152. throw Error("invalid wire type " + f + " at offset " + this.pos);
  2153. }
  2154. return this
  2155. };
  2156. m.n = function (f) {
  2157. a = f;
  2158. var u = b.Long ? "toLong" : "toNumber";
  2159. b.merge(m.prototype, {
  2160. int64: function () {
  2161. return n.call(this)[u](!1)
  2162. }, uint64: function () {
  2163. return n.call(this)[u](!0)
  2164. }, sint64: function () {
  2165. return n.call(this).zzDecode()[u](!1)
  2166. }, fixed64: function () {
  2167. return d.call(this)[u](!0)
  2168. }, sfixed64: function () {
  2169. return d.call(this)[u](!1)
  2170. }
  2171. })
  2172. }
  2173. }, {15: 15}], 10: [function (p, w) {
  2174. function h(e) {
  2175. m.call(this, e)
  2176. }
  2177.  
  2178. w.exports = h;
  2179. var m = p(9);
  2180. (h.prototype = Object.create(m.prototype)).constructor = h;
  2181. var n = p(15);
  2182. n.Buffer && (h.prototype.i = n.Buffer.prototype.slice);
  2183. h.prototype.string = function () {
  2184. var e = this.uint32();
  2185. return this.buf.utf8Slice(this.pos, this.pos = Math.min(this.pos + e, this.len))
  2186. }
  2187. }, {15: 15, 9: 9}], 11: [function (p, w) {
  2188. w.exports = {}
  2189. }, {}], 12: [function (p, w, h) {
  2190. h.Service = p(13)
  2191. }, {13: 13}], 13: [function (p, w) {
  2192. function h(n, e, d) {
  2193. if ("function" != typeof n) throw TypeError("rpcImpl must be a function");
  2194. m.EventEmitter.call(this);
  2195. this.rpcImpl = n;
  2196. this.requestDelimited = !!e;
  2197. this.responseDelimited = !!d
  2198. }
  2199.  
  2200. w.exports = h;
  2201. var m = p(15);
  2202. ((h.prototype = Object.create(m.EventEmitter.prototype)).constructor = h).prototype.rpcCall = function k(e, d, a, b, c) {
  2203. if (!b) throw TypeError("request must be specified");
  2204. var l = this;
  2205. if (!c) return m.asPromise(k, l, e, d, a, b);
  2206. if (!l.rpcImpl) return setTimeout(function () {
  2207. c(Error("already ended"))
  2208. }, 0), z;
  2209. try {
  2210. return l.rpcImpl(e, d[l.requestDelimited ? "encodeDelimited" : "encode"](b).finish(), function (q, f) {
  2211. if (q) return l.emit("error", q, e), c(q);
  2212. if (null === f) return l.end(!0), z;
  2213. if (!(f instanceof a)) try {
  2214. f = a[l.responseDelimited ? "decodeDelimited" : "decode"](f)
  2215. } catch (u) {
  2216. return l.emit("error", u, e), c(u)
  2217. }
  2218. return l.emit("data", f, e), c(null, f)
  2219. })
  2220. } catch (q) {
  2221. return l.emit("error", q, e), setTimeout(function () {
  2222. c(q)
  2223. }, 0), z
  2224. }
  2225. };
  2226. h.prototype.end = function (e) {
  2227. return this.rpcImpl && (e || this.rpcImpl(null, null, null), this.rpcImpl = null, this.emit("end").off()), this
  2228. }
  2229. }, {15: 15}], 14: [function (p, w) {
  2230. function h(a, b) {
  2231. this.lo = a >>> 0;
  2232. this.hi = b >>> 0
  2233. }
  2234.  
  2235. w.exports = h;
  2236. var m = p(15), n = h.zero = new h(0, 0);
  2237. n.toNumber = function () {
  2238. return 0
  2239. };
  2240. n.zzEncode = n.zzDecode = function () {
  2241. return this
  2242. };
  2243. n.length = function () {
  2244. return 1
  2245. };
  2246. var e = h.zeroHash = "\x00\x00\x00\x00\x00\x00\x00\x00";
  2247. h.fromNumber = function (a) {
  2248. if (0 === a) return n;
  2249. var b = 0 > a;
  2250. b && (a = -a);
  2251. var c = a >>> 0;
  2252. a = (a - c) / 4294967296 >>> 0;
  2253. return b && (a = ~a >>> 0, c = ~c >>> 0, 4294967295 < ++c && (c = 0, 4294967295 < ++a && (a = 0))), new h(c, a)
  2254. };
  2255. h.from = function (a) {
  2256. if ("number" == typeof a) return h.fromNumber(a);
  2257. if (m.isString(a)) {
  2258. if (!m.Long) return h.fromNumber(parseInt(a, 10));
  2259. a = m.Long.fromString(a)
  2260. }
  2261. return a.low || a.high ? new h(a.low >>> 0, a.high >>> 0) : n
  2262. };
  2263. h.prototype.toNumber = function (a) {
  2264. if (!a && this.hi >>> 31) {
  2265. a = 1 + ~this.lo >>> 0;
  2266. var b = ~this.hi >>> 0;
  2267. return a || (b = b + 1 >>> 0), -(a + 4294967296 * b)
  2268. }
  2269. return this.lo + 4294967296 * this.hi
  2270. };
  2271. h.prototype.toLong = function (a) {
  2272. return m.Long ? new m.Long(0 | this.lo, 0 | this.hi, !!a) : {
  2273. low: 0 | this.lo, high: 0 | this.hi, unsigned: !!a
  2274. }
  2275. };
  2276. var d = String.prototype.charCodeAt;
  2277. h.fromHash = function (a) {
  2278. return a === e ? n : new h((d.call(a, 0) | d.call(a, 1) << 8 | d.call(a, 2) << 16 | d.call(a, 3) << 24) >>> 0, (d.call(a, 4) | d.call(a, 5) << 8 | d.call(a, 6) << 16 | d.call(a, 7) << 24) >>> 0)
  2279. };
  2280. h.prototype.toHash = function () {
  2281. return String.fromCharCode(255 & this.lo, this.lo >>> 8 & 255, this.lo >>> 16 & 255, this.lo >>> 24, 255 & this.hi, this.hi >>> 8 & 255, this.hi >>> 16 & 255, this.hi >>> 24)
  2282. };
  2283. h.prototype.zzEncode = function () {
  2284. var a = this.hi >> 31;
  2285. return this.hi = ((this.hi << 1 | this.lo >>> 31) ^ a) >>> 0, this.lo = (this.lo << 1 ^ a) >>> 0, this
  2286. };
  2287. h.prototype.zzDecode = function () {
  2288. var a = -(1 & this.lo);
  2289. return this.lo = ((this.lo >>> 1 | this.hi << 31) ^ a) >>> 0, this.hi = (this.hi >>> 1 ^ a) >>> 0, this
  2290. };
  2291. h.prototype.length = function () {
  2292. var a = this.lo, b = (this.lo >>> 28 | this.hi << 4) >>> 0, c = this.hi >>> 24;
  2293. return 0 === c ? 0 === b ? 16384 > a ? 128 > a ? 1 : 2 : 2097152 > a ? 3 : 4 : 16384 > b ? 128 > b ? 5 : 6 : 2097152 > b ? 7 : 8 : 128 > c ? 9 : 10
  2294. }
  2295. }, {15: 15}], 15: [function (p, w, h) {
  2296. function m(e, d, a) {
  2297. for (var b = Object.keys(d), c = 0; c < b.length; ++c) e[b[c]] !== z && a || (e[b[c]] = d[b[c]]);
  2298. return e
  2299. }
  2300.  
  2301. function n(e) {
  2302. function d(a, b) {
  2303. if (!(this instanceof d)) return new d(a, b);
  2304. Object.defineProperty(this, "message", {
  2305. get: function () {
  2306. return a
  2307. }
  2308. });
  2309. Error.captureStackTrace ? Error.captureStackTrace(this, d) : Object.defineProperty(this, "stack", {value: Error().stack || ""});
  2310. b && m(this, b)
  2311. }
  2312.  
  2313. return (d.prototype = Object.create(Error.prototype)).constructor = d, Object.defineProperty(d.prototype, "name", {
  2314. get: function () {
  2315. return e
  2316. }
  2317. }), d.prototype.toString = function () {
  2318. return this.name + ": " + this.message
  2319. }, d
  2320. }
  2321.  
  2322. h.asPromise = p(1);
  2323. h.base64 = p(2);
  2324. h.EventEmitter = p(3);
  2325. h["float"] = p(4);
  2326. h.inquire = p(5);
  2327. h.utf8 = p(7);
  2328. h.pool = p(6);
  2329. h.LongBits = p(14);
  2330. h.global = "undefined" != typeof window && window || "undefined" != typeof global && global || "undefined" != typeof self && self || this;
  2331. h.emptyArray = Object.freeze ? Object.freeze([]) : [];
  2332. h.emptyObject = Object.freeze ? Object.freeze({}) : {};
  2333. h.isNode = !!(h.global.process && h.global.process.versions && h.global.process.versions.node);
  2334. h.isInteger = Number.isInteger || function (e) {
  2335. return "number" == typeof e && isFinite(e) && Math.floor(e) === e
  2336. };
  2337. h.isString = function (e) {
  2338. return "string" == typeof e || e instanceof String
  2339. };
  2340. h.isObject = function (e) {
  2341. return e && "object" == typeof e
  2342. };
  2343. h.isset = h.isSet = function (e, d) {
  2344. var a = e[d];
  2345. return !(null == a || !e.hasOwnProperty(d)) && ("object" != typeof a || 0 < (Array.isArray(a) ? a.length : Object.keys(a).length))
  2346. };
  2347. h.Buffer = function () {
  2348. try {
  2349. var e = h.inquire("buffer").Buffer;
  2350. return e.prototype.utf8Write ? e : null
  2351. } catch (d) {
  2352. return null
  2353. }
  2354. }();
  2355. h.r = null;
  2356. h.u = null;
  2357. h.newBuffer = function (e) {
  2358. return "number" == typeof e ? h.Buffer ? h.u(e) : new h.Array(e) : h.Buffer ? h.r(e) : "undefined" == typeof Uint8Array ? e : new Uint8Array(e)
  2359. };
  2360. h.Array = "undefined" != typeof Uint8Array ? Uint8Array : Array;
  2361. h.Long = h.global.dcodeIO && h.global.dcodeIO.Long || h.global.Long || h.inquire("long");
  2362. h.key2Re = /^true|false|0|1$/;
  2363. h.key32Re = /^-?(?:0|[1-9][0-9]*)$/;
  2364. h.key64Re = /^(?:[\\x00-\\xff]{8}|-?(?:0|[1-9][0-9]*))$/;
  2365. h.longToHash = function (e) {
  2366. return e ? h.LongBits.from(e).toHash() : h.LongBits.zeroHash
  2367. };
  2368. h.longFromHash = function (e, d) {
  2369. var a = h.LongBits.fromHash(e);
  2370. return h.Long ? h.Long.fromBits(a.lo, a.hi, d) : a.toNumber(!!d)
  2371. };
  2372. h.merge = m;
  2373. h.lcFirst = function (e) {
  2374. return e.charAt(0).toLowerCase() + e.substring(1)
  2375. };
  2376. h.newError = n;
  2377. h.ProtocolError = n("ProtocolError");
  2378. h.oneOfGetter = function (e) {
  2379. for (var d = {}, a = 0; a < e.length; ++a) d[e[a]] = 1;
  2380. return function () {
  2381. for (var b = Object.keys(this), c = b.length - 1; -1 < c; --c) if (1 === d[b[c]] && this[b[c]] !== z && null !== this[b[c]]) return b[c]
  2382. }
  2383. };
  2384. h.oneOfSetter = function (e) {
  2385. return function (d) {
  2386. for (var a = 0; a < e.length; ++a) e[a] !== d && delete this[e[a]]
  2387. }
  2388. };
  2389. h.toJSONOptions = {longs: String, enums: String, bytes: String, json: !0};
  2390. h.n = function () {
  2391. var e = h.Buffer;
  2392. e ? (h.r = e.from !== Uint8Array.from && e.from || function (d, a) {
  2393. return new e(d, a)
  2394. }, h.u = e.allocUnsafe || function (d) {
  2395. return new e(d)
  2396. }) : h.r = h.u = null
  2397. }
  2398. }, {1: 1, 14: 14, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7}], 16: [function (p, w) {
  2399. function h(g, t, x) {
  2400. this.fn = g;
  2401. this.len = t;
  2402. this.next = z;
  2403. this.val = x
  2404. }
  2405.  
  2406. function m() {
  2407. }
  2408.  
  2409. function n(g) {
  2410. this.head = g.head;
  2411. this.tail = g.tail;
  2412. this.len = g.len;
  2413. this.next = g.states
  2414. }
  2415.  
  2416. function e() {
  2417. this.len = 0;
  2418. this.tail = this.head = new h(m, 0, 0);
  2419. this.states = null
  2420. }
  2421.  
  2422. function d(g, t, x) {
  2423. t[x] = 255 & g
  2424. }
  2425.  
  2426. function a(g, t) {
  2427. this.len = g;
  2428. this.next = z;
  2429. this.val = t
  2430. }
  2431.  
  2432. function b(g, t, x) {
  2433. for (; g.hi;) t[x++] = 127 & g.lo | 128, g.lo = (g.lo >>> 7 | g.hi << 25) >>> 0, g.hi >>>= 7;
  2434. for (; 127 < g.lo;) t[x++] = 127 & g.lo | 128, g.lo >>>= 7;
  2435. t[x++] = g.lo
  2436. }
  2437.  
  2438. function c(g, t, x) {
  2439. t[x] = 255 & g;
  2440. t[x + 1] = g >>> 8 & 255;
  2441. t[x + 2] = g >>> 16 & 255;
  2442. t[x + 3] = g >>> 24
  2443. }
  2444.  
  2445. w.exports = e;
  2446. var k, l = p(15), q = l.LongBits, f = l.base64, u = l.utf8;
  2447. e.create = l.Buffer ? function () {
  2448. return (e.create = function () {
  2449. return new k
  2450. })()
  2451. } : function () {
  2452. return new e
  2453. };
  2454. e.alloc = function (g) {
  2455. return new l.Array(g)
  2456. };
  2457. l.Array !== Array && (e.alloc = l.pool(e.alloc, l.Array.prototype.subarray));
  2458. e.prototype.e = function (g, t, x) {
  2459. return this.tail = this.tail.next = new h(g, t, x), this.len += t, this
  2460. };
  2461. (a.prototype = Object.create(h.prototype)).fn = function (g, t, x) {
  2462. for (; 127 < g;) t[x++] = 127 & g | 128, g >>>= 7;
  2463. t[x] = g
  2464. };
  2465. e.prototype.uint32 = function (g) {
  2466. return this.len += (this.tail = this.tail.next = new a(128 > (g >>>= 0) ? 1 : 16384 > g ? 2 : 2097152 > g ? 3 : 268435456 > g ? 4 : 5, g)).len, this
  2467. };
  2468. e.prototype.int32 = function (g) {
  2469. return 0 > g ? this.e(b, 10, q.fromNumber(g)) : this.uint32(g)
  2470. };
  2471. e.prototype.sint32 = function (g) {
  2472. return this.uint32((g << 1 ^ g >> 31) >>> 0)
  2473. };
  2474. e.prototype.int64 = e.prototype.uint64 = function (g) {
  2475. g = q.from(g);
  2476. return this.e(b, g.length(), g)
  2477. };
  2478. e.prototype.sint64 = function (g) {
  2479. g = q.from(g).zzEncode();
  2480. return this.e(b, g.length(), g)
  2481. };
  2482. e.prototype.bool = function (g) {
  2483. return this.e(d, 1, g ? 1 : 0)
  2484. };
  2485. e.prototype.sfixed32 = e.prototype.fixed32 = function (g) {
  2486. return this.e(c, 4, g >>> 0)
  2487. };
  2488. e.prototype.sfixed64 = e.prototype.fixed64 = function (g) {
  2489. g = q.from(g);
  2490. return this.e(c, 4, g.lo).e(c, 4, g.hi)
  2491. };
  2492. e.prototype["float"] = function (g) {
  2493. return this.e(l["float"].writeFloatLE, 4, g)
  2494. };
  2495. e.prototype["double"] = function (g) {
  2496. return this.e(l["float"].writeDoubleLE, 8, g)
  2497. };
  2498. var v = l.Array.prototype.set ? function (g, t, x) {
  2499. t.set(g, x)
  2500. } : function (g, t, x) {
  2501. for (var B = 0; B < g.length; ++B) t[x + B] = g[B]
  2502. };
  2503. e.prototype.bytes = function (g) {
  2504. var t = g.length >>> 0;
  2505. if (!t) return this.e(d, 1, 0);
  2506. if (l.isString(g)) {
  2507. var x = e.alloc(t = f.length(g));
  2508. f.decode(g, x, 0);
  2509. g = x
  2510. }
  2511. return this.uint32(t).e(v, t, g)
  2512. };
  2513. e.prototype.string = function (g) {
  2514. var t = u.length(g);
  2515. return t ? this.uint32(t).e(u.write, t, g) : this.e(d, 1, 0)
  2516. };
  2517. e.prototype.fork = function () {
  2518. return this.states = new n(this), this.head = this.tail = new h(m, 0, 0), this.len = 0, this
  2519. };
  2520. e.prototype.reset = function () {
  2521. return this.states ? (this.head = this.states.head, this.tail = this.states.tail, this.len = this.states.len, this.states = this.states.next) : (this.head = this.tail = new h(m, 0, 0), this.len = 0), this
  2522. };
  2523. e.prototype.ldelim = function () {
  2524. var g = this.head, t = this.tail, x = this.len;
  2525. return this.reset().uint32(x), x && (this.tail.next = g.next, this.tail = t, this.len += x), this
  2526. };
  2527. e.prototype.finish = function () {
  2528. for (var g = this.head.next, t = this.constructor.alloc(this.len), x = 0; g;) g.fn(g.val, t, x), x += g.len, g = g.next;
  2529. return t
  2530. };
  2531. e.n = function (g) {
  2532. k = g
  2533. }
  2534. }, {15: 15}], 17: [function (p, w) {
  2535. function h() {
  2536. n.call(this)
  2537. }
  2538.  
  2539. function m(b, c, k) {
  2540. 40 > b.length ? e.utf8.write(b, c, k) : c.utf8Write(b, k)
  2541. }
  2542.  
  2543. w.exports = h;
  2544. var n = p(16);
  2545. (h.prototype = Object.create(n.prototype)).constructor = h;
  2546. var e = p(15), d = e.Buffer;
  2547. h.alloc = function (b) {
  2548. return (h.alloc = e.u)(b)
  2549. };
  2550. var a = d && d.prototype instanceof Uint8Array && "set" === d.prototype.set.name ? function (b, c, k) {
  2551. c.set(b, k)
  2552. } : function (b, c, k) {
  2553. if (b.copy) b.copy(c, k, 0, b.length); else for (var l = 0; l < b.length;) c[k++] = b[l++]
  2554. };
  2555. h.prototype.bytes = function (b) {
  2556. e.isString(b) && (b = e.r(b, "base64"));
  2557. var c = b.length >>> 0;
  2558. return this.uint32(c), c && this.e(a, c, b), this
  2559. };
  2560. h.prototype.string = function (b) {
  2561. var c = d.byteLength(b);
  2562. return this.uint32(c), c && this.e(m, c, b), this
  2563. }
  2564. }, {15: 15, 16: 16}]
  2565. };
  2566. var A = {};
  2567. var r = function h(w) {
  2568. var m = A[w];
  2569. return m || y[w][0].call(m = A[w] = {exports: {}}, h, m, m.exports), m.exports
  2570. }(8);
  2571. r.util.global.protobuf = r;
  2572. "function" == typeof define && define.amd && define(["long"], function (w) {
  2573. return w && w.isLong && (r.util.Long = w, r.configure()), r
  2574. });
  2575. "object" == typeof module && module && module.exports && (module.exports = r)
  2576. }();
  2577. (function (z) {
  2578. var y = z.Reader, A = z.Writer, r = z.util, p = z.roots["default"] || (z.roots["default"] = {});
  2579. p.bilibili = function () {
  2580. var w = {};
  2581. w.community = function () {
  2582. var h = {};
  2583. h.service = function () {
  2584. var m = {};
  2585. m.dm = function () {
  2586. var n = {};
  2587. n.v1 = function () {
  2588. var e = {};
  2589. e.DmWebViewReply = function () {
  2590. function d(a) {
  2591. this.specialDms = [];
  2592. if (a) for (var b = Object.keys(a), c = 0; c < b.length; ++c) null != a[b[c]] && (this[b[c]] = a[b[c]])
  2593. }
  2594.  
  2595. d.prototype.state = 0;
  2596. d.prototype.text = "";
  2597. d.prototype.textSide = "";
  2598. d.prototype.dmSge = null;
  2599. d.prototype.flag = null;
  2600. d.prototype.specialDms = r.emptyArray;
  2601. d.create = function (a) {
  2602. return new d(a)
  2603. };
  2604. d.encode = function (a, b) {
  2605. b || (b = A.create());
  2606. null != a.state && Object.hasOwnProperty.call(a, "state") && b.uint32(8).int32(a.state);
  2607. null != a.text && Object.hasOwnProperty.call(a, "text") && b.uint32(18).string(a.text);
  2608. null != a.textSide && Object.hasOwnProperty.call(a, "textSide") && b.uint32(26).string(a.textSide);
  2609. null != a.dmSge && Object.hasOwnProperty.call(a, "dmSge") && p.bilibili.community.service.dm.v1.DmSegConfig.encode(a.dmSge, b.uint32(34).fork()).ldelim();
  2610. null != a.flag && Object.hasOwnProperty.call(a, "flag") && p.bilibili.community.service.dm.v1.DanmakuFlagConfig.encode(a.flag, b.uint32(42).fork()).ldelim();
  2611. if (null != a.specialDms && a.specialDms.length) for (var c = 0; c < a.specialDms.length; ++c) b.uint32(50).string(a.specialDms[c]);
  2612. return b
  2613. };
  2614. d.encodeDelimited = function (a, b) {
  2615. return this.encode(a, b).ldelim()
  2616. };
  2617. d.decode = function (a, b) {
  2618. a instanceof y || (a = y.create(a));
  2619. for (var c = void 0 === b ? a.len : a.pos + b, k = new p.bilibili.community.service.dm.v1.DmWebViewReply; a.pos < c;) {
  2620. var l = a.uint32();
  2621. switch (l >>> 3) {
  2622. case 1:
  2623. k.state = a.int32();
  2624. break;
  2625. case 2:
  2626. k.text = a.string();
  2627. break;
  2628. case 3:
  2629. k.textSide = a.string();
  2630. break;
  2631. case 4:
  2632. k.dmSge = p.bilibili.community.service.dm.v1.DmSegConfig.decode(a, a.uint32());
  2633. break;
  2634. case 5:
  2635. k.flag = p.bilibili.community.service.dm.v1.DanmakuFlagConfig.decode(a, a.uint32());
  2636. break;
  2637. case 6:
  2638. k.specialDms && k.specialDms.length || (k.specialDms = []);
  2639. k.specialDms.push(a.string());
  2640. break;
  2641. default:
  2642. a.skipType(l & 7)
  2643. }
  2644. }
  2645. return k
  2646. };
  2647. d.decodeDelimited = function (a) {
  2648. a instanceof y || (a = new y(a));
  2649. return this.decode(a, a.uint32())
  2650. };
  2651. d.verify = function (a) {
  2652. if ("object" !== typeof a || null === a) return "object expected";
  2653. if (null != a.state && a.hasOwnProperty("state") && !r.isInteger(a.state)) return "state: integer expected";
  2654. if (null != a.text && a.hasOwnProperty("text") && !r.isString(a.text)) return "text: string expected";
  2655. if (null != a.textSide && a.hasOwnProperty("textSide") && !r.isString(a.textSide)) return "textSide: string expected";
  2656. if (null != a.dmSge && a.hasOwnProperty("dmSge")) {
  2657. var b = p.bilibili.community.service.dm.v1.DmSegConfig.verify(a.dmSge);
  2658. if (b) return "dmSge." + b
  2659. }
  2660. if (null != a.flag && a.hasOwnProperty("flag") && (b = p.bilibili.community.service.dm.v1.DanmakuFlagConfig.verify(a.flag))) return "flag." + b;
  2661. if (null != a.specialDms && a.hasOwnProperty("specialDms")) {
  2662. if (!Array.isArray(a.specialDms)) return "specialDms: array expected";
  2663. for (b = 0; b < a.specialDms.length; ++b) if (!r.isString(a.specialDms[b])) return "specialDms: string[] expected"
  2664. }
  2665. return null
  2666. };
  2667. d.fromObject = function (a) {
  2668. if (a instanceof p.bilibili.community.service.dm.v1.DmWebViewReply) return a;
  2669. var b = new p.bilibili.community.service.dm.v1.DmWebViewReply;
  2670. null != a.state && (b.state = a.state | 0);
  2671. null != a.text && (b.text = String(a.text));
  2672. null != a.textSide && (b.textSide = String(a.textSide));
  2673. if (null != a.dmSge) {
  2674. if ("object" !== typeof a.dmSge) throw TypeError(".bilibili.community.service.dm.v1.DmWebViewReply.dmSge: object expected");
  2675. b.dmSge = p.bilibili.community.service.dm.v1.DmSegConfig.fromObject(a.dmSge)
  2676. }
  2677. if (null != a.flag) {
  2678. if ("object" !== typeof a.flag) throw TypeError(".bilibili.community.service.dm.v1.DmWebViewReply.flag: object expected");
  2679. b.flag = p.bilibili.community.service.dm.v1.DanmakuFlagConfig.fromObject(a.flag)
  2680. }
  2681. if (a.specialDms) {
  2682. if (!Array.isArray(a.specialDms)) throw TypeError(".bilibili.community.service.dm.v1.DmWebViewReply.specialDms: array expected");
  2683. b.specialDms = [];
  2684. for (var c = 0; c < a.specialDms.length; ++c) b.specialDms[c] = String(a.specialDms[c])
  2685. }
  2686. return b
  2687. };
  2688. d.toObject = function (a, b) {
  2689. b || (b = {});
  2690. var c = {};
  2691. if (b.arrays || b.defaults) c.specialDms = [];
  2692. b.defaults && (c.state = 0, c.text = "", c.textSide = "", c.dmSge = null, c.flag = null);
  2693. null != a.state && a.hasOwnProperty("state") && (c.state = a.state);
  2694. null != a.text && a.hasOwnProperty("text") && (c.text = a.text);
  2695. null != a.textSide && a.hasOwnProperty("textSide") && (c.textSide = a.textSide);
  2696. null != a.dmSge && a.hasOwnProperty("dmSge") && (c.dmSge = p.bilibili.community.service.dm.v1.DmSegConfig.toObject(a.dmSge, b));
  2697. null != a.flag && a.hasOwnProperty("flag") && (c.flag = p.bilibili.community.service.dm.v1.DanmakuFlagConfig.toObject(a.flag, b));
  2698. if (a.specialDms && a.specialDms.length) {
  2699. c.specialDms = [];
  2700. for (var k = 0; k < a.specialDms.length; ++k) c.specialDms[k] = a.specialDms[k]
  2701. }
  2702. return c
  2703. };
  2704. d.prototype.toJSON = function () {
  2705. return this.constructor.toObject(this, z.util.toJSONOptions)
  2706. };
  2707. return d
  2708. }();
  2709. e.DmSegConfig = function () {
  2710. function d(a) {
  2711. if (a) for (var b = Object.keys(a), c = 0; c < b.length; ++c) null != a[b[c]] && (this[b[c]] = a[b[c]])
  2712. }
  2713.  
  2714. d.prototype.pageSize = r.Long ? r.Long.fromBits(0, 0, !1) : 0;
  2715. d.prototype.total = r.Long ? r.Long.fromBits(0, 0, !1) : 0;
  2716. d.create = function (a) {
  2717. return new d(a)
  2718. };
  2719. d.encode = function (a, b) {
  2720. b || (b = A.create());
  2721. null != a.pageSize && Object.hasOwnProperty.call(a, "pageSize") && b.uint32(8).int64(a.pageSize);
  2722. null != a.total && Object.hasOwnProperty.call(a, "total") && b.uint32(16).int64(a.total);
  2723. return b
  2724. };
  2725. d.encodeDelimited = function (a, b) {
  2726. return this.encode(a, b).ldelim()
  2727. };
  2728. d.decode = function (a, b) {
  2729. a instanceof y || (a = y.create(a));
  2730. for (var c = void 0 === b ? a.len : a.pos + b, k = new p.bilibili.community.service.dm.v1.DmSegConfig; a.pos < c;) {
  2731. var l = a.uint32();
  2732. switch (l >>> 3) {
  2733. case 1:
  2734. k.pageSize = a.int64();
  2735. break;
  2736. case 2:
  2737. k.total = a.int64();
  2738. break;
  2739. default:
  2740. a.skipType(l & 7)
  2741. }
  2742. }
  2743. return k
  2744. };
  2745. d.decodeDelimited = function (a) {
  2746. a instanceof y || (a = new y(a));
  2747. return this.decode(a, a.uint32())
  2748. };
  2749. d.verify = function (a) {
  2750. return "object" !== typeof a || null === a ? "object expected" : null == a.pageSize || !a.hasOwnProperty("pageSize") || r.isInteger(a.pageSize) || a.pageSize && r.isInteger(a.pageSize.low) && r.isInteger(a.pageSize.high) ? null == a.total || !a.hasOwnProperty("total") || r.isInteger(a.total) || a.total && r.isInteger(a.total.low) && r.isInteger(a.total.high) ? null : "total: integer|Long expected" : "pageSize: integer|Long expected"
  2751. };
  2752. d.fromObject = function (a) {
  2753. if (a instanceof p.bilibili.community.service.dm.v1.DmSegConfig) return a;
  2754. var b = new p.bilibili.community.service.dm.v1.DmSegConfig;
  2755. null != a.pageSize && (r.Long ? (b.pageSize = r.Long.fromValue(a.pageSize)).unsigned = !1 : "string" === typeof a.pageSize ? b.pageSize = parseInt(a.pageSize, 10) : "number" === typeof a.pageSize ? b.pageSize = a.pageSize : "object" === typeof a.pageSize && (b.pageSize = (new r.LongBits(a.pageSize.low >>> 0, a.pageSize.high >>> 0)).toNumber()));
  2756. null != a.total && (r.Long ? (b.total = r.Long.fromValue(a.total)).unsigned = !1 : "string" === typeof a.total ? b.total = parseInt(a.total, 10) : "number" === typeof a.total ? b.total = a.total : "object" === typeof a.total && (b.total = (new r.LongBits(a.total.low >>> 0, a.total.high >>> 0)).toNumber()));
  2757. return b
  2758. };
  2759. d.toObject = function (a, b) {
  2760. b || (b = {});
  2761. var c = {};
  2762. if (b.defaults) {
  2763. if (r.Long) {
  2764. var k = new r.Long(0, 0, !1);
  2765. c.pageSize = b.longs === String ? k.toString() : b.longs === Number ? k.toNumber() : k
  2766. } else c.pageSize = b.longs === String ? "0" : 0;
  2767. r.Long ? (k = new r.Long(0, 0, !1), c.total = b.longs === String ? k.toString() : b.longs === Number ? k.toNumber() : k) : c.total = b.longs === String ? "0" : 0
  2768. }
  2769. null != a.pageSize && a.hasOwnProperty("pageSize") && (c.pageSize = "number" === typeof a.pageSize ? b.longs === String ? String(a.pageSize) : a.pageSize : b.longs === String ? r.Long.prototype.toString.call(a.pageSize) : b.longs === Number ? (new r.LongBits(a.pageSize.low >>> 0, a.pageSize.high >>> 0)).toNumber() : a.pageSize);
  2770. null != a.total && a.hasOwnProperty("total") && (c.total = "number" === typeof a.total ? b.longs === String ? String(a.total) : a.total : b.longs === String ? r.Long.prototype.toString.call(a.total) : b.longs === Number ? (new r.LongBits(a.total.low >>> 0, a.total.high >>> 0)).toNumber() : a.total);
  2771. return c
  2772. };
  2773. d.prototype.toJSON = function () {
  2774. return this.constructor.toObject(this, z.util.toJSONOptions)
  2775. };
  2776. return d
  2777. }();
  2778. e.DanmakuFlagConfig = function () {
  2779. function d(a) {
  2780. if (a) for (var b = Object.keys(a), c = 0; c < b.length; ++c) null != a[b[c]] && (this[b[c]] = a[b[c]])
  2781. }
  2782.  
  2783. d.prototype.recFlag = 0;
  2784. d.prototype.recText = "";
  2785. d.prototype.recSwitch = 0;
  2786. d.create = function (a) {
  2787. return new d(a)
  2788. };
  2789. d.encode = function (a, b) {
  2790. b || (b = A.create());
  2791. null != a.recFlag && Object.hasOwnProperty.call(a, "recFlag") && b.uint32(8).int32(a.recFlag);
  2792. null != a.recText && Object.hasOwnProperty.call(a, "recText") && b.uint32(18).string(a.recText);
  2793. null != a.recSwitch && Object.hasOwnProperty.call(a, "recSwitch") && b.uint32(24).int32(a.recSwitch);
  2794. return b
  2795. };
  2796. d.encodeDelimited = function (a, b) {
  2797. return this.encode(a, b).ldelim()
  2798. };
  2799. d.decode = function (a, b) {
  2800. a instanceof y || (a = y.create(a));
  2801. for (var c = void 0 === b ? a.len : a.pos + b, k = new p.bilibili.community.service.dm.v1.DanmakuFlagConfig; a.pos < c;) {
  2802. var l = a.uint32();
  2803. switch (l >>> 3) {
  2804. case 1:
  2805. k.recFlag = a.int32();
  2806. break;
  2807. case 2:
  2808. k.recText = a.string();
  2809. break;
  2810. case 3:
  2811. k.recSwitch = a.int32();
  2812. break;
  2813. default:
  2814. a.skipType(l & 7)
  2815. }
  2816. }
  2817. return k
  2818. };
  2819. d.decodeDelimited = function (a) {
  2820. a instanceof y || (a = new y(a));
  2821. return this.decode(a, a.uint32())
  2822. };
  2823. d.verify = function (a) {
  2824. return "object" !== typeof a || null === a ? "object expected" : null != a.recFlag && a.hasOwnProperty("recFlag") && !r.isInteger(a.recFlag) ? "recFlag: integer expected" : null != a.recText && a.hasOwnProperty("recText") && !r.isString(a.recText) ? "recText: string expected" : null != a.recSwitch && a.hasOwnProperty("recSwitch") && !r.isInteger(a.recSwitch) ? "recSwitch: integer expected" : null
  2825. };
  2826. d.fromObject = function (a) {
  2827. if (a instanceof p.bilibili.community.service.dm.v1.DanmakuFlagConfig) return a;
  2828. var b = new p.bilibili.community.service.dm.v1.DanmakuFlagConfig;
  2829. null != a.recFlag && (b.recFlag = a.recFlag | 0);
  2830. null != a.recText && (b.recText = String(a.recText));
  2831. null != a.recSwitch && (b.recSwitch = a.recSwitch | 0);
  2832. return b
  2833. };
  2834. d.toObject = function (a, b) {
  2835. b || (b = {});
  2836. var c = {};
  2837. b.defaults && (c.recFlag = 0, c.recText = "", c.recSwitch = 0);
  2838. null != a.recFlag && a.hasOwnProperty("recFlag") && (c.recFlag = a.recFlag);
  2839. null != a.recText && a.hasOwnProperty("recText") && (c.recText = a.recText);
  2840. null != a.recSwitch && a.hasOwnProperty("recSwitch") && (c.recSwitch = a.recSwitch);
  2841. return c
  2842. };
  2843. d.prototype.toJSON = function () {
  2844. return this.constructor.toObject(this, z.util.toJSONOptions)
  2845. };
  2846. return d
  2847. }();
  2848. e.DmSegMobileReply = function () {
  2849. function d(a) {
  2850. this.elems = [];
  2851. if (a) for (var b = Object.keys(a), c = 0; c < b.length; ++c) null != a[b[c]] && (this[b[c]] = a[b[c]])
  2852. }
  2853.  
  2854. d.prototype.elems = r.emptyArray;
  2855. d.create = function (a) {
  2856. return new d(a)
  2857. };
  2858. d.encode = function (a, b) {
  2859. b || (b = A.create());
  2860. if (null != a.elems && a.elems.length) for (var c = 0; c < a.elems.length; ++c) p.bilibili.community.service.dm.v1.DanmakuElem.encode(a.elems[c], b.uint32(10).fork()).ldelim();
  2861. return b
  2862. };
  2863. d.encodeDelimited = function (a, b) {
  2864. return this.encode(a, b).ldelim()
  2865. };
  2866. d.decode = function (a, b) {
  2867. a instanceof y || (a = y.create(a));
  2868. for (var c = void 0 === b ? a.len : a.pos + b, k = new p.bilibili.community.service.dm.v1.DmSegMobileReply; a.pos < c;) {
  2869. var l = a.uint32();
  2870. switch (l >>> 3) {
  2871. case 1:
  2872. k.elems && k.elems.length || (k.elems = []);
  2873. k.elems.push(p.bilibili.community.service.dm.v1.DanmakuElem.decode(a, a.uint32()));
  2874. break;
  2875. default:
  2876. a.skipType(l & 7)
  2877. }
  2878. }
  2879. return k
  2880. };
  2881. d.decodeDelimited = function (a) {
  2882. a instanceof y || (a = new y(a));
  2883. return this.decode(a, a.uint32())
  2884. };
  2885. d.verify = function (a) {
  2886. if ("object" !== typeof a || null === a) return "object expected";
  2887. if (null != a.elems && a.hasOwnProperty("elems")) {
  2888. if (!Array.isArray(a.elems)) return "elems: array expected";
  2889. for (var b = 0; b < a.elems.length; ++b) {
  2890. var c = p.bilibili.community.service.dm.v1.DanmakuElem.verify(a.elems[b]);
  2891. if (c) return "elems." + c
  2892. }
  2893. }
  2894. return null
  2895. };
  2896. d.fromObject = function (a) {
  2897. if (a instanceof p.bilibili.community.service.dm.v1.DmSegMobileReply) return a;
  2898. var b = new p.bilibili.community.service.dm.v1.DmSegMobileReply;
  2899. if (a.elems) {
  2900. if (!Array.isArray(a.elems)) throw TypeError(".bilibili.community.service.dm.v1.DmSegMobileReply.elems: array expected");
  2901. b.elems = [];
  2902. for (var c = 0; c < a.elems.length; ++c) {
  2903. if ("object" !== typeof a.elems[c]) throw TypeError(".bilibili.community.service.dm.v1.DmSegMobileReply.elems: object expected");
  2904. b.elems[c] = p.bilibili.community.service.dm.v1.DanmakuElem.fromObject(a.elems[c])
  2905. }
  2906. }
  2907. return b
  2908. };
  2909. d.toObject = function (a, b) {
  2910. b || (b = {});
  2911. var c = {};
  2912. if (b.arrays || b.defaults) c.elems = [];
  2913. if (a.elems && a.elems.length) {
  2914. c.elems = [];
  2915. for (var k = 0; k < a.elems.length; ++k) c.elems[k] = p.bilibili.community.service.dm.v1.DanmakuElem.toObject(a.elems[k], b)
  2916. }
  2917. return c
  2918. };
  2919. d.prototype.toJSON = function () {
  2920. return this.constructor.toObject(this, z.util.toJSONOptions)
  2921. };
  2922. return d
  2923. }();
  2924. e.DanmakuElem = function () {
  2925. function d(a) {
  2926. if (a) for (var b = Object.keys(a), c = 0; c < b.length; ++c) null != a[b[c]] && (this[b[c]] = a[b[c]])
  2927. }
  2928.  
  2929. d.prototype.id = r.Long ? r.Long.fromBits(0, 0, !1) : 0;
  2930. d.prototype.progress = 0;
  2931. d.prototype.mode = 0;
  2932. d.prototype.fontsize = 0;
  2933. d.prototype.color = 0;
  2934. d.prototype.midHash = "";
  2935. d.prototype.content = "";
  2936. d.prototype.ctime = r.Long ? r.Long.fromBits(0, 0, !1) : 0;
  2937. d.prototype.weight = 0;
  2938. d.prototype.action = "";
  2939. d.prototype.pool = 0;
  2940. d.prototype.idStr = "";
  2941. d.create = function (a) {
  2942. return new d(a)
  2943. };
  2944. d.encode = function (a, b) {
  2945. b || (b = A.create());
  2946. null != a.id && Object.hasOwnProperty.call(a, "id") && b.uint32(8).int64(a.id);
  2947. null != a.progress && Object.hasOwnProperty.call(a, "progress") && b.uint32(16).int32(a.progress);
  2948. null != a.mode && Object.hasOwnProperty.call(a, "mode") && b.uint32(24).int32(a.mode);
  2949. null != a.fontsize && Object.hasOwnProperty.call(a, "fontsize") && b.uint32(32).int32(a.fontsize);
  2950. null != a.color && Object.hasOwnProperty.call(a, "color") && b.uint32(40).uint32(a.color);
  2951. null != a.midHash && Object.hasOwnProperty.call(a, "midHash") && b.uint32(50).string(a.midHash);
  2952. null != a.content && Object.hasOwnProperty.call(a, "content") && b.uint32(58).string(a.content);
  2953. null != a.ctime && Object.hasOwnProperty.call(a, "ctime") && b.uint32(64).int64(a.ctime);
  2954. null != a.weight && Object.hasOwnProperty.call(a, "weight") && b.uint32(72).int32(a.weight);
  2955. null != a.action && Object.hasOwnProperty.call(a, "action") && b.uint32(82).string(a.action);
  2956. null != a.pool && Object.hasOwnProperty.call(a, "pool") && b.uint32(88).int32(a.pool);
  2957. null != a.idStr && Object.hasOwnProperty.call(a, "idStr") && b.uint32(98).string(a.idStr);
  2958. return b
  2959. };
  2960. d.encodeDelimited = function (a, b) {
  2961. return this.encode(a, b).ldelim()
  2962. };
  2963. d.decode = function (a, b) {
  2964. a instanceof y || (a = y.create(a));
  2965. for (var c = void 0 === b ? a.len : a.pos + b, k = new p.bilibili.community.service.dm.v1.DanmakuElem; a.pos < c;) {
  2966. var l = a.uint32();
  2967. switch (l >>> 3) {
  2968. case 1:
  2969. k.id = a.int64();
  2970. break;
  2971. case 2:
  2972. k.progress = a.int32();
  2973. break;
  2974. case 3:
  2975. k.mode = a.int32();
  2976. break;
  2977. case 4:
  2978. k.fontsize = a.int32();
  2979. break;
  2980. case 5:
  2981. k.color = a.uint32();
  2982. break;
  2983. case 6:
  2984. k.midHash = a.string();
  2985. break;
  2986. case 7:
  2987. k.content = a.string();
  2988. break;
  2989. case 8:
  2990. k.ctime = a.int64();
  2991. break;
  2992. case 9:
  2993. k.weight = a.int32();
  2994. break;
  2995. case 10:
  2996. k.action = a.string();
  2997. break;
  2998. case 11:
  2999. k.pool = a.int32();
  3000. break;
  3001. case 12:
  3002. k.idStr = a.string();
  3003. break;
  3004. default:
  3005. a.skipType(l & 7)
  3006. }
  3007. }
  3008. return k
  3009. };
  3010. d.decodeDelimited = function (a) {
  3011. a instanceof y || (a = new y(a));
  3012. return this.decode(a, a.uint32())
  3013. };
  3014. d.verify = function (a) {
  3015. return "object" !== typeof a || null === a ? "object expected" : null == a.id || !a.hasOwnProperty("id") || r.isInteger(a.id) || a.id && r.isInteger(a.id.low) && r.isInteger(a.id.high) ? null != a.progress && a.hasOwnProperty("progress") && !r.isInteger(a.progress) ? "progress: integer expected" : null != a.mode && a.hasOwnProperty("mode") && !r.isInteger(a.mode) ? "mode: integer expected" : null != a.fontsize && a.hasOwnProperty("fontsize") && !r.isInteger(a.fontsize) ? "fontsize: integer expected" : null != a.color && a.hasOwnProperty("color") && !r.isInteger(a.color) ? "color: integer expected" : null != a.midHash && a.hasOwnProperty("midHash") && !r.isString(a.midHash) ? "midHash: string expected" : null != a.content && a.hasOwnProperty("content") && !r.isString(a.content) ? "content: string expected" : null == a.ctime || !a.hasOwnProperty("ctime") || r.isInteger(a.ctime) || a.ctime && r.isInteger(a.ctime.low) && r.isInteger(a.ctime.high) ? null != a.weight && a.hasOwnProperty("weight") && !r.isInteger(a.weight) ? "weight: integer expected" : null != a.action && a.hasOwnProperty("action") && !r.isString(a.action) ? "action: string expected" : null != a.pool && a.hasOwnProperty("pool") && !r.isInteger(a.pool) ? "pool: integer expected" : null != a.idStr && a.hasOwnProperty("idStr") && !r.isString(a.idStr) ? "idStr: string expected" : null : "ctime: integer|Long expected" : "id: integer|Long expected"
  3016. };
  3017. d.fromObject = function (a) {
  3018. if (a instanceof p.bilibili.community.service.dm.v1.DanmakuElem) return a;
  3019. var b = new p.bilibili.community.service.dm.v1.DanmakuElem;
  3020. null != a.id && (r.Long ? (b.id = r.Long.fromValue(a.id)).unsigned = !1 : "string" === typeof a.id ? b.id = parseInt(a.id, 10) : "number" === typeof a.id ? b.id = a.id : "object" === typeof a.id && (b.id = (new r.LongBits(a.id.low >>> 0, a.id.high >>> 0)).toNumber()));
  3021. null != a.progress && (b.progress = a.progress | 0);
  3022. null != a.mode && (b.mode = a.mode | 0);
  3023. null != a.fontsize && (b.fontsize = a.fontsize | 0);
  3024. null != a.color && (b.color = a.color >>> 0);
  3025. null != a.midHash && (b.midHash = String(a.midHash));
  3026. null != a.content && (b.content = String(a.content));
  3027. null != a.ctime && (r.Long ? (b.ctime = r.Long.fromValue(a.ctime)).unsigned = !1 : "string" === typeof a.ctime ? b.ctime = parseInt(a.ctime, 10) : "number" === typeof a.ctime ? b.ctime = a.ctime : "object" === typeof a.ctime && (b.ctime = (new r.LongBits(a.ctime.low >>> 0, a.ctime.high >>> 0)).toNumber()));
  3028. null != a.weight && (b.weight = a.weight | 0);
  3029. null != a.action && (b.action = String(a.action));
  3030. null != a.pool && (b.pool = a.pool | 0);
  3031. null != a.idStr && (b.idStr = String(a.idStr));
  3032. return b
  3033. };
  3034. d.toObject = function (a, b) {
  3035. b || (b = {});
  3036. var c = {};
  3037. if (b.defaults) {
  3038. if (r.Long) {
  3039. var k = new r.Long(0, 0, !1);
  3040. c.id = b.longs === String ? k.toString() : b.longs === Number ? k.toNumber() : k
  3041. } else c.id = b.longs === String ? "0" : 0;
  3042. c.progress = 0;
  3043. c.mode = 0;
  3044. c.fontsize = 0;
  3045. c.color = 0;
  3046. c.midHash = "";
  3047. c.content = "";
  3048. r.Long ? (k = new r.Long(0, 0, !1), c.ctime = b.longs === String ? k.toString() : b.longs === Number ? k.toNumber() : k) : c.ctime = b.longs === String ? "0" : 0;
  3049. c.weight = 0;
  3050. c.action = "";
  3051. c.pool = 0;
  3052. c.idStr = ""
  3053. }
  3054. null != a.id && a.hasOwnProperty("id") && (c.id = "number" === typeof a.id ? b.longs === String ? String(a.id) : a.id : b.longs === String ? r.Long.prototype.toString.call(a.id) : b.longs === Number ? (new r.LongBits(a.id.low >>> 0, a.id.high >>> 0)).toNumber() : a.id);
  3055. null != a.progress && a.hasOwnProperty("progress") && (c.progress = a.progress);
  3056. null != a.mode && a.hasOwnProperty("mode") && (c.mode = a.mode);
  3057. null != a.fontsize && a.hasOwnProperty("fontsize") && (c.fontsize = a.fontsize);
  3058. null != a.color && a.hasOwnProperty("color") && (c.color = a.color);
  3059. null != a.midHash && a.hasOwnProperty("midHash") && (c.midHash = a.midHash);
  3060. null != a.content && a.hasOwnProperty("content") && (c.content = a.content);
  3061. null != a.ctime && a.hasOwnProperty("ctime") && (c.ctime = "number" === typeof a.ctime ? b.longs === String ? String(a.ctime) : a.ctime : b.longs === String ? r.Long.prototype.toString.call(a.ctime) : b.longs === Number ? (new r.LongBits(a.ctime.low >>> 0, a.ctime.high >>> 0)).toNumber() : a.ctime);
  3062. null != a.weight && a.hasOwnProperty("weight") && (c.weight = a.weight);
  3063. null != a.action && a.hasOwnProperty("action") && (c.action = a.action);
  3064. null != a.pool && a.hasOwnProperty("pool") && (c.pool = a.pool);
  3065. null != a.idStr && a.hasOwnProperty("idStr") && (c.idStr = a.idStr);
  3066. return c
  3067. };
  3068. d.prototype.toJSON = function () {
  3069. return this.constructor.toObject(this, z.util.toJSONOptions)
  3070. };
  3071. return d
  3072. }();
  3073. return e
  3074. }();
  3075. return n
  3076. }();
  3077. return m
  3078. }();
  3079. return h
  3080. }();
  3081. return w
  3082. }();
  3083. return p
  3084. })(protobuf);
  3085. var proto_seg = protobuf.roots["default"].bilibili.community.service.dm.v1.DmSegMobileReply;
  3086.  
  3087. function htmlEscape(text, skipQuot) {
  3088. if (!text) return text
  3089. text = text.replace(/[\x00-\x08\x0b-\x0c\x0e-\x1f\ufffe\uffff]/g, ' ')
  3090.  
  3091. function fn(match, pos, originalText) {
  3092. switch (match) {
  3093. case "<":
  3094. return "&lt;";
  3095. case ">":
  3096. return "&gt;";
  3097. case "&":
  3098. return "&amp;";
  3099. case "\"":
  3100. return '"';
  3101. }
  3102. }
  3103.  
  3104. if (!skipQuot) {
  3105. return text.replace(/[<>"&]/g, fn);
  3106. } else {
  3107. return text.replace(/[<>&]/g, fn);
  3108.  
  3109. }
  3110. }
  3111.  
  3112. function xmlunEscape(content) {
  3113. return content.replace(';', ';')
  3114. .replace(/&amp;/g, '&')
  3115. .replace(/&lt;/g, '<')
  3116. .replace(/&gt;/g, '>')
  3117. .replace(/&apos;/g, "'")
  3118. .replace(/&quot;/g, '"')
  3119. }
  3120.  
  3121. function xml2danmu(sdanmu, user = null) {
  3122. let ldanmu = sdanmu.split('</d><d p=');
  3123.  
  3124. if (ldanmu.length === 1) {
  3125. return []
  3126. }
  3127. let tdanmu = ldanmu[0];
  3128. ldanmu[0] = tdanmu.slice(tdanmu.indexOf('<d p=') + 5, tdanmu.length);
  3129. tdanmu = ldanmu[ldanmu.length - 1];
  3130. ldanmu[ldanmu.length - 1] = tdanmu.slice(0, tdanmu.length - 8);
  3131. for (let i = 0; i < ldanmu.length; i++) {
  3132. let danmu = ldanmu[i]
  3133. let argv = danmu.substring(1, danmu.indexOf('"', 2)).split(',')
  3134. ldanmu[i] = {
  3135. color: Number(argv[3]),
  3136. content: xmlunEscape(danmu.slice(danmu.indexOf('>') + 1, danmu.length)),
  3137. ctime: Number(argv[4]),
  3138. fontsize: Number(argv[2]),
  3139. id: Number(argv[7]),
  3140. idStr: argv[7],
  3141. midHash: argv[6],
  3142. mode: Number(argv[1]),
  3143. progress: Math.round(Number(argv[0]) * 1000),
  3144. weight: 10
  3145. }
  3146. }
  3147. return ldanmu
  3148. }
  3149.  
  3150. async function loadProtoDanmu(url, timeout = null, header = null, retry = 0) {
  3151. if (header === null) {
  3152. header = {
  3153. "referer": 'https://www.bilibili.com/bangumi/play/ep790784',
  3154. origin: 'https://www.bilibili.com',
  3155. 'sec-fetch-site': 'same-site'
  3156. }
  3157. }
  3158. while (true) {
  3159. try {
  3160. let result = await new Promise((resolve) => {
  3161. GM_xmlhttpRequest({
  3162. method: 'GET',
  3163. url: url,
  3164. responseType: 'arraybuffer',
  3165. headers: header,
  3166. timeout: timeout || 30000,
  3167. withCredentials: true,
  3168. onload: (response) => {
  3169. if (response.status === 200) {
  3170. let lpdanmu;
  3171. try {
  3172. lpdanmu = proto_seg.decode(new Uint8Array(response.response));
  3173. } catch (e) {
  3174. if (response.responseText.indexOf('-101') !== -1) {
  3175. alert("历史弹幕下载失败. 请检查该浏览器中B站是否未登录账号\n" + response.responseText)
  3176. window.location.href = "https://space.bilibili.com/0"
  3177. }
  3178. console.log('XhrError=', retry);
  3179. if (retry < 3) {
  3180. return resolve(loadProtoDanmu(url, timeout, header, retry + 1));
  3181. } else {
  3182. return resolve(null);
  3183. }
  3184. }
  3185. try {
  3186. lpdanmu.elems.forEach((e) => {
  3187. if (!e.progress) e.progress = 0;
  3188. });
  3189. resolve(lpdanmu.elems);
  3190. } catch (e) {
  3191. console.log(e.stack);
  3192. resolve([]);
  3193. }
  3194. } else if (response.status === 304) {
  3195. resolve([]);
  3196. } else {
  3197. console.log(response.status, response);
  3198. resolve(null);
  3199. }
  3200. },
  3201. onerror: (error) => {
  3202. console.log('XhrError=', retry);
  3203. retry += 1;
  3204. if (retry > 3) {
  3205. setTimeout(() => resolve(null), 10 * 1000);
  3206. } else {
  3207. setTimeout(() => resolve(null), retry * 2 * 1000);
  3208. }
  3209. },
  3210. });
  3211. });
  3212. if (pageSetting.suspendDownload) {
  3213. return result
  3214. }
  3215.  
  3216. if (result === null) {
  3217. retry += 1;
  3218. } else {
  3219. return result;
  3220. }
  3221. } catch (e) {
  3222. console.log('XhrError=', retry);
  3223. retry += 1;
  3224. }
  3225. await sleep(1000)
  3226. if (retry > 3) {
  3227. setTimeout(() => resolve(null), 10 * 1000);
  3228. } else {
  3229. setTimeout(() => resolve(null), retry * 2 * 1000);
  3230. }
  3231. }
  3232. }
  3233.  
  3234. function savedanmuStandalone(ldanmu, info = null) {
  3235. var end, head;
  3236. head = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><i><chatserver>chat.bilibili.com</chatserver><chatid>0</chatid><mission>0</mission><maxlimit>0</maxlimit><state>0</state><real_name>0</real_name><source>DF</source>"
  3237. end = "</i>";
  3238. if ((info !== null)) {
  3239. head += '<info>' + htmlEscape(JSON.stringify(info), true) + '</info>';
  3240. }
  3241. return head + ldanmu.join('') + end
  3242. }
  3243.  
  3244.  
  3245. function danmuObject2XML(ldanmu) {
  3246. for (let i = 0, length = ldanmu.length; i < length; i++) {
  3247. let danmu = ldanmu[i]
  3248. ldanmu[i] = `<d p="${(danmu.progress ? danmu.progress : 0) / 1000},${danmu.mode},${danmu.fontsize},${danmu.color},${danmu.ctime},${0},${danmu.midHash},${danmu.id}">${htmlEscape(danmu.content)}</d>`
  3249. }
  3250. return ldanmu
  3251. }
  3252.  
  3253.  
  3254. async function moreHistory(cid) {
  3255. let date = new Date();
  3256. if (videoPublishDate && currentSetting.capturePeriodEnd !== -1) {
  3257. date.setTime((videoPublishDate + currentSetting.capturePeriodEnd * 86400) * 1000)
  3258. } else {
  3259. date.setTime(date.getTime() - 86400000)
  3260. }
  3261. console.log('GetDanmuFor CID' + cid)
  3262. let aldanmu = [], ldanmu = []
  3263. let firstdate = 0;
  3264. let ndanmu, ondanmu
  3265. let url = 'https://comment.bilibili.com/' + cid + '.xml'
  3266. let sdanmu = await xhrGet(url)
  3267. ondanmu = ndanmu = Number(/<maxlimit>(.*?)</.exec(sdanmu)[1])
  3268. while (true) {
  3269. if (firstdate !== 0) {
  3270. await sleep(2000)
  3271. }
  3272. if (firstdate === 0 || ldanmu.length >= Math.min(ondanmu, 5000) * 0.5) {
  3273. let url = "https://api.bilibili.com/x/v2/dm/web/history/seg.so?type=1&date=" + dateObjectToDateStr(date) + "&oid=" + cid.toString();
  3274. console.log('ndanmu:', aldanmu.length, dateObjectToDateStr(date), url);
  3275. ldanmu = await loadProtoDanmu(url)
  3276.  
  3277. }
  3278. if (ldanmu !== null) {
  3279. aldanmu = mergeDanmu(aldanmu, ldanmu)
  3280. }
  3281. if (pageSetting.suspendDownload) {
  3282. return [aldanmu, ondanmu]
  3283. }
  3284. document.title = aldanmu.length.toString()
  3285. toastText(dateObjectToDateStr(date) + '/' + aldanmu.length)
  3286. if (ldanmu.length < Math.min(ondanmu, 5000) * 0.5) {
  3287. return [aldanmu, ondanmu]
  3288. }
  3289. if (ldanmu.length >= Math.min(ondanmu, 5000) * 0.5) {
  3290. let tfirstdate = getMinDate(ldanmu)
  3291. if (firstdate !== 0 && firstdate - tfirstdate < 86400) tfirstdate = firstdate - 86400;
  3292. firstdate = tfirstdate;
  3293. date.setTime(firstdate * 1000);
  3294. }
  3295. if (videoPublishDate && currentSetting.capturePeriodStart !== 0) {
  3296. if (videoPublishDate + currentSetting.capturePeriodStart > date.getTime() / 1000) {
  3297. return [aldanmu, ondanmu]
  3298. }
  3299. }
  3300. }
  3301. }
  3302.  
  3303.  
  3304. function timestampToFullDateStr(timestamp) {
  3305. const date = new Date(timestamp * 1000); // Convert seconds to milliseconds
  3306. const year = date.getFullYear();
  3307. const month = (date.getMonth() + 1).toString().padStart(2, '0'); // Month is zero-indexed
  3308. const day = date.getDate().toString().padStart(2, '0');
  3309. const hour = date.getHours().toString().padStart(2, '0');
  3310. const minute = date.getMinutes().toString().padStart(2, '0');
  3311. const second = date.getSeconds().toString().padStart(2, '0');
  3312.  
  3313. return `${year}-${month}-${day}-${hour}-${minute}-${second}`;
  3314. }
  3315.  
  3316.  
  3317. function dateObjectToDateStr(date) {
  3318. const year = date.getFullYear();
  3319. const month = (date.getMonth() + 1).toString().padStart(2, '0'); // Month is zero-indexed
  3320. const day = date.getDate().toString().padStart(2, '0');
  3321.  
  3322. return `${year}-${month}-${day}`;
  3323. }
  3324.  
  3325.  
  3326. function getMinDate(ldanmu) {
  3327. let minDate = ldanmu[0].ctime
  3328. for (let danmu of ldanmu) {
  3329. if (minDate > danmu.ctime) {
  3330. minDate = danmu.ctime
  3331. }
  3332. }
  3333. return minDate
  3334. }
  3335.  
  3336. function mergeDanmu(oldanmu, nldanmu) {
  3337. if (oldanmu.idPool === undefined) {
  3338.  
  3339. let idPool = new Set()
  3340. for (let danmu of oldanmu) {
  3341. try {
  3342. idPool.add(danmu.progress * danmu.content.length * parseInt(danmu.midHash, 16))
  3343.  
  3344. } catch (e) {
  3345. console.log(danmu)
  3346. console.log(e)
  3347. throw e
  3348. }
  3349. }
  3350. oldanmu.idPool = idPool
  3351. }
  3352. try {
  3353. for (let danmu of nldanmu) {
  3354. let ida = (danmu.progress ? danmu.progress : 1) * danmu.content.length * parseInt(danmu.midHash, 16)
  3355. if (!oldanmu.idPool.has(ida)) {
  3356. oldanmu.push(danmu)
  3357. oldanmu.idPool.add(ida)
  3358. }
  3359. }
  3360. } catch (e) {
  3361. console.log()
  3362. }
  3363.  
  3364. return oldanmu
  3365. }
  3366.  
  3367. function poolSize2Duration(poolSize) {
  3368. let lPoolSize = [[0, 100], [30, 300], [60, 500], [180, 1000], [600, 1500], [900, 3000], [1500, 4000], [2400, 6000], [3600, 8000],]
  3369.  
  3370. for (let i = 0; i < lPoolSize.length; i += 1) {
  3371. if (poolSize === lPoolSize[i][1]) {
  3372. return lPoolSize[i][0]
  3373. }
  3374. }
  3375. }
  3376.  
  3377. async function allProtobufDanmu(cid, duration) {
  3378. toastText("实时弹幕:", cid)
  3379. let segIndex = 0, aldanmu = []
  3380. while (true) {
  3381. segIndex += 1
  3382. let tldanmu = await loadProtoDanmu('https://api.bilibili.com/x/v2/dm/web/seg.so?type=1&oid=' + cid + '&segment_index=' + segIndex)
  3383. mergeDanmu(aldanmu, tldanmu)
  3384. toastText(aldanmu.length)
  3385. if ((!duration || segIndex * 360 > duration) && (!tldanmu || tldanmu.length === 0)) {
  3386. break
  3387. }
  3388. await sleep(500)
  3389. }
  3390. toastText('下载完成')
  3391. return aldanmu
  3392. }
  3393.  
  3394. async function allProtobufDanmuXml(cid, title, ndanmu) {
  3395. let ldanmu = savedanmuStandalone(danmuObject2XML(await allProtobufDanmu(cid, poolSize2Duration(ndanmu))))
  3396. downloadFile(validateTitle(title) + '.xml', ldanmu)
  3397. }
  3398.  
  3399. async function downloadDanmaku(cid, info) {
  3400. toastText("全弹幕:" + cid)
  3401. if (currentSetting.capturePeriodStart !== 0 || currentSetting.capturePeriodEnd !== -1) {
  3402. toastText("下载时段:第" + currentSetting.capturePeriodStart + '-' + currentSetting.capturePeriodEnd + '天')
  3403. toastText(videoPublishDate ? "视频发布日期:" + dateObjectToDateStr(new Date(videoPublishDate * 1000)) : "未知日期:由弹幕判断")
  3404. }
  3405. let [ldanmu, ndanmu] = await moreHistory(cid)
  3406. if (!info) {
  3407. info = {}
  3408. }
  3409. info.cid = cid
  3410. info.ndanmu = ndanmu
  3411. if (!pageSetting.suspendDownload) {
  3412. // if (ldanmu.length > ndanmu * 2 || ((currentSetting.capturePeriodStart !== 0 || currentSetting.capturePeriodEnd !== -1) && ldanmu.length > ndanmu * 0.8)) {
  3413. let sldanmu = await allProtobufDanmu(cid, poolSize2Duration(ndanmu))
  3414. mergeDanmu(ldanmu, sldanmu)
  3415. // }
  3416. if (currentSetting.capturePeriodStart !== 0 || currentSetting.capturePeriodEnd !== -1) {
  3417. let publishDate = videoPublishDate || getMinDate(ldanmu)
  3418. let start = publishDate + currentSetting.capturePeriodStart * 86400 - 1
  3419. let end = currentSetting.capturePeriodEnd > 0 ? publishDate + currentSetting.capturePeriodEnd * 86400 : 1e12
  3420. console.log('before', ldanmu.length)
  3421. ldanmu = ldanmu.filter(danmu => {
  3422. return danmu.ctime > start && danmu.ctime < end
  3423. })
  3424. console.log('after', ldanmu.length)
  3425. }
  3426.  
  3427.  
  3428. toastText('下载完成')
  3429. return new DownloadResult(ldanmu, info)
  3430. } else {
  3431. toastText('下载中断, 下载临时弹幕')
  3432. info.isSuspend = true
  3433. return new DownloadResult(ldanmu, info)
  3434. }
  3435. }
  3436.  
  3437. class DownloadResult {
  3438. constructor(ldanmu, info) {
  3439. this.ldanmu = ldanmu
  3440. this.info = info
  3441. }
  3442.  
  3443. toXml() {
  3444. return savedanmuStandalone(danmuObject2XML(this.ldanmu), this.info)
  3445. }
  3446.  
  3447. dumpFile(title) {
  3448. downloadFile(validateTitle(title) + '.xml', this.toXml())
  3449. }
  3450.  
  3451. splitByTime(folder) {
  3452. this.ldanmu.sort((a, b) => {
  3453. return a.ctime - b.ctime
  3454. })
  3455.  
  3456. let i = 0
  3457. const chunkSize = 3000
  3458. while (i * chunkSize < this.ldanmu.length) {
  3459. let tldanmu = this.ldanmu.slice(i * chunkSize, (i + 1) * chunkSize)
  3460. let lastTs = tldanmu[tldanmu.length - 1].ctime
  3461. let fileName = timestampToFullDateStr(lastTs) + '_' + this.info.cid + '.xml'
  3462. folder.file(fileName, new DownloadResult(tldanmu, this.info).toXml())
  3463. i += 1
  3464. }
  3465. }
  3466. }
  3467.  
  3468. async function downloadDanmakuToZip(cid, folder, partTitle, partInfo, spiltFileFlag) {
  3469. let result = await downloadDanmaku(cid, '', partInfo)
  3470. if (!spiltFileFlag) {
  3471. let sdanmu = result.toXml()
  3472. await sleep(1);
  3473. folder.file(partTitle + '.xml', sdanmu)
  3474. await sleep(1);
  3475. } else {
  3476. let partFolder = folder.folder(partTitle)
  3477. result.splitByTime(partFolder)
  3478. }
  3479. }
  3480.  
  3481. async function concatDanmaku(videoInfo) {
  3482. let aldanmu = []
  3483.  
  3484. let posOffset = 0
  3485. for (let partInfo of videoInfo.list) {
  3486. let ldanmu = await allProtobufDanmu(partInfo.cid, partInfo.duration - partInfo.backBlack ?? 0)
  3487. if (partInfo.backBlack) {
  3488. ldanmu = ldanmu.filter((danmu) => {
  3489. return danmu.progress < (partInfo.duration - partInfo.backBlack ?? 0) * 1000
  3490. })
  3491. }
  3492. if (partInfo.frontBlack) {
  3493. ldanmu.forEach((danmu) => {
  3494. danmu.progress -= (partInfo.frontBlack ?? 0) * 1000
  3495. })
  3496. ldanmu = ldanmu.filter((danmu) => {
  3497. return danmu.progress > 0
  3498. })
  3499. }
  3500. ldanmu.forEach((danmu) => {
  3501. danmu.progress = danmu.progress + posOffset * 1000
  3502. })
  3503. posOffset += partInfo.duration - (partInfo.backBlack ?? 0) - (partInfo.frontBlack ?? 0)
  3504. aldanmu = aldanmu.concat(ldanmu)
  3505. }
  3506. let xml = savedanmuStandalone(danmuObject2XML(aldanmu), videoInfo)
  3507. downloadFile(`av${videoInfo.id} ${validateTitle(videoInfo.title)} P${videoInfo.list[0].page} ${validateTitle(videoInfo.list[0].part ?? videoInfo.list[0].title ?? '')}.xml`, xml)
  3508. }
  3509.  
  3510. return [downloadDanmaku,
  3511.  
  3512. downloadDanmakuToZip,
  3513.  
  3514. allProtobufDanmuXml,
  3515. concatDanmaku]
  3516. })();
  3517.  
  3518. let downloadDanmakuVideo = (() => {
  3519. return async function (videoInfo) {
  3520. let zip = new JSZip();
  3521. let title
  3522. let aid
  3523. if (typeof videoInfo['aid'] === 'number') {
  3524. aid = videoInfo['aid']
  3525. title = 'av' + videoInfo['aid'] + ' ' + validateTitle(videoInfo['title'])
  3526. } else {
  3527. title = videoInfo['aid'] + ' ' + validateTitle(videoInfo['title'])
  3528. aid = Number(videoInfo['aid'].substring(2))
  3529. }
  3530. title = validateTitle(title)
  3531. console.log('title= ' + title)
  3532. let folder = zip.folder(title)
  3533. folder.file('videoInfo.json', JSON.stringify(videoInfo))
  3534. let i = 0
  3535.  
  3536. if (!videoInfo.isCache && (typeof videoInfo['aid'] === 'number' || videoInfo['aid'].startsWith('av'))) {
  3537. try {
  3538. let pageList = JSON.parse(await xhrGet(`https://api.bilibili.com/x/player/pagelist?aid=${aid}&jsonp=jsonp`))
  3539. if (pageList.code === 0) {
  3540. for (let page of pageList['data']) {
  3541. let matched = false
  3542. for (let part of videoInfo['list']) {
  3543. if (part.cid === page.cid) {
  3544. part.duration = page.duration
  3545. matched = true
  3546. break
  3547. }
  3548. }
  3549. if (!matched) {
  3550. videoInfo['list'].push(page)
  3551. }
  3552. }
  3553. }
  3554. } catch (e) {
  3555. console.error(e, e.stack)
  3556. }
  3557. }
  3558.  
  3559.  
  3560. if (videoInfo.videoPublishDate) {
  3561. videoPublishDate = videoInfo.videoPublishDate
  3562. }
  3563.  
  3564. for (let partInfo of videoInfo['list']) {
  3565. i += 1
  3566. partInfo.title = partInfo.part
  3567. partInfo.aid = aid
  3568. let partTitle = getPartTitle(partInfo)
  3569. if (partInfo.videoPublishDate) {
  3570. videoPublishDate = partInfo.videoPublishDate
  3571. }
  3572. toastText(partTitle)
  3573. let progress = (i * 100 / videoInfo['list'].length).toFixed(2)
  3574. document.title = progress + ' %'
  3575. await downloadDanmakuToZip(partInfo.cid, folder, partTitle, partInfo, currentSetting['splitFileByTime'])
  3576. broadcastChannel.postMessage({
  3577. type: 'cidComplete', cid: partInfo.cid, aid: videoInfo.aid, progress: progress,
  3578. }, '*');
  3579. if (partInfo.videoPublishDate) {
  3580. videoPublishDate = null
  3581. }
  3582. }
  3583. let result = await zip.generateAsync({
  3584. type: "blob", compression: "DEFLATE", compressionOptions: {
  3585. level: 9
  3586. }
  3587. })
  3588. videoPublishDate = null
  3589. downloadFile(title + '.zip', result);
  3590. }
  3591. })()
  3592.  
  3593. let downloadedCid = []
  3594. let downloadedAid = []
  3595. let downloadingVideo = []
  3596. broadcastChannel.addEventListener('message', async (e) => {
  3597. if (e.data.type === 'biliplusDownloadDanmaku') {
  3598. if (e.data.history !== false) {
  3599. if (downloadedCid.indexOf(e.data.cid) !== -1) {
  3600. return
  3601. }
  3602. downloadedCid.push(e.data.cid);
  3603. (await downloadDanmaku(e.data.cid, e.data)).dumpFile(e.data.title)
  3604. } else {
  3605. await allProtobufDanmu(e.data.cid, e.data.title, e.data.ndanmu)
  3606. }
  3607. }
  3608. if (e.data.type === 'biliplusDownloadDanmakuVideo') {
  3609. if (downloadedAid.indexOf(e.data.videoInfo.aid) !== -1) {
  3610. broadcastChannel.postMessage({type: 'aidDownloaded', aid: e.data.videoInfo.aid}, '*');
  3611. return
  3612. }
  3613. downloadedAid.push(e.data.videoInfo.aid)
  3614. if (downloadingVideo.length === 0) {
  3615. downloadingVideo.push(e.data.videoInfo)
  3616. while (downloadingVideo.length !== 0) {
  3617. let videoInfo = downloadingVideo[0]
  3618. console.log('start', videoInfo.aid)
  3619. broadcastChannel.postMessage({type: 'aidStart', aid: videoInfo.aid}, '*');
  3620. await new Promise((resolve) => setTimeout(resolve, 1));
  3621. await downloadDanmakuVideo(videoInfo)
  3622. document.title = '下载完成'
  3623. broadcastChannel.postMessage({type: 'aidComplete', aid: videoInfo.aid}, '*');
  3624. await sleep(1000)
  3625. downloadingVideo = downloadingVideo.slice(1)
  3626. }
  3627. } else {
  3628. console.log('wait', e.data.videoInfo.aid)
  3629. downloadingVideo.push(e.data.videoInfo)
  3630. }
  3631.  
  3632. }
  3633. if (e.data.type === 'concatDanmaku') {
  3634. await concatDanmaku(e.data.videoInfo)
  3635. }
  3636. });
  3637. }
  3638.  
  3639. let currentSetting = panel()
  3640. let pageSetting = {
  3641. frontBlack: undefined,
  3642. backBlack: undefined,
  3643. suspendDownload: false
  3644. }
  3645. client()
  3646. server()