Biliplus Evolved

简单的B+增强脚本

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