Biliplus Evolved

简单的B+增强脚本

当前为 2025-01-06 提交的版本,查看 最新版本

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