youtube-comment-censor-detector

A real-time comment checker, Fuck YouTube’s opaque comment censorship

  1. // ==UserScript==
  2. // @name youtube-comment-censor-detector
  3. // @name:zh-CN YouTube发评反诈
  4. // @name:zh-TW YouTube發評反詐
  5. // @namespace npm/vite-plugin-monkey
  6. // @version 2.0.0
  7. // @author freedom-introvert
  8. // @description A real-time comment checker, Fuck YouTube’s opaque comment censorship
  9. // @description:zh-CN Fuck YouTube版“阿瓦隆系统”,实时检查评论状态,防止评论被儿童偷偷误食你还被蒙在鼓里
  10. // @description:zh-TW Fuck YouTube版“阿瓦隆系統”,即時檢查評論狀態,防止評論被兒童偷偷誤食你還被蒙在鼓裡
  11. // @license GPL
  12. // @icon https://raw.githubusercontent.com/freedom-introvert/youtube-comment-censor-detector/refs/heads/main/logo/logo_256x256.avif
  13. // @match *://*.youtube.com/*
  14. // @require https://cdn.jsdelivr.net/npm/vue@3.5.15/dist/vue.global.prod.js
  15. // @require https://unpkg.com/vue-demi@latest/lib/index.iife.js
  16. // @require data:application/javascript,window.Vue%3DVue%3B
  17. // @require https://cdn.jsdelivr.net/npm/element-plus@2.9.11/dist/index.full.min.js
  18. // @resource element-plus/dist/index.css https://cdn.jsdelivr.net/npm/element-plus@2.9.11/dist/index.css
  19. // @grant GM_addStyle
  20. // @grant GM_getResourceText
  21. // @grant GM_registerMenuCommand
  22. // @grant unsafeWindow
  23. // @run-at document-start
  24. // ==/UserScript==
  25.  
  26. (e=>{if(typeof GM_addStyle=="function"){GM_addStyle(e);return}const a=document.createElement("style");a.textContent=e,document.head.append(a)})(" .el-message,.is-message-box{z-index:9999!important}.comment-checker[data-v-684910ce]{font-size:12px}.container[data-v-684910ce]{width:80%;margin:0 auto}.comment-checker[data-v-684910ce]{padding:15px 15px 11px;border-radius:8px;transition:background-color .3s}.title[data-v-684910ce]{font-weight:700;margin-bottom:6px}.message[data-v-684910ce]{margin-bottom:10px}.el-progress[data-v-684910ce]{margin-bottom:4px}.buttons[data-v-684910ce]>[data-v-684910ce]{display:inline-flex;align-items:center;padding:4px 8px;margin-left:-8px;color:#4b5e9d;border-radius:4px;transition:background-color .2s,color .2s;-webkit-user-select:none;user-select:none;margin-right:10px}.buttons[data-v-684910ce]>[data-v-684910ce]:hover{background-color:#0000000d}.buttons[data-v-684910ce]>[data-v-684910ce]:active{background-color:#0000001a}.comment-checker.not-check[data-v-684910ce]{background-color:#00f3}.comment-checker.normal[data-v-684910ce]{background-color:#0f03}.comment-checker.deleted[data-v-684910ce]{background-color:#f003}.comment-checker.shadow-ban[data-v-684910ce]{background-color:#ff03}.hot-ban-checker[data-v-e5341f8d]{background-color:#007bff1a;border:1px solid rgba(0,60,136,.4);border-radius:6px;padding:1rem;margin:10px 0}.title[data-v-e5341f8d]{font-weight:700;margin-bottom:6px}.message[data-v-e5341f8d]{margin-bottom:10px}.actions[data-v-e5341f8d]{margin-top:10px}.buttons[data-v-e5341f8d]>[data-v-e5341f8d]{display:inline-flex;align-items:center;padding:4px 8px;margin-left:-8px;color:#4b5e9d;border-radius:4px;transition:background-color .2s,color .2s;-webkit-user-select:none;user-select:none;margin-right:10px}.buttons[data-v-e5341f8d]>[data-v-e5341f8d]:hover{background-color:#0000000d}.buttons[data-v-e5341f8d]>[data-v-e5341f8d]:active{background-color:#0000001a}[data-v-ff4696c9] .dialog-body{height:calc(100% - 40px);display:flex;flex-direction:column}.pagination[data-v-ff4696c9]{margin-top:6px}.detail[data-v-ff4696c9]{margin-left:10px}.info-table td[data-v-ff4696c9]:nth-child(1){white-space:nowrap;vertical-align:top}.info-table td[data-v-ff4696c9]:nth-child(2){padding-left:16px}.comment-content[data-v-ff4696c9]{white-space:break-spaces}summary[data-v-ff4696c9]{cursor:pointer;margin-top:2px;-webkit-user-select:none;user-select:none}.locate-link[data-v-ff4696c9]{width:100%}[data-v-ff4696c9] .locate-link>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.post-locate-link[data-v-ff4696c9]{font-size:10px} ");
  27.  
  28. (function (vue, ElementPlus) {
  29. 'use strict';
  30.  
  31. function sleep(time) {
  32. return new Promise((resolve, reject) => {
  33. setTimeout(() => {
  34. resolve();
  35. }, time);
  36. });
  37. }
  38. function urlSafeBase64ToStandard(urlSafeBase64) {
  39. let standardBase64 = urlSafeBase64.replace(/%3D/g, "=").replace(/-/g, "+").replace(/_/g, "/");
  40. return standardBase64;
  41. }
  42. function standardBase64ToUrlSafe(standardBase64) {
  43. let urlSafeBase64 = standardBase64.replace(/=/g, "%3D").replace(/\+/g, "-").replace(/\//g, "_");
  44. return urlSafeBase64;
  45. }
  46. function createUrl(path) {
  47. return new URL(new URL(window.location.href).origin + path);
  48. }
  49. function formatSecondsToMMSS(seconds) {
  50. const sec = parseInt(seconds, 10);
  51. const minutes = Math.floor(sec / 60);
  52. const remainingSeconds = sec % 60;
  53. const formattedMinutes = String(minutes).padStart(2, "0");
  54. const formattedSeconds = String(remainingSeconds).padStart(2, "0");
  55. return `${formattedMinutes}:${formattedSeconds}`;
  56. }
  57. function formatTimestamp(timestamp) {
  58. if (!timestamp) {
  59. return "--:--:--";
  60. }
  61. const date = new Date(timestamp);
  62. const year = date.getFullYear();
  63. const month = String(date.getMonth() + 1).padStart(2, "0");
  64. const day = String(date.getDate()).padStart(2, "0");
  65. const hours = String(date.getHours()).padStart(2, "0");
  66. const minutes = String(date.getMinutes()).padStart(2, "0");
  67. const seconds = String(date.getSeconds()).padStart(2, "0");
  68. return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  69. }
  70. function translateState(state) {
  71. switch (state) {
  72. case "NORMAL":
  73. return "正常";
  74. case "DELETED":
  75. return "已删除";
  76. case "SHADOW_BAN":
  77. return "仅自己可见";
  78. case "NOT_CHECK":
  79. return "还未检查";
  80. }
  81. }
  82. const _export_sfc = (sfc, props) => {
  83. const target = sfc.__vccOpts || sfc;
  84. for (const [key, val] of props) {
  85. target[key] = val;
  86. }
  87. return target;
  88. };
  89. const _hoisted_1$2 = { class: "title" };
  90. const _hoisted_2$2 = { class: "message" };
  91. const _hoisted_3$2 = { key: 0 };
  92. const _hoisted_4$2 = { class: "message" };
  93. const _hoisted_5$1 = { class: "buttons" };
  94. const maxTimeSec = 120;
  95. const _sfc_main$2 = {
  96. __name: "CommentChecker",
  97. setup(__props) {
  98. const check2 = vue.inject("check");
  99. const hotBanCheck2 = vue.inject("hotBanCheck");
  100. const commentRecord = vue.inject("commentRecord");
  101. const onClose = vue.inject("onClose");
  102. const onUnblock = vue.inject("onUnblock");
  103. const interval = vue.inject("interval");
  104. const showCancelButton = vue.ref(true);
  105. const showConfirmButton = vue.ref(false);
  106. const showCloseButton = vue.ref(false);
  107. const showHotBanCheckButton = vue.ref(false);
  108. const showStopHotBanCheckButton = vue.ref(false);
  109. const showLetMeAccessButtton = vue.ref(false);
  110. const showHotBanChecker = vue.ref(false);
  111. const stateClass = vue.ref("not-check");
  112. const title = vue.ref("等待检查中……");
  113. const message = vue.ref("");
  114. const messageByHotCheck = vue.ref("等待检查中……");
  115. let completed = false;
  116. let netErr = false;
  117. let hotBanCheckerController = {
  118. isCancelled: false
  119. };
  120. let skipHotBanCheckWait = false;
  121. const stripedFlow = vue.ref(false);
  122. const currentTimeSec = vue.ref(0);
  123. const percentage = vue.computed(() => {
  124. if (currentTimeSec.value < 0 || currentTimeSec.value > maxTimeSec) {
  125. return 100;
  126. } else {
  127. return currentTimeSec.value / maxTimeSec * 100;
  128. }
  129. });
  130. function format() {
  131. if (currentTimeSec.value < 0) {
  132. return `--:-- / ${formatSecondsToMMSS(maxTimeSec)}`;
  133. } else {
  134. return `${formatSecondsToMMSS(currentTimeSec.value)} / ${formatSecondsToMMSS(maxTimeSec)}`;
  135. }
  136. }
  137. let shown = null;
  138. let startTime = Date.now() / 1e3;
  139. async function startCheck() {
  140. while (currentTimeSec.value < maxTimeSec || netErr) {
  141. if (!netErr) {
  142. for (let i = interval; i > 0; i--) {
  143. message.value = "等待 " + i + "s 后检查评论状态";
  144. await sleep(1e3);
  145. currentTimeSec.value = Date.now() / 1e3 - startTime;
  146. if (completed) {
  147. onStateCheckComplete();
  148. return;
  149. }
  150. }
  151. } else {
  152. currentTimeSec.value = Date.now() / 1e3 - startTime;
  153. if (completed) {
  154. onStateCheckComplete();
  155. return;
  156. }
  157. }
  158. message.value = "检查评论状态中……";
  159. stripedFlow.value = true;
  160. try {
  161. await check2(commentRecord);
  162. } catch (err) {
  163. netErr = true;
  164. title.value = "网络错误,获取当前状态失败";
  165. showConfirmButton.value = false;
  166. showCloseButton.value = true;
  167. stripedFlow.value = false;
  168. console.error(err);
  169. continue;
  170. }
  171. netErr = false;
  172. showCancelButton.value = false;
  173. showCloseButton.value = false;
  174. stripedFlow.value = false;
  175. if (commentRecord.currentState == "NORMAL") {
  176. title.value = "当前状态:正常";
  177. stateClass.value = "normal";
  178. shown = commentRecord.currentState;
  179. } else if (commentRecord.currentState == "SHADOW_BAN") {
  180. title.value = "当前状态:仅自己可见";
  181. stateClass.value = "shadow-ban";
  182. shown = commentRecord.currentState;
  183. } else if (commentRecord.currentState == "DELETED") {
  184. title.value = "当前状态:已被删除";
  185. stateClass.value = "deleted";
  186. if (shown) {
  187. completed = true;
  188. message.value = `不用等了,你的评论检查到的状态先从『${shown == "NORMAL" ? "正常" : "仅自己可见"}』再到删除,系统偷偷删了无疑。如果不信,你可以尝试编辑评论或添加回复来求证`;
  189. onStateCheckComplete();
  190. return;
  191. }
  192. }
  193. showConfirmButton.value = true;
  194. }
  195. onStateCheckComplete();
  196. completed = true;
  197. message.value = "观察时间已足够,当前状态可信,检查完毕";
  198. buttonText.value = "关闭";
  199. }
  200. function onStateCheckComplete() {
  201. showConfirmButton.value = false;
  202. showCloseButton.value = true;
  203. if (commentRecord.currentState == "NORMAL") {
  204. showHotBanCheckButton.value = true;
  205. } else if (commentRecord.currentState == "DELETED") {
  206. onUnblock(commentRecord);
  207. }
  208. }
  209. startCheck();
  210. function cancelCheck() {
  211. completed = true;
  212. onClose(commentRecord);
  213. }
  214. function confirmCurrentState() {
  215. completed = true;
  216. message.value = "您已确认当前状态,检查完毕";
  217. }
  218. function close() {
  219. onClose(commentRecord);
  220. }
  221. async function checkHotBan() {
  222. if (commentRecord.commentId.indexOf(".") == -1) {
  223. try {
  224. await ElementPlus.ElMessageBox.confirm(
  225. "确认检查吗?该检查需要遍历热门评论区,请注意评论区的评论数量(总数大于3000的评论区慎重考虑)!数量太多将导致漫长的检查过程,同时频繁调用API可能会引发不可预料的后果!",
  226. "警告",
  227. {
  228. confirmButtonText: "确定",
  229. cancelButtonText: "取消"
  230. }
  231. );
  232. } catch (err) {
  233. return;
  234. }
  235. }
  236. showCloseButton.value = false;
  237. showHotBanCheckButton.value = false;
  238. showHotBanChecker.value = true;
  239. showStopHotBanCheckButton.value = true;
  240. while (currentTimeSec.value < maxTimeSec && !hotBanCheckerController.isCancelled) {
  241. messageByHotCheck.value = `为避免检查误判,检查需要等待至状态可信任时开始,剩余 ${Math.floor(maxTimeSec - currentTimeSec.value)}s`;
  242. if (!skipHotBanCheckWait && currentTimeSec.value > 50) {
  243. showLetMeAccessButtton.value = true;
  244. }
  245. if (skipHotBanCheckWait) {
  246. break;
  247. }
  248. await sleep(1e3);
  249. if (hotBanCheckerController.isCancelled) {
  250. return;
  251. }
  252. currentTimeSec.value = Date.now() / 1e3 - startTime;
  253. }
  254. showLetMeAccessButtton.value = false;
  255. messageByHotCheck.value = "正在重新检查评论状态……";
  256. await check2(commentRecord);
  257. if (commentRecord.currentState != "NORMAL") {
  258. if (commentRecord.currentState == "SHADOW_BAN") {
  259. title.value = "当前状态:仅自己可见";
  260. stateClass.value = "shadow-ban";
  261. messageByHotCheck.value = "评论已被ShadowBan,热门的屏蔽的检查已取消";
  262. } else if (commentRecord.currentState == "DELETED") {
  263. title.value = "当前状态:已被删除";
  264. stateClass.value = "deleted";
  265. messageByHotCheck.value = "评论已被删除,热门的屏蔽的检查已取消";
  266. }
  267. showStopHotBanCheckButton.value = false;
  268. showCloseButton.value = true;
  269. return;
  270. }
  271. messageByHotCheck.value = "评论状态正常,准备检查中……";
  272. let observer = {
  273. onCountChange(c, p) {
  274. messageByHotCheck.value = `正在搜索热门列表,已搜寻至:第${c}个 ${p}页`;
  275. }
  276. };
  277. if (await hotBanCheck2(commentRecord, observer, hotBanCheckerController)) {
  278. if (commentRecord.hotBan) {
  279. messageByHotCheck.value = "⚠ 你的评论未在热门列表找到,已被热门屏蔽,检查完成";
  280. } else {
  281. messageByHotCheck.value = "✔ 你的评论已在热门列表找到,没有被热门屏蔽,检查完成";
  282. }
  283. }
  284. showStopHotBanCheckButton.value = false;
  285. showCloseButton.value = true;
  286. }
  287. function stopHotBanCheck() {
  288. hotBanCheckerController.isCancelled = true;
  289. messageByHotCheck.value = "你已终止热门屏蔽的检查";
  290. showStopHotBanCheckButton.value = false;
  291. showCloseButton.value = true;
  292. }
  293. function letMeAccess() {
  294. skipHotBanCheckWait = true;
  295. showLetMeAccessButtton.value = false;
  296. }
  297. return (_ctx, _cache) => {
  298. const _component_el_progress = vue.resolveComponent("el-progress");
  299. return vue.openBlock(), vue.createElementBlock("div", {
  300. class: vue.normalizeClass(["comment-checker", stateClass.value])
  301. }, [
  302. vue.createElementVNode("div", _hoisted_1$2, vue.toDisplayString(title.value), 1),
  303. vue.createElementVNode("div", _hoisted_2$2, vue.toDisplayString(message.value), 1),
  304. vue.createVNode(_component_el_progress, {
  305. percentage: percentage.value,
  306. striped: "",
  307. format,
  308. "striped-flow": stripedFlow.value
  309. }, null, 8, ["percentage", "striped-flow"]),
  310. showHotBanChecker.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$2, [
  311. _cache[0] || (_cache[0] = vue.createElementVNode("div", { class: "title" }, "热门屏蔽检查", -1)),
  312. vue.createElementVNode("div", _hoisted_4$2, vue.toDisplayString(messageByHotCheck.value), 1)
  313. ])) : vue.createCommentVNode("", true),
  314. vue.createElementVNode("div", _hoisted_5$1, [
  315. showCancelButton.value ? (vue.openBlock(), vue.createElementBlock("span", {
  316. key: 0,
  317. onClick: cancelCheck
  318. }, "取消")) : vue.createCommentVNode("", true),
  319. showConfirmButton.value ? (vue.openBlock(), vue.createElementBlock("span", {
  320. key: 1,
  321. onClick: confirmCurrentState
  322. }, "确认当前状态")) : vue.createCommentVNode("", true),
  323. showCloseButton.value ? (vue.openBlock(), vue.createElementBlock("span", {
  324. key: 2,
  325. onClick: close
  326. }, "关闭")) : vue.createCommentVNode("", true),
  327. showHotBanCheckButton.value ? (vue.openBlock(), vue.createElementBlock("span", {
  328. key: 3,
  329. onClick: checkHotBan
  330. }, "热门屏蔽检查")) : vue.createCommentVNode("", true),
  331. showStopHotBanCheckButton.value ? (vue.openBlock(), vue.createElementBlock("span", {
  332. key: 4,
  333. onClick: stopHotBanCheck
  334. }, "终止检查")) : vue.createCommentVNode("", true),
  335. showLetMeAccessButtton.value ? (vue.openBlock(), vue.createElementBlock("span", {
  336. key: 5,
  337. onClick: letMeAccess
  338. }, "让我检查!")) : vue.createCommentVNode("", true)
  339. ])
  340. ], 2);
  341. };
  342. }
  343. };
  344. const CommentChecker = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-684910ce"]]);
  345. var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
  346. var indexMinimal = {};
  347. var minimal$1 = {};
  348. var aspromise;
  349. var hasRequiredAspromise;
  350. function requireAspromise() {
  351. if (hasRequiredAspromise) return aspromise;
  352. hasRequiredAspromise = 1;
  353. aspromise = asPromise;
  354. function asPromise(fn, ctx) {
  355. var params = new Array(arguments.length - 1), offset = 0, index = 2, pending = true;
  356. while (index < arguments.length)
  357. params[offset++] = arguments[index++];
  358. return new Promise(function executor(resolve, reject) {
  359. params[offset] = function callback(err) {
  360. if (pending) {
  361. pending = false;
  362. if (err)
  363. reject(err);
  364. else {
  365. var params2 = new Array(arguments.length - 1), offset2 = 0;
  366. while (offset2 < params2.length)
  367. params2[offset2++] = arguments[offset2];
  368. resolve.apply(null, params2);
  369. }
  370. }
  371. };
  372. try {
  373. fn.apply(ctx || null, params);
  374. } catch (err) {
  375. if (pending) {
  376. pending = false;
  377. reject(err);
  378. }
  379. }
  380. });
  381. }
  382. return aspromise;
  383. }
  384. var base64 = {};
  385. var hasRequiredBase64;
  386. function requireBase64() {
  387. if (hasRequiredBase64) return base64;
  388. hasRequiredBase64 = 1;
  389. (function(exports) {
  390. var base642 = exports;
  391. base642.length = function length(string) {
  392. var p = string.length;
  393. if (!p)
  394. return 0;
  395. var n = 0;
  396. while (--p % 4 > 1 && string.charAt(p) === "=")
  397. ++n;
  398. return Math.ceil(string.length * 3) / 4 - n;
  399. };
  400. var b64 = new Array(64);
  401. var s64 = new Array(123);
  402. for (var i = 0; i < 64; )
  403. s64[b64[i] = i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i - 59 | 43] = i++;
  404. base642.encode = function encode(buffer, start, end) {
  405. var parts = null, chunk = [];
  406. var i2 = 0, j = 0, t;
  407. while (start < end) {
  408. var b = buffer[start++];
  409. switch (j) {
  410. case 0:
  411. chunk[i2++] = b64[b >> 2];
  412. t = (b & 3) << 4;
  413. j = 1;
  414. break;
  415. case 1:
  416. chunk[i2++] = b64[t | b >> 4];
  417. t = (b & 15) << 2;
  418. j = 2;
  419. break;
  420. case 2:
  421. chunk[i2++] = b64[t | b >> 6];
  422. chunk[i2++] = b64[b & 63];
  423. j = 0;
  424. break;
  425. }
  426. if (i2 > 8191) {
  427. (parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));
  428. i2 = 0;
  429. }
  430. }
  431. if (j) {
  432. chunk[i2++] = b64[t];
  433. chunk[i2++] = 61;
  434. if (j === 1)
  435. chunk[i2++] = 61;
  436. }
  437. if (parts) {
  438. if (i2)
  439. parts.push(String.fromCharCode.apply(String, chunk.slice(0, i2)));
  440. return parts.join("");
  441. }
  442. return String.fromCharCode.apply(String, chunk.slice(0, i2));
  443. };
  444. var invalidEncoding = "invalid encoding";
  445. base642.decode = function decode(string, buffer, offset) {
  446. var start = offset;
  447. var j = 0, t;
  448. for (var i2 = 0; i2 < string.length; ) {
  449. var c = string.charCodeAt(i2++);
  450. if (c === 61 && j > 1)
  451. break;
  452. if ((c = s64[c]) === void 0)
  453. throw Error(invalidEncoding);
  454. switch (j) {
  455. case 0:
  456. t = c;
  457. j = 1;
  458. break;
  459. case 1:
  460. buffer[offset++] = t << 2 | (c & 48) >> 4;
  461. t = c;
  462. j = 2;
  463. break;
  464. case 2:
  465. buffer[offset++] = (t & 15) << 4 | (c & 60) >> 2;
  466. t = c;
  467. j = 3;
  468. break;
  469. case 3:
  470. buffer[offset++] = (t & 3) << 6 | c;
  471. j = 0;
  472. break;
  473. }
  474. }
  475. if (j === 1)
  476. throw Error(invalidEncoding);
  477. return offset - start;
  478. };
  479. base642.test = function test(string) {
  480. return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(string);
  481. };
  482. })(base64);
  483. return base64;
  484. }
  485. var eventemitter;
  486. var hasRequiredEventemitter;
  487. function requireEventemitter() {
  488. if (hasRequiredEventemitter) return eventemitter;
  489. hasRequiredEventemitter = 1;
  490. eventemitter = EventEmitter;
  491. function EventEmitter() {
  492. this._listeners = {};
  493. }
  494. EventEmitter.prototype.on = function on(evt, fn, ctx) {
  495. (this._listeners[evt] || (this._listeners[evt] = [])).push({
  496. fn,
  497. ctx: ctx || this
  498. });
  499. return this;
  500. };
  501. EventEmitter.prototype.off = function off(evt, fn) {
  502. if (evt === void 0)
  503. this._listeners = {};
  504. else {
  505. if (fn === void 0)
  506. this._listeners[evt] = [];
  507. else {
  508. var listeners = this._listeners[evt];
  509. for (var i = 0; i < listeners.length; )
  510. if (listeners[i].fn === fn)
  511. listeners.splice(i, 1);
  512. else
  513. ++i;
  514. }
  515. }
  516. return this;
  517. };
  518. EventEmitter.prototype.emit = function emit(evt) {
  519. var listeners = this._listeners[evt];
  520. if (listeners) {
  521. var args = [], i = 1;
  522. for (; i < arguments.length; )
  523. args.push(arguments[i++]);
  524. for (i = 0; i < listeners.length; )
  525. listeners[i].fn.apply(listeners[i++].ctx, args);
  526. }
  527. return this;
  528. };
  529. return eventemitter;
  530. }
  531. var float;
  532. var hasRequiredFloat;
  533. function requireFloat() {
  534. if (hasRequiredFloat) return float;
  535. hasRequiredFloat = 1;
  536. float = factory(factory);
  537. function factory(exports) {
  538. if (typeof Float32Array !== "undefined") (function() {
  539. var f32 = new Float32Array([-0]), f8b = new Uint8Array(f32.buffer), le = f8b[3] === 128;
  540. function writeFloat_f32_cpy(val, buf, pos) {
  541. f32[0] = val;
  542. buf[pos] = f8b[0];
  543. buf[pos + 1] = f8b[1];
  544. buf[pos + 2] = f8b[2];
  545. buf[pos + 3] = f8b[3];
  546. }
  547. function writeFloat_f32_rev(val, buf, pos) {
  548. f32[0] = val;
  549. buf[pos] = f8b[3];
  550. buf[pos + 1] = f8b[2];
  551. buf[pos + 2] = f8b[1];
  552. buf[pos + 3] = f8b[0];
  553. }
  554. exports.writeFloatLE = le ? writeFloat_f32_cpy : writeFloat_f32_rev;
  555. exports.writeFloatBE = le ? writeFloat_f32_rev : writeFloat_f32_cpy;
  556. function readFloat_f32_cpy(buf, pos) {
  557. f8b[0] = buf[pos];
  558. f8b[1] = buf[pos + 1];
  559. f8b[2] = buf[pos + 2];
  560. f8b[3] = buf[pos + 3];
  561. return f32[0];
  562. }
  563. function readFloat_f32_rev(buf, pos) {
  564. f8b[3] = buf[pos];
  565. f8b[2] = buf[pos + 1];
  566. f8b[1] = buf[pos + 2];
  567. f8b[0] = buf[pos + 3];
  568. return f32[0];
  569. }
  570. exports.readFloatLE = le ? readFloat_f32_cpy : readFloat_f32_rev;
  571. exports.readFloatBE = le ? readFloat_f32_rev : readFloat_f32_cpy;
  572. })();
  573. else (function() {
  574. function writeFloat_ieee754(writeUint, val, buf, pos) {
  575. var sign = val < 0 ? 1 : 0;
  576. if (sign)
  577. val = -val;
  578. if (val === 0)
  579. writeUint(1 / val > 0 ? (
  580. /* positive */
  581. 0
  582. ) : (
  583. /* negative 0 */
  584. 2147483648
  585. ), buf, pos);
  586. else if (isNaN(val))
  587. writeUint(2143289344, buf, pos);
  588. else if (val > 34028234663852886e22)
  589. writeUint((sign << 31 | 2139095040) >>> 0, buf, pos);
  590. else if (val < 11754943508222875e-54)
  591. writeUint((sign << 31 | Math.round(val / 1401298464324817e-60)) >>> 0, buf, pos);
  592. else {
  593. var exponent = Math.floor(Math.log(val) / Math.LN2), mantissa = Math.round(val * Math.pow(2, -exponent) * 8388608) & 8388607;
  594. writeUint((sign << 31 | exponent + 127 << 23 | mantissa) >>> 0, buf, pos);
  595. }
  596. }
  597. exports.writeFloatLE = writeFloat_ieee754.bind(null, writeUintLE);
  598. exports.writeFloatBE = writeFloat_ieee754.bind(null, writeUintBE);
  599. function readFloat_ieee754(readUint, buf, pos) {
  600. var uint = readUint(buf, pos), sign = (uint >> 31) * 2 + 1, exponent = uint >>> 23 & 255, mantissa = uint & 8388607;
  601. return exponent === 255 ? mantissa ? NaN : sign * Infinity : exponent === 0 ? sign * 1401298464324817e-60 * mantissa : sign * Math.pow(2, exponent - 150) * (mantissa + 8388608);
  602. }
  603. exports.readFloatLE = readFloat_ieee754.bind(null, readUintLE);
  604. exports.readFloatBE = readFloat_ieee754.bind(null, readUintBE);
  605. })();
  606. if (typeof Float64Array !== "undefined") (function() {
  607. var f64 = new Float64Array([-0]), f8b = new Uint8Array(f64.buffer), le = f8b[7] === 128;
  608. function writeDouble_f64_cpy(val, buf, pos) {
  609. f64[0] = val;
  610. buf[pos] = f8b[0];
  611. buf[pos + 1] = f8b[1];
  612. buf[pos + 2] = f8b[2];
  613. buf[pos + 3] = f8b[3];
  614. buf[pos + 4] = f8b[4];
  615. buf[pos + 5] = f8b[5];
  616. buf[pos + 6] = f8b[6];
  617. buf[pos + 7] = f8b[7];
  618. }
  619. function writeDouble_f64_rev(val, buf, pos) {
  620. f64[0] = val;
  621. buf[pos] = f8b[7];
  622. buf[pos + 1] = f8b[6];
  623. buf[pos + 2] = f8b[5];
  624. buf[pos + 3] = f8b[4];
  625. buf[pos + 4] = f8b[3];
  626. buf[pos + 5] = f8b[2];
  627. buf[pos + 6] = f8b[1];
  628. buf[pos + 7] = f8b[0];
  629. }
  630. exports.writeDoubleLE = le ? writeDouble_f64_cpy : writeDouble_f64_rev;
  631. exports.writeDoubleBE = le ? writeDouble_f64_rev : writeDouble_f64_cpy;
  632. function readDouble_f64_cpy(buf, pos) {
  633. f8b[0] = buf[pos];
  634. f8b[1] = buf[pos + 1];
  635. f8b[2] = buf[pos + 2];
  636. f8b[3] = buf[pos + 3];
  637. f8b[4] = buf[pos + 4];
  638. f8b[5] = buf[pos + 5];
  639. f8b[6] = buf[pos + 6];
  640. f8b[7] = buf[pos + 7];
  641. return f64[0];
  642. }
  643. function readDouble_f64_rev(buf, pos) {
  644. f8b[7] = buf[pos];
  645. f8b[6] = buf[pos + 1];
  646. f8b[5] = buf[pos + 2];
  647. f8b[4] = buf[pos + 3];
  648. f8b[3] = buf[pos + 4];
  649. f8b[2] = buf[pos + 5];
  650. f8b[1] = buf[pos + 6];
  651. f8b[0] = buf[pos + 7];
  652. return f64[0];
  653. }
  654. exports.readDoubleLE = le ? readDouble_f64_cpy : readDouble_f64_rev;
  655. exports.readDoubleBE = le ? readDouble_f64_rev : readDouble_f64_cpy;
  656. })();
  657. else (function() {
  658. function writeDouble_ieee754(writeUint, off0, off1, val, buf, pos) {
  659. var sign = val < 0 ? 1 : 0;
  660. if (sign)
  661. val = -val;
  662. if (val === 0) {
  663. writeUint(0, buf, pos + off0);
  664. writeUint(1 / val > 0 ? (
  665. /* positive */
  666. 0
  667. ) : (
  668. /* negative 0 */
  669. 2147483648
  670. ), buf, pos + off1);
  671. } else if (isNaN(val)) {
  672. writeUint(0, buf, pos + off0);
  673. writeUint(2146959360, buf, pos + off1);
  674. } else if (val > 17976931348623157e292) {
  675. writeUint(0, buf, pos + off0);
  676. writeUint((sign << 31 | 2146435072) >>> 0, buf, pos + off1);
  677. } else {
  678. var mantissa;
  679. if (val < 22250738585072014e-324) {
  680. mantissa = val / 5e-324;
  681. writeUint(mantissa >>> 0, buf, pos + off0);
  682. writeUint((sign << 31 | mantissa / 4294967296) >>> 0, buf, pos + off1);
  683. } else {
  684. var exponent = Math.floor(Math.log(val) / Math.LN2);
  685. if (exponent === 1024)
  686. exponent = 1023;
  687. mantissa = val * Math.pow(2, -exponent);
  688. writeUint(mantissa * 4503599627370496 >>> 0, buf, pos + off0);
  689. writeUint((sign << 31 | exponent + 1023 << 20 | mantissa * 1048576 & 1048575) >>> 0, buf, pos + off1);
  690. }
  691. }
  692. }
  693. exports.writeDoubleLE = writeDouble_ieee754.bind(null, writeUintLE, 0, 4);
  694. exports.writeDoubleBE = writeDouble_ieee754.bind(null, writeUintBE, 4, 0);
  695. function readDouble_ieee754(readUint, off0, off1, buf, pos) {
  696. var lo = readUint(buf, pos + off0), hi = readUint(buf, pos + off1);
  697. var sign = (hi >> 31) * 2 + 1, exponent = hi >>> 20 & 2047, mantissa = 4294967296 * (hi & 1048575) + lo;
  698. return exponent === 2047 ? mantissa ? NaN : sign * Infinity : exponent === 0 ? sign * 5e-324 * mantissa : sign * Math.pow(2, exponent - 1075) * (mantissa + 4503599627370496);
  699. }
  700. exports.readDoubleLE = readDouble_ieee754.bind(null, readUintLE, 0, 4);
  701. exports.readDoubleBE = readDouble_ieee754.bind(null, readUintBE, 4, 0);
  702. })();
  703. return exports;
  704. }
  705. function writeUintLE(val, buf, pos) {
  706. buf[pos] = val & 255;
  707. buf[pos + 1] = val >>> 8 & 255;
  708. buf[pos + 2] = val >>> 16 & 255;
  709. buf[pos + 3] = val >>> 24;
  710. }
  711. function writeUintBE(val, buf, pos) {
  712. buf[pos] = val >>> 24;
  713. buf[pos + 1] = val >>> 16 & 255;
  714. buf[pos + 2] = val >>> 8 & 255;
  715. buf[pos + 3] = val & 255;
  716. }
  717. function readUintLE(buf, pos) {
  718. return (buf[pos] | buf[pos + 1] << 8 | buf[pos + 2] << 16 | buf[pos + 3] << 24) >>> 0;
  719. }
  720. function readUintBE(buf, pos) {
  721. return (buf[pos] << 24 | buf[pos + 1] << 16 | buf[pos + 2] << 8 | buf[pos + 3]) >>> 0;
  722. }
  723. return float;
  724. }
  725. var inquire_1;
  726. var hasRequiredInquire;
  727. function requireInquire() {
  728. if (hasRequiredInquire) return inquire_1;
  729. hasRequiredInquire = 1;
  730. inquire_1 = inquire;
  731. function inquire(moduleName) {
  732. try {
  733. var mod = eval("quire".replace(/^/, "re"))(moduleName);
  734. if (mod && (mod.length || Object.keys(mod).length))
  735. return mod;
  736. } catch (e) {
  737. }
  738. return null;
  739. }
  740. return inquire_1;
  741. }
  742. var utf8 = {};
  743. var hasRequiredUtf8;
  744. function requireUtf8() {
  745. if (hasRequiredUtf8) return utf8;
  746. hasRequiredUtf8 = 1;
  747. (function(exports) {
  748. var utf82 = exports;
  749. utf82.length = function utf8_length(string) {
  750. var len = 0, c = 0;
  751. for (var i = 0; i < string.length; ++i) {
  752. c = string.charCodeAt(i);
  753. if (c < 128)
  754. len += 1;
  755. else if (c < 2048)
  756. len += 2;
  757. else if ((c & 64512) === 55296 && (string.charCodeAt(i + 1) & 64512) === 56320) {
  758. ++i;
  759. len += 4;
  760. } else
  761. len += 3;
  762. }
  763. return len;
  764. };
  765. utf82.read = function utf8_read(buffer, start, end) {
  766. var len = end - start;
  767. if (len < 1)
  768. return "";
  769. var parts = null, chunk = [], i = 0, t;
  770. while (start < end) {
  771. t = buffer[start++];
  772. if (t < 128)
  773. chunk[i++] = t;
  774. else if (t > 191 && t < 224)
  775. chunk[i++] = (t & 31) << 6 | buffer[start++] & 63;
  776. else if (t > 239 && t < 365) {
  777. t = ((t & 7) << 18 | (buffer[start++] & 63) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63) - 65536;
  778. chunk[i++] = 55296 + (t >> 10);
  779. chunk[i++] = 56320 + (t & 1023);
  780. } else
  781. chunk[i++] = (t & 15) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63;
  782. if (i > 8191) {
  783. (parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));
  784. i = 0;
  785. }
  786. }
  787. if (parts) {
  788. if (i)
  789. parts.push(String.fromCharCode.apply(String, chunk.slice(0, i)));
  790. return parts.join("");
  791. }
  792. return String.fromCharCode.apply(String, chunk.slice(0, i));
  793. };
  794. utf82.write = function utf8_write(string, buffer, offset) {
  795. var start = offset, c1, c2;
  796. for (var i = 0; i < string.length; ++i) {
  797. c1 = string.charCodeAt(i);
  798. if (c1 < 128) {
  799. buffer[offset++] = c1;
  800. } else if (c1 < 2048) {
  801. buffer[offset++] = c1 >> 6 | 192;
  802. buffer[offset++] = c1 & 63 | 128;
  803. } else if ((c1 & 64512) === 55296 && ((c2 = string.charCodeAt(i + 1)) & 64512) === 56320) {
  804. c1 = 65536 + ((c1 & 1023) << 10) + (c2 & 1023);
  805. ++i;
  806. buffer[offset++] = c1 >> 18 | 240;
  807. buffer[offset++] = c1 >> 12 & 63 | 128;
  808. buffer[offset++] = c1 >> 6 & 63 | 128;
  809. buffer[offset++] = c1 & 63 | 128;
  810. } else {
  811. buffer[offset++] = c1 >> 12 | 224;
  812. buffer[offset++] = c1 >> 6 & 63 | 128;
  813. buffer[offset++] = c1 & 63 | 128;
  814. }
  815. }
  816. return offset - start;
  817. };
  818. })(utf8);
  819. return utf8;
  820. }
  821. var pool_1;
  822. var hasRequiredPool;
  823. function requirePool() {
  824. if (hasRequiredPool) return pool_1;
  825. hasRequiredPool = 1;
  826. pool_1 = pool;
  827. function pool(alloc, slice, size) {
  828. var SIZE = size || 8192;
  829. var MAX = SIZE >>> 1;
  830. var slab = null;
  831. var offset = SIZE;
  832. return function pool_alloc(size2) {
  833. if (size2 < 1 || size2 > MAX)
  834. return alloc(size2);
  835. if (offset + size2 > SIZE) {
  836. slab = alloc(SIZE);
  837. offset = 0;
  838. }
  839. var buf = slice.call(slab, offset, offset += size2);
  840. if (offset & 7)
  841. offset = (offset | 7) + 1;
  842. return buf;
  843. };
  844. }
  845. return pool_1;
  846. }
  847. var longbits;
  848. var hasRequiredLongbits;
  849. function requireLongbits() {
  850. if (hasRequiredLongbits) return longbits;
  851. hasRequiredLongbits = 1;
  852. longbits = LongBits;
  853. var util = requireMinimal$1();
  854. function LongBits(lo, hi) {
  855. this.lo = lo >>> 0;
  856. this.hi = hi >>> 0;
  857. }
  858. var zero = LongBits.zero = new LongBits(0, 0);
  859. zero.toNumber = function() {
  860. return 0;
  861. };
  862. zero.zzEncode = zero.zzDecode = function() {
  863. return this;
  864. };
  865. zero.length = function() {
  866. return 1;
  867. };
  868. var zeroHash = LongBits.zeroHash = "\0\0\0\0\0\0\0\0";
  869. LongBits.fromNumber = function fromNumber(value) {
  870. if (value === 0)
  871. return zero;
  872. var sign = value < 0;
  873. if (sign)
  874. value = -value;
  875. var lo = value >>> 0, hi = (value - lo) / 4294967296 >>> 0;
  876. if (sign) {
  877. hi = ~hi >>> 0;
  878. lo = ~lo >>> 0;
  879. if (++lo > 4294967295) {
  880. lo = 0;
  881. if (++hi > 4294967295)
  882. hi = 0;
  883. }
  884. }
  885. return new LongBits(lo, hi);
  886. };
  887. LongBits.from = function from(value) {
  888. if (typeof value === "number")
  889. return LongBits.fromNumber(value);
  890. if (util.isString(value)) {
  891. if (util.Long)
  892. value = util.Long.fromString(value);
  893. else
  894. return LongBits.fromNumber(parseInt(value, 10));
  895. }
  896. return value.low || value.high ? new LongBits(value.low >>> 0, value.high >>> 0) : zero;
  897. };
  898. LongBits.prototype.toNumber = function toNumber(unsigned) {
  899. if (!unsigned && this.hi >>> 31) {
  900. var lo = ~this.lo + 1 >>> 0, hi = ~this.hi >>> 0;
  901. if (!lo)
  902. hi = hi + 1 >>> 0;
  903. return -(lo + hi * 4294967296);
  904. }
  905. return this.lo + this.hi * 4294967296;
  906. };
  907. LongBits.prototype.toLong = function toLong(unsigned) {
  908. return util.Long ? new util.Long(this.lo | 0, this.hi | 0, Boolean(unsigned)) : { low: this.lo | 0, high: this.hi | 0, unsigned: Boolean(unsigned) };
  909. };
  910. var charCodeAt = String.prototype.charCodeAt;
  911. LongBits.fromHash = function fromHash(hash) {
  912. if (hash === zeroHash)
  913. return zero;
  914. return new LongBits(
  915. (charCodeAt.call(hash, 0) | charCodeAt.call(hash, 1) << 8 | charCodeAt.call(hash, 2) << 16 | charCodeAt.call(hash, 3) << 24) >>> 0,
  916. (charCodeAt.call(hash, 4) | charCodeAt.call(hash, 5) << 8 | charCodeAt.call(hash, 6) << 16 | charCodeAt.call(hash, 7) << 24) >>> 0
  917. );
  918. };
  919. LongBits.prototype.toHash = function toHash() {
  920. return String.fromCharCode(
  921. this.lo & 255,
  922. this.lo >>> 8 & 255,
  923. this.lo >>> 16 & 255,
  924. this.lo >>> 24,
  925. this.hi & 255,
  926. this.hi >>> 8 & 255,
  927. this.hi >>> 16 & 255,
  928. this.hi >>> 24
  929. );
  930. };
  931. LongBits.prototype.zzEncode = function zzEncode() {
  932. var mask = this.hi >> 31;
  933. this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask) >>> 0;
  934. this.lo = (this.lo << 1 ^ mask) >>> 0;
  935. return this;
  936. };
  937. LongBits.prototype.zzDecode = function zzDecode() {
  938. var mask = -(this.lo & 1);
  939. this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask) >>> 0;
  940. this.hi = (this.hi >>> 1 ^ mask) >>> 0;
  941. return this;
  942. };
  943. LongBits.prototype.length = function length() {
  944. var part0 = this.lo, part1 = (this.lo >>> 28 | this.hi << 4) >>> 0, part2 = this.hi >>> 24;
  945. return part2 === 0 ? part1 === 0 ? part0 < 16384 ? part0 < 128 ? 1 : 2 : part0 < 2097152 ? 3 : 4 : part1 < 16384 ? part1 < 128 ? 5 : 6 : part1 < 2097152 ? 7 : 8 : part2 < 128 ? 9 : 10;
  946. };
  947. return longbits;
  948. }
  949. var hasRequiredMinimal$1;
  950. function requireMinimal$1() {
  951. if (hasRequiredMinimal$1) return minimal$1;
  952. hasRequiredMinimal$1 = 1;
  953. (function(exports) {
  954. var util = exports;
  955. util.asPromise = requireAspromise();
  956. util.base64 = requireBase64();
  957. util.EventEmitter = requireEventemitter();
  958. util.float = requireFloat();
  959. util.inquire = requireInquire();
  960. util.utf8 = requireUtf8();
  961. util.pool = requirePool();
  962. util.LongBits = requireLongbits();
  963. util.isNode = Boolean(typeof commonjsGlobal !== "undefined" && commonjsGlobal && commonjsGlobal.process && commonjsGlobal.process.versions && commonjsGlobal.process.versions.node);
  964. util.global = util.isNode && commonjsGlobal || typeof window !== "undefined" && window || typeof self !== "undefined" && self || minimal$1;
  965. util.emptyArray = Object.freeze ? Object.freeze([]) : (
  966. /* istanbul ignore next */
  967. []
  968. );
  969. util.emptyObject = Object.freeze ? Object.freeze({}) : (
  970. /* istanbul ignore next */
  971. {}
  972. );
  973. util.isInteger = Number.isInteger || /* istanbul ignore next */
  974. function isInteger(value) {
  975. return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
  976. };
  977. util.isString = function isString(value) {
  978. return typeof value === "string" || value instanceof String;
  979. };
  980. util.isObject = function isObject(value) {
  981. return value && typeof value === "object";
  982. };
  983. util.isset = /**
  984. * Checks if a property on a message is considered to be present.
  985. * @param {Object} obj Plain object or message instance
  986. * @param {string} prop Property name
  987. * @returns {boolean} `true` if considered to be present, otherwise `false`
  988. */
  989. util.isSet = function isSet(obj, prop) {
  990. var value = obj[prop];
  991. if (value != null && obj.hasOwnProperty(prop))
  992. return typeof value !== "object" || (Array.isArray(value) ? value.length : Object.keys(value).length) > 0;
  993. return false;
  994. };
  995. util.Buffer = function() {
  996. try {
  997. var Buffer = util.inquire("buffer").Buffer;
  998. return Buffer.prototype.utf8Write ? Buffer : (
  999. /* istanbul ignore next */
  1000. null
  1001. );
  1002. } catch (e) {
  1003. return null;
  1004. }
  1005. }();
  1006. util._Buffer_from = null;
  1007. util._Buffer_allocUnsafe = null;
  1008. util.newBuffer = function newBuffer(sizeOrArray) {
  1009. return typeof sizeOrArray === "number" ? util.Buffer ? util._Buffer_allocUnsafe(sizeOrArray) : new util.Array(sizeOrArray) : util.Buffer ? util._Buffer_from(sizeOrArray) : typeof Uint8Array === "undefined" ? sizeOrArray : new Uint8Array(sizeOrArray);
  1010. };
  1011. util.Array = typeof Uint8Array !== "undefined" ? Uint8Array : Array;
  1012. util.Long = /* istanbul ignore next */
  1013. util.global.dcodeIO && /* istanbul ignore next */
  1014. util.global.dcodeIO.Long || /* istanbul ignore next */
  1015. util.global.Long || util.inquire("long");
  1016. util.key2Re = /^true|false|0|1$/;
  1017. util.key32Re = /^-?(?:0|[1-9][0-9]*)$/;
  1018. util.key64Re = /^(?:[\\x00-\\xff]{8}|-?(?:0|[1-9][0-9]*))$/;
  1019. util.longToHash = function longToHash(value) {
  1020. return value ? util.LongBits.from(value).toHash() : util.LongBits.zeroHash;
  1021. };
  1022. util.longFromHash = function longFromHash(hash, unsigned) {
  1023. var bits = util.LongBits.fromHash(hash);
  1024. if (util.Long)
  1025. return util.Long.fromBits(bits.lo, bits.hi, unsigned);
  1026. return bits.toNumber(Boolean(unsigned));
  1027. };
  1028. function merge(dst, src, ifNotSet) {
  1029. for (var keys = Object.keys(src), i = 0; i < keys.length; ++i)
  1030. if (dst[keys[i]] === void 0 || !ifNotSet)
  1031. dst[keys[i]] = src[keys[i]];
  1032. return dst;
  1033. }
  1034. util.merge = merge;
  1035. util.lcFirst = function lcFirst(str) {
  1036. return str.charAt(0).toLowerCase() + str.substring(1);
  1037. };
  1038. function newError(name) {
  1039. function CustomError(message, properties) {
  1040. if (!(this instanceof CustomError))
  1041. return new CustomError(message, properties);
  1042. Object.defineProperty(this, "message", { get: function() {
  1043. return message;
  1044. } });
  1045. if (Error.captureStackTrace)
  1046. Error.captureStackTrace(this, CustomError);
  1047. else
  1048. Object.defineProperty(this, "stack", { value: new Error().stack || "" });
  1049. if (properties)
  1050. merge(this, properties);
  1051. }
  1052. CustomError.prototype = Object.create(Error.prototype, {
  1053. constructor: {
  1054. value: CustomError,
  1055. writable: true,
  1056. enumerable: false,
  1057. configurable: true
  1058. },
  1059. name: {
  1060. get: function get() {
  1061. return name;
  1062. },
  1063. set: void 0,
  1064. enumerable: false,
  1065. // configurable: false would accurately preserve the behavior of
  1066. // the original, but I'm guessing that was not intentional.
  1067. // For an actual error subclass, this property would
  1068. // be configurable.
  1069. configurable: true
  1070. },
  1071. toString: {
  1072. value: function value() {
  1073. return this.name + ": " + this.message;
  1074. },
  1075. writable: true,
  1076. enumerable: false,
  1077. configurable: true
  1078. }
  1079. });
  1080. return CustomError;
  1081. }
  1082. util.newError = newError;
  1083. util.ProtocolError = newError("ProtocolError");
  1084. util.oneOfGetter = function getOneOf(fieldNames) {
  1085. var fieldMap = {};
  1086. for (var i = 0; i < fieldNames.length; ++i)
  1087. fieldMap[fieldNames[i]] = 1;
  1088. return function() {
  1089. for (var keys = Object.keys(this), i2 = keys.length - 1; i2 > -1; --i2)
  1090. if (fieldMap[keys[i2]] === 1 && this[keys[i2]] !== void 0 && this[keys[i2]] !== null)
  1091. return keys[i2];
  1092. };
  1093. };
  1094. util.oneOfSetter = function setOneOf(fieldNames) {
  1095. return function(name) {
  1096. for (var i = 0; i < fieldNames.length; ++i)
  1097. if (fieldNames[i] !== name)
  1098. delete this[fieldNames[i]];
  1099. };
  1100. };
  1101. util.toJSONOptions = {
  1102. longs: String,
  1103. enums: String,
  1104. bytes: String,
  1105. json: true
  1106. };
  1107. util._configure = function() {
  1108. var Buffer = util.Buffer;
  1109. if (!Buffer) {
  1110. util._Buffer_from = util._Buffer_allocUnsafe = null;
  1111. return;
  1112. }
  1113. util._Buffer_from = Buffer.from !== Uint8Array.from && Buffer.from || /* istanbul ignore next */
  1114. function Buffer_from(value, encoding) {
  1115. return new Buffer(value, encoding);
  1116. };
  1117. util._Buffer_allocUnsafe = Buffer.allocUnsafe || /* istanbul ignore next */
  1118. function Buffer_allocUnsafe(size) {
  1119. return new Buffer(size);
  1120. };
  1121. };
  1122. })(minimal$1);
  1123. return minimal$1;
  1124. }
  1125. var writer;
  1126. var hasRequiredWriter;
  1127. function requireWriter() {
  1128. if (hasRequiredWriter) return writer;
  1129. hasRequiredWriter = 1;
  1130. writer = Writer;
  1131. var util = requireMinimal$1();
  1132. var BufferWriter;
  1133. var LongBits = util.LongBits, base642 = util.base64, utf82 = util.utf8;
  1134. function Op(fn, len, val) {
  1135. this.fn = fn;
  1136. this.len = len;
  1137. this.next = void 0;
  1138. this.val = val;
  1139. }
  1140. function noop() {
  1141. }
  1142. function State(writer2) {
  1143. this.head = writer2.head;
  1144. this.tail = writer2.tail;
  1145. this.len = writer2.len;
  1146. this.next = writer2.states;
  1147. }
  1148. function Writer() {
  1149. this.len = 0;
  1150. this.head = new Op(noop, 0, 0);
  1151. this.tail = this.head;
  1152. this.states = null;
  1153. }
  1154. var create = function create2() {
  1155. return util.Buffer ? function create_buffer_setup() {
  1156. return (Writer.create = function create_buffer() {
  1157. return new BufferWriter();
  1158. })();
  1159. } : function create_array() {
  1160. return new Writer();
  1161. };
  1162. };
  1163. Writer.create = create();
  1164. Writer.alloc = function alloc(size) {
  1165. return new util.Array(size);
  1166. };
  1167. if (util.Array !== Array)
  1168. Writer.alloc = util.pool(Writer.alloc, util.Array.prototype.subarray);
  1169. Writer.prototype._push = function push(fn, len, val) {
  1170. this.tail = this.tail.next = new Op(fn, len, val);
  1171. this.len += len;
  1172. return this;
  1173. };
  1174. function writeByte(val, buf, pos) {
  1175. buf[pos] = val & 255;
  1176. }
  1177. function writeVarint32(val, buf, pos) {
  1178. while (val > 127) {
  1179. buf[pos++] = val & 127 | 128;
  1180. val >>>= 7;
  1181. }
  1182. buf[pos] = val;
  1183. }
  1184. function VarintOp(len, val) {
  1185. this.len = len;
  1186. this.next = void 0;
  1187. this.val = val;
  1188. }
  1189. VarintOp.prototype = Object.create(Op.prototype);
  1190. VarintOp.prototype.fn = writeVarint32;
  1191. Writer.prototype.uint32 = function write_uint32(value) {
  1192. this.len += (this.tail = this.tail.next = new VarintOp(
  1193. (value = value >>> 0) < 128 ? 1 : value < 16384 ? 2 : value < 2097152 ? 3 : value < 268435456 ? 4 : 5,
  1194. value
  1195. )).len;
  1196. return this;
  1197. };
  1198. Writer.prototype.int32 = function write_int32(value) {
  1199. return value < 0 ? this._push(writeVarint64, 10, LongBits.fromNumber(value)) : this.uint32(value);
  1200. };
  1201. Writer.prototype.sint32 = function write_sint32(value) {
  1202. return this.uint32((value << 1 ^ value >> 31) >>> 0);
  1203. };
  1204. function writeVarint64(val, buf, pos) {
  1205. while (val.hi) {
  1206. buf[pos++] = val.lo & 127 | 128;
  1207. val.lo = (val.lo >>> 7 | val.hi << 25) >>> 0;
  1208. val.hi >>>= 7;
  1209. }
  1210. while (val.lo > 127) {
  1211. buf[pos++] = val.lo & 127 | 128;
  1212. val.lo = val.lo >>> 7;
  1213. }
  1214. buf[pos++] = val.lo;
  1215. }
  1216. Writer.prototype.uint64 = function write_uint64(value) {
  1217. var bits = LongBits.from(value);
  1218. return this._push(writeVarint64, bits.length(), bits);
  1219. };
  1220. Writer.prototype.int64 = Writer.prototype.uint64;
  1221. Writer.prototype.sint64 = function write_sint64(value) {
  1222. var bits = LongBits.from(value).zzEncode();
  1223. return this._push(writeVarint64, bits.length(), bits);
  1224. };
  1225. Writer.prototype.bool = function write_bool(value) {
  1226. return this._push(writeByte, 1, value ? 1 : 0);
  1227. };
  1228. function writeFixed32(val, buf, pos) {
  1229. buf[pos] = val & 255;
  1230. buf[pos + 1] = val >>> 8 & 255;
  1231. buf[pos + 2] = val >>> 16 & 255;
  1232. buf[pos + 3] = val >>> 24;
  1233. }
  1234. Writer.prototype.fixed32 = function write_fixed32(value) {
  1235. return this._push(writeFixed32, 4, value >>> 0);
  1236. };
  1237. Writer.prototype.sfixed32 = Writer.prototype.fixed32;
  1238. Writer.prototype.fixed64 = function write_fixed64(value) {
  1239. var bits = LongBits.from(value);
  1240. return this._push(writeFixed32, 4, bits.lo)._push(writeFixed32, 4, bits.hi);
  1241. };
  1242. Writer.prototype.sfixed64 = Writer.prototype.fixed64;
  1243. Writer.prototype.float = function write_float(value) {
  1244. return this._push(util.float.writeFloatLE, 4, value);
  1245. };
  1246. Writer.prototype.double = function write_double(value) {
  1247. return this._push(util.float.writeDoubleLE, 8, value);
  1248. };
  1249. var writeBytes = util.Array.prototype.set ? function writeBytes_set(val, buf, pos) {
  1250. buf.set(val, pos);
  1251. } : function writeBytes_for(val, buf, pos) {
  1252. for (var i = 0; i < val.length; ++i)
  1253. buf[pos + i] = val[i];
  1254. };
  1255. Writer.prototype.bytes = function write_bytes(value) {
  1256. var len = value.length >>> 0;
  1257. if (!len)
  1258. return this._push(writeByte, 1, 0);
  1259. if (util.isString(value)) {
  1260. var buf = Writer.alloc(len = base642.length(value));
  1261. base642.decode(value, buf, 0);
  1262. value = buf;
  1263. }
  1264. return this.uint32(len)._push(writeBytes, len, value);
  1265. };
  1266. Writer.prototype.string = function write_string(value) {
  1267. var len = utf82.length(value);
  1268. return len ? this.uint32(len)._push(utf82.write, len, value) : this._push(writeByte, 1, 0);
  1269. };
  1270. Writer.prototype.fork = function fork() {
  1271. this.states = new State(this);
  1272. this.head = this.tail = new Op(noop, 0, 0);
  1273. this.len = 0;
  1274. return this;
  1275. };
  1276. Writer.prototype.reset = function reset() {
  1277. if (this.states) {
  1278. this.head = this.states.head;
  1279. this.tail = this.states.tail;
  1280. this.len = this.states.len;
  1281. this.states = this.states.next;
  1282. } else {
  1283. this.head = this.tail = new Op(noop, 0, 0);
  1284. this.len = 0;
  1285. }
  1286. return this;
  1287. };
  1288. Writer.prototype.ldelim = function ldelim() {
  1289. var head = this.head, tail = this.tail, len = this.len;
  1290. this.reset().uint32(len);
  1291. if (len) {
  1292. this.tail.next = head.next;
  1293. this.tail = tail;
  1294. this.len += len;
  1295. }
  1296. return this;
  1297. };
  1298. Writer.prototype.finish = function finish() {
  1299. var head = this.head.next, buf = this.constructor.alloc(this.len), pos = 0;
  1300. while (head) {
  1301. head.fn(head.val, buf, pos);
  1302. pos += head.len;
  1303. head = head.next;
  1304. }
  1305. return buf;
  1306. };
  1307. Writer._configure = function(BufferWriter_) {
  1308. BufferWriter = BufferWriter_;
  1309. Writer.create = create();
  1310. BufferWriter._configure();
  1311. };
  1312. return writer;
  1313. }
  1314. var writer_buffer;
  1315. var hasRequiredWriter_buffer;
  1316. function requireWriter_buffer() {
  1317. if (hasRequiredWriter_buffer) return writer_buffer;
  1318. hasRequiredWriter_buffer = 1;
  1319. writer_buffer = BufferWriter;
  1320. var Writer = requireWriter();
  1321. (BufferWriter.prototype = Object.create(Writer.prototype)).constructor = BufferWriter;
  1322. var util = requireMinimal$1();
  1323. function BufferWriter() {
  1324. Writer.call(this);
  1325. }
  1326. BufferWriter._configure = function() {
  1327. BufferWriter.alloc = util._Buffer_allocUnsafe;
  1328. BufferWriter.writeBytesBuffer = util.Buffer && util.Buffer.prototype instanceof Uint8Array && util.Buffer.prototype.set.name === "set" ? function writeBytesBuffer_set(val, buf, pos) {
  1329. buf.set(val, pos);
  1330. } : function writeBytesBuffer_copy(val, buf, pos) {
  1331. if (val.copy)
  1332. val.copy(buf, pos, 0, val.length);
  1333. else for (var i = 0; i < val.length; )
  1334. buf[pos++] = val[i++];
  1335. };
  1336. };
  1337. BufferWriter.prototype.bytes = function write_bytes_buffer(value) {
  1338. if (util.isString(value))
  1339. value = util._Buffer_from(value, "base64");
  1340. var len = value.length >>> 0;
  1341. this.uint32(len);
  1342. if (len)
  1343. this._push(BufferWriter.writeBytesBuffer, len, value);
  1344. return this;
  1345. };
  1346. function writeStringBuffer(val, buf, pos) {
  1347. if (val.length < 40)
  1348. util.utf8.write(val, buf, pos);
  1349. else if (buf.utf8Write)
  1350. buf.utf8Write(val, pos);
  1351. else
  1352. buf.write(val, pos);
  1353. }
  1354. BufferWriter.prototype.string = function write_string_buffer(value) {
  1355. var len = util.Buffer.byteLength(value);
  1356. this.uint32(len);
  1357. if (len)
  1358. this._push(writeStringBuffer, len, value);
  1359. return this;
  1360. };
  1361. BufferWriter._configure();
  1362. return writer_buffer;
  1363. }
  1364. var reader;
  1365. var hasRequiredReader;
  1366. function requireReader() {
  1367. if (hasRequiredReader) return reader;
  1368. hasRequiredReader = 1;
  1369. reader = Reader;
  1370. var util = requireMinimal$1();
  1371. var BufferReader;
  1372. var LongBits = util.LongBits, utf82 = util.utf8;
  1373. function indexOutOfRange(reader2, writeLength) {
  1374. return RangeError("index out of range: " + reader2.pos + " + " + (writeLength || 1) + " > " + reader2.len);
  1375. }
  1376. function Reader(buffer) {
  1377. this.buf = buffer;
  1378. this.pos = 0;
  1379. this.len = buffer.length;
  1380. }
  1381. var create_array = typeof Uint8Array !== "undefined" ? function create_typed_array(buffer) {
  1382. if (buffer instanceof Uint8Array || Array.isArray(buffer))
  1383. return new Reader(buffer);
  1384. throw Error("illegal buffer");
  1385. } : function create_array2(buffer) {
  1386. if (Array.isArray(buffer))
  1387. return new Reader(buffer);
  1388. throw Error("illegal buffer");
  1389. };
  1390. var create = function create2() {
  1391. return util.Buffer ? function create_buffer_setup(buffer) {
  1392. return (Reader.create = function create_buffer(buffer2) {
  1393. return util.Buffer.isBuffer(buffer2) ? new BufferReader(buffer2) : create_array(buffer2);
  1394. })(buffer);
  1395. } : create_array;
  1396. };
  1397. Reader.create = create();
  1398. Reader.prototype._slice = util.Array.prototype.subarray || /* istanbul ignore next */
  1399. util.Array.prototype.slice;
  1400. Reader.prototype.uint32 = /* @__PURE__ */ function read_uint32_setup() {
  1401. var value = 4294967295;
  1402. return function read_uint32() {
  1403. value = (this.buf[this.pos] & 127) >>> 0;
  1404. if (this.buf[this.pos++] < 128) return value;
  1405. value = (value | (this.buf[this.pos] & 127) << 7) >>> 0;
  1406. if (this.buf[this.pos++] < 128) return value;
  1407. value = (value | (this.buf[this.pos] & 127) << 14) >>> 0;
  1408. if (this.buf[this.pos++] < 128) return value;
  1409. value = (value | (this.buf[this.pos] & 127) << 21) >>> 0;
  1410. if (this.buf[this.pos++] < 128) return value;
  1411. value = (value | (this.buf[this.pos] & 15) << 28) >>> 0;
  1412. if (this.buf[this.pos++] < 128) return value;
  1413. if ((this.pos += 5) > this.len) {
  1414. this.pos = this.len;
  1415. throw indexOutOfRange(this, 10);
  1416. }
  1417. return value;
  1418. };
  1419. }();
  1420. Reader.prototype.int32 = function read_int32() {
  1421. return this.uint32() | 0;
  1422. };
  1423. Reader.prototype.sint32 = function read_sint32() {
  1424. var value = this.uint32();
  1425. return value >>> 1 ^ -(value & 1) | 0;
  1426. };
  1427. function readLongVarint() {
  1428. var bits = new LongBits(0, 0);
  1429. var i = 0;
  1430. if (this.len - this.pos > 4) {
  1431. for (; i < 4; ++i) {
  1432. bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;
  1433. if (this.buf[this.pos++] < 128)
  1434. return bits;
  1435. }
  1436. bits.lo = (bits.lo | (this.buf[this.pos] & 127) << 28) >>> 0;
  1437. bits.hi = (bits.hi | (this.buf[this.pos] & 127) >> 4) >>> 0;
  1438. if (this.buf[this.pos++] < 128)
  1439. return bits;
  1440. i = 0;
  1441. } else {
  1442. for (; i < 3; ++i) {
  1443. if (this.pos >= this.len)
  1444. throw indexOutOfRange(this);
  1445. bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;
  1446. if (this.buf[this.pos++] < 128)
  1447. return bits;
  1448. }
  1449. bits.lo = (bits.lo | (this.buf[this.pos++] & 127) << i * 7) >>> 0;
  1450. return bits;
  1451. }
  1452. if (this.len - this.pos > 4) {
  1453. for (; i < 5; ++i) {
  1454. bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0;
  1455. if (this.buf[this.pos++] < 128)
  1456. return bits;
  1457. }
  1458. } else {
  1459. for (; i < 5; ++i) {
  1460. if (this.pos >= this.len)
  1461. throw indexOutOfRange(this);
  1462. bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0;
  1463. if (this.buf[this.pos++] < 128)
  1464. return bits;
  1465. }
  1466. }
  1467. throw Error("invalid varint encoding");
  1468. }
  1469. Reader.prototype.bool = function read_bool() {
  1470. return this.uint32() !== 0;
  1471. };
  1472. function readFixed32_end(buf, end) {
  1473. return (buf[end - 4] | buf[end - 3] << 8 | buf[end - 2] << 16 | buf[end - 1] << 24) >>> 0;
  1474. }
  1475. Reader.prototype.fixed32 = function read_fixed32() {
  1476. if (this.pos + 4 > this.len)
  1477. throw indexOutOfRange(this, 4);
  1478. return readFixed32_end(this.buf, this.pos += 4);
  1479. };
  1480. Reader.prototype.sfixed32 = function read_sfixed32() {
  1481. if (this.pos + 4 > this.len)
  1482. throw indexOutOfRange(this, 4);
  1483. return readFixed32_end(this.buf, this.pos += 4) | 0;
  1484. };
  1485. function readFixed64() {
  1486. if (this.pos + 8 > this.len)
  1487. throw indexOutOfRange(this, 8);
  1488. return new LongBits(readFixed32_end(this.buf, this.pos += 4), readFixed32_end(this.buf, this.pos += 4));
  1489. }
  1490. Reader.prototype.float = function read_float() {
  1491. if (this.pos + 4 > this.len)
  1492. throw indexOutOfRange(this, 4);
  1493. var value = util.float.readFloatLE(this.buf, this.pos);
  1494. this.pos += 4;
  1495. return value;
  1496. };
  1497. Reader.prototype.double = function read_double() {
  1498. if (this.pos + 8 > this.len)
  1499. throw indexOutOfRange(this, 4);
  1500. var value = util.float.readDoubleLE(this.buf, this.pos);
  1501. this.pos += 8;
  1502. return value;
  1503. };
  1504. Reader.prototype.bytes = function read_bytes() {
  1505. var length = this.uint32(), start = this.pos, end = this.pos + length;
  1506. if (end > this.len)
  1507. throw indexOutOfRange(this, length);
  1508. this.pos += length;
  1509. if (Array.isArray(this.buf))
  1510. return this.buf.slice(start, end);
  1511. if (start === end) {
  1512. var nativeBuffer = util.Buffer;
  1513. return nativeBuffer ? nativeBuffer.alloc(0) : new this.buf.constructor(0);
  1514. }
  1515. return this._slice.call(this.buf, start, end);
  1516. };
  1517. Reader.prototype.string = function read_string() {
  1518. var bytes = this.bytes();
  1519. return utf82.read(bytes, 0, bytes.length);
  1520. };
  1521. Reader.prototype.skip = function skip(length) {
  1522. if (typeof length === "number") {
  1523. if (this.pos + length > this.len)
  1524. throw indexOutOfRange(this, length);
  1525. this.pos += length;
  1526. } else {
  1527. do {
  1528. if (this.pos >= this.len)
  1529. throw indexOutOfRange(this);
  1530. } while (this.buf[this.pos++] & 128);
  1531. }
  1532. return this;
  1533. };
  1534. Reader.prototype.skipType = function(wireType) {
  1535. switch (wireType) {
  1536. case 0:
  1537. this.skip();
  1538. break;
  1539. case 1:
  1540. this.skip(8);
  1541. break;
  1542. case 2:
  1543. this.skip(this.uint32());
  1544. break;
  1545. case 3:
  1546. while ((wireType = this.uint32() & 7) !== 4) {
  1547. this.skipType(wireType);
  1548. }
  1549. break;
  1550. case 5:
  1551. this.skip(4);
  1552. break;
  1553. /* istanbul ignore next */
  1554. default:
  1555. throw Error("invalid wire type " + wireType + " at offset " + this.pos);
  1556. }
  1557. return this;
  1558. };
  1559. Reader._configure = function(BufferReader_) {
  1560. BufferReader = BufferReader_;
  1561. Reader.create = create();
  1562. BufferReader._configure();
  1563. var fn = util.Long ? "toLong" : (
  1564. /* istanbul ignore next */
  1565. "toNumber"
  1566. );
  1567. util.merge(Reader.prototype, {
  1568. int64: function read_int64() {
  1569. return readLongVarint.call(this)[fn](false);
  1570. },
  1571. uint64: function read_uint64() {
  1572. return readLongVarint.call(this)[fn](true);
  1573. },
  1574. sint64: function read_sint64() {
  1575. return readLongVarint.call(this).zzDecode()[fn](false);
  1576. },
  1577. fixed64: function read_fixed64() {
  1578. return readFixed64.call(this)[fn](true);
  1579. },
  1580. sfixed64: function read_sfixed64() {
  1581. return readFixed64.call(this)[fn](false);
  1582. }
  1583. });
  1584. };
  1585. return reader;
  1586. }
  1587. var reader_buffer;
  1588. var hasRequiredReader_buffer;
  1589. function requireReader_buffer() {
  1590. if (hasRequiredReader_buffer) return reader_buffer;
  1591. hasRequiredReader_buffer = 1;
  1592. reader_buffer = BufferReader;
  1593. var Reader = requireReader();
  1594. (BufferReader.prototype = Object.create(Reader.prototype)).constructor = BufferReader;
  1595. var util = requireMinimal$1();
  1596. function BufferReader(buffer) {
  1597. Reader.call(this, buffer);
  1598. }
  1599. BufferReader._configure = function() {
  1600. if (util.Buffer)
  1601. BufferReader.prototype._slice = util.Buffer.prototype.slice;
  1602. };
  1603. BufferReader.prototype.string = function read_string_buffer() {
  1604. var len = this.uint32();
  1605. return this.buf.utf8Slice ? this.buf.utf8Slice(this.pos, this.pos = Math.min(this.pos + len, this.len)) : this.buf.toString("utf-8", this.pos, this.pos = Math.min(this.pos + len, this.len));
  1606. };
  1607. BufferReader._configure();
  1608. return reader_buffer;
  1609. }
  1610. var rpc = {};
  1611. var service;
  1612. var hasRequiredService;
  1613. function requireService() {
  1614. if (hasRequiredService) return service;
  1615. hasRequiredService = 1;
  1616. service = Service;
  1617. var util = requireMinimal$1();
  1618. (Service.prototype = Object.create(util.EventEmitter.prototype)).constructor = Service;
  1619. function Service(rpcImpl, requestDelimited, responseDelimited) {
  1620. if (typeof rpcImpl !== "function")
  1621. throw TypeError("rpcImpl must be a function");
  1622. util.EventEmitter.call(this);
  1623. this.rpcImpl = rpcImpl;
  1624. this.requestDelimited = Boolean(requestDelimited);
  1625. this.responseDelimited = Boolean(responseDelimited);
  1626. }
  1627. Service.prototype.rpcCall = function rpcCall(method, requestCtor, responseCtor, request, callback) {
  1628. if (!request)
  1629. throw TypeError("request must be specified");
  1630. var self2 = this;
  1631. if (!callback)
  1632. return util.asPromise(rpcCall, self2, method, requestCtor, responseCtor, request);
  1633. if (!self2.rpcImpl) {
  1634. setTimeout(function() {
  1635. callback(Error("already ended"));
  1636. }, 0);
  1637. return void 0;
  1638. }
  1639. try {
  1640. return self2.rpcImpl(
  1641. method,
  1642. requestCtor[self2.requestDelimited ? "encodeDelimited" : "encode"](request).finish(),
  1643. function rpcCallback(err, response) {
  1644. if (err) {
  1645. self2.emit("error", err, method);
  1646. return callback(err);
  1647. }
  1648. if (response === null) {
  1649. self2.end(
  1650. /* endedByRPC */
  1651. true
  1652. );
  1653. return void 0;
  1654. }
  1655. if (!(response instanceof responseCtor)) {
  1656. try {
  1657. response = responseCtor[self2.responseDelimited ? "decodeDelimited" : "decode"](response);
  1658. } catch (err2) {
  1659. self2.emit("error", err2, method);
  1660. return callback(err2);
  1661. }
  1662. }
  1663. self2.emit("data", response, method);
  1664. return callback(null, response);
  1665. }
  1666. );
  1667. } catch (err) {
  1668. self2.emit("error", err, method);
  1669. setTimeout(function() {
  1670. callback(err);
  1671. }, 0);
  1672. return void 0;
  1673. }
  1674. };
  1675. Service.prototype.end = function end(endedByRPC) {
  1676. if (this.rpcImpl) {
  1677. if (!endedByRPC)
  1678. this.rpcImpl(null, null, null);
  1679. this.rpcImpl = null;
  1680. this.emit("end").off();
  1681. }
  1682. return this;
  1683. };
  1684. return service;
  1685. }
  1686. var hasRequiredRpc;
  1687. function requireRpc() {
  1688. if (hasRequiredRpc) return rpc;
  1689. hasRequiredRpc = 1;
  1690. (function(exports) {
  1691. var rpc2 = exports;
  1692. rpc2.Service = requireService();
  1693. })(rpc);
  1694. return rpc;
  1695. }
  1696. var roots;
  1697. var hasRequiredRoots;
  1698. function requireRoots() {
  1699. if (hasRequiredRoots) return roots;
  1700. hasRequiredRoots = 1;
  1701. roots = {};
  1702. return roots;
  1703. }
  1704. var hasRequiredIndexMinimal;
  1705. function requireIndexMinimal() {
  1706. if (hasRequiredIndexMinimal) return indexMinimal;
  1707. hasRequiredIndexMinimal = 1;
  1708. (function(exports) {
  1709. var protobuf = exports;
  1710. protobuf.build = "minimal";
  1711. protobuf.Writer = requireWriter();
  1712. protobuf.BufferWriter = requireWriter_buffer();
  1713. protobuf.Reader = requireReader();
  1714. protobuf.BufferReader = requireReader_buffer();
  1715. protobuf.util = requireMinimal$1();
  1716. protobuf.rpc = requireRpc();
  1717. protobuf.roots = requireRoots();
  1718. protobuf.configure = configure;
  1719. function configure() {
  1720. protobuf.util._configure();
  1721. protobuf.Writer._configure(protobuf.BufferWriter);
  1722. protobuf.Reader._configure(protobuf.BufferReader);
  1723. }
  1724. configure();
  1725. })(indexMinimal);
  1726. return indexMinimal;
  1727. }
  1728. var minimal;
  1729. var hasRequiredMinimal;
  1730. function requireMinimal() {
  1731. if (hasRequiredMinimal) return minimal;
  1732. hasRequiredMinimal = 1;
  1733. minimal = requireIndexMinimal();
  1734. return minimal;
  1735. }
  1736. var minimalExports = requireMinimal();
  1737. const $Writer = minimalExports.Writer;
  1738. const $root$2 = minimalExports.roots["default"] || (minimalExports.roots["default"] = {});
  1739. const NextContinuation = $root$2.NextContinuation = (() => {
  1740. function NextContinuation2(p) {
  1741. if (p) {
  1742. for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
  1743. if (p[ks[i]] != null)
  1744. this[ks[i]] = p[ks[i]];
  1745. }
  1746. }
  1747. NextContinuation2.prototype.commentAreaWrapper = null;
  1748. NextContinuation2.prototype.uField3 = 0;
  1749. NextContinuation2.prototype.mainCommentRequest = null;
  1750. NextContinuation2.encode = function encode(m, w) {
  1751. if (!w)
  1752. w = $Writer.create();
  1753. if (m.commentAreaWrapper != null && Object.hasOwnProperty.call(m, "commentAreaWrapper"))
  1754. $root$2.CommentAreaWrapper.encode(m.commentAreaWrapper, w.uint32(18).fork()).ldelim();
  1755. if (m.uField3 != null && Object.hasOwnProperty.call(m, "uField3"))
  1756. w.uint32(24).int32(m.uField3);
  1757. if (m.mainCommentRequest != null && Object.hasOwnProperty.call(m, "mainCommentRequest"))
  1758. $root$2.MainCommentRequest.encode(m.mainCommentRequest, w.uint32(50).fork()).ldelim();
  1759. return w;
  1760. };
  1761. return NextContinuation2;
  1762. })();
  1763. $root$2.CommentAreaWrapper = (() => {
  1764. function CommentAreaWrapper(p) {
  1765. if (p) {
  1766. for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
  1767. if (p[ks[i]] != null)
  1768. this[ks[i]] = p[ks[i]];
  1769. }
  1770. }
  1771. CommentAreaWrapper.prototype.videoId = "";
  1772. CommentAreaWrapper.encode = function encode(m, w) {
  1773. if (!w)
  1774. w = $Writer.create();
  1775. if (m.videoId != null && Object.hasOwnProperty.call(m, "videoId"))
  1776. w.uint32(18).string(m.videoId);
  1777. return w;
  1778. };
  1779. return CommentAreaWrapper;
  1780. })();
  1781. $root$2.MainCommentRequest = (() => {
  1782. function MainCommentRequest(p) {
  1783. if (p) {
  1784. for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
  1785. if (p[ks[i]] != null)
  1786. this[ks[i]] = p[ks[i]];
  1787. }
  1788. }
  1789. MainCommentRequest.prototype.commentParameters = null;
  1790. MainCommentRequest.prototype.commentReplyParameters = null;
  1791. MainCommentRequest.prototype.sectionIdentifier = "";
  1792. MainCommentRequest.encode = function encode(m, w) {
  1793. if (!w)
  1794. w = $Writer.create();
  1795. if (m.commentReplyParameters != null && Object.hasOwnProperty.call(m, "commentReplyParameters"))
  1796. $root$2.CommentReplyParameters.encode(m.commentReplyParameters, w.uint32(26).fork()).ldelim();
  1797. if (m.commentParameters != null && Object.hasOwnProperty.call(m, "commentParameters"))
  1798. $root$2.CommentParameters.encode(m.commentParameters, w.uint32(34).fork()).ldelim();
  1799. if (m.sectionIdentifier != null && Object.hasOwnProperty.call(m, "sectionIdentifier"))
  1800. w.uint32(66).string(m.sectionIdentifier);
  1801. return w;
  1802. };
  1803. return MainCommentRequest;
  1804. })();
  1805. $root$2.CommentParameters = (() => {
  1806. function CommentParameters(p) {
  1807. if (p) {
  1808. for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
  1809. if (p[ks[i]] != null)
  1810. this[ks[i]] = p[ks[i]];
  1811. }
  1812. }
  1813. CommentParameters.prototype.videoId = "";
  1814. CommentParameters.prototype.postId = "";
  1815. CommentParameters.prototype.channelId = "";
  1816. CommentParameters.prototype.sortType = 0;
  1817. CommentParameters.prototype.targetCommentId = "";
  1818. CommentParameters.encode = function encode(m, w) {
  1819. if (!w)
  1820. w = $Writer.create();
  1821. if (m.videoId != null && Object.hasOwnProperty.call(m, "videoId"))
  1822. w.uint32(34).string(m.videoId);
  1823. if (m.sortType != null && Object.hasOwnProperty.call(m, "sortType"))
  1824. w.uint32(48).int32(m.sortType);
  1825. if (m.targetCommentId != null && Object.hasOwnProperty.call(m, "targetCommentId"))
  1826. w.uint32(130).string(m.targetCommentId);
  1827. if (m.postId != null && Object.hasOwnProperty.call(m, "postId"))
  1828. w.uint32(234).string(m.postId);
  1829. if (m.channelId != null && Object.hasOwnProperty.call(m, "channelId"))
  1830. w.uint32(242).string(m.channelId);
  1831. return w;
  1832. };
  1833. CommentParameters.SortType = function() {
  1834. const valuesById = {}, values = Object.create(valuesById);
  1835. values[valuesById[0] = "HOT"] = 0;
  1836. values[valuesById[1] = "LATEST"] = 1;
  1837. return values;
  1838. }();
  1839. return CommentParameters;
  1840. })();
  1841. $root$2.CommentReplyParameters = (() => {
  1842. function CommentReplyParameters(p) {
  1843. if (p) {
  1844. for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
  1845. if (p[ks[i]] != null)
  1846. this[ks[i]] = p[ks[i]];
  1847. }
  1848. }
  1849. CommentReplyParameters.prototype.rootCommentId = "";
  1850. CommentReplyParameters.prototype.channelId = "";
  1851. CommentReplyParameters.prototype.videoId = "";
  1852. CommentReplyParameters.prototype.postId = "";
  1853. CommentReplyParameters.prototype.pageSize = 0;
  1854. CommentReplyParameters.prototype.sortParam = null;
  1855. CommentReplyParameters.encode = function encode(m, w) {
  1856. if (!w)
  1857. w = $Writer.create();
  1858. if (m.rootCommentId != null && Object.hasOwnProperty.call(m, "rootCommentId"))
  1859. w.uint32(18).string(m.rootCommentId);
  1860. if (m.channelId != null && Object.hasOwnProperty.call(m, "channelId"))
  1861. w.uint32(42).string(m.channelId);
  1862. if (m.videoId != null && Object.hasOwnProperty.call(m, "videoId"))
  1863. w.uint32(50).string(m.videoId);
  1864. if (m.pageSize != null && Object.hasOwnProperty.call(m, "pageSize"))
  1865. w.uint32(72).int32(m.pageSize);
  1866. if (m.postId != null && Object.hasOwnProperty.call(m, "postId"))
  1867. w.uint32(122).string(m.postId);
  1868. if (m.sortParam != null && Object.hasOwnProperty.call(m, "sortParam"))
  1869. $root$2.CommentReplyParameters.SortParam.encode(m.sortParam, w.uint32(130).fork()).ldelim();
  1870. return w;
  1871. };
  1872. CommentReplyParameters.SortParam = function() {
  1873. function SortParam(p) {
  1874. if (p) {
  1875. for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
  1876. if (p[ks[i]] != null)
  1877. this[ks[i]] = p[ks[i]];
  1878. }
  1879. }
  1880. SortParam.prototype.sortType = 0;
  1881. SortParam.encode = function encode(m, w) {
  1882. if (!w)
  1883. w = $Writer.create();
  1884. if (m.sortType != null && Object.hasOwnProperty.call(m, "sortType"))
  1885. w.uint32(8).int32(m.sortType);
  1886. return w;
  1887. };
  1888. SortParam.SortType = function() {
  1889. const valuesById = {}, values = Object.create(valuesById);
  1890. values[valuesById[0] = "DEFAULT"] = 0;
  1891. values[valuesById[1] = "HOT"] = 1;
  1892. values[valuesById[2] = "LATEST"] = 2;
  1893. return values;
  1894. }();
  1895. return SortParam;
  1896. }();
  1897. return CommentReplyParameters;
  1898. })();
  1899. const BrowserContinuation = $root$2.BrowserContinuation = (() => {
  1900. function BrowserContinuation2(p) {
  1901. if (p) {
  1902. for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
  1903. if (p[ks[i]] != null)
  1904. this[ks[i]] = p[ks[i]];
  1905. }
  1906. }
  1907. BrowserContinuation2.prototype.request = null;
  1908. BrowserContinuation2.encode = function encode(m, w) {
  1909. if (!w)
  1910. w = $Writer.create();
  1911. if (m.request != null && Object.hasOwnProperty.call(m, "request"))
  1912. $root$2.BrowserContinuation.Request.encode(m.request, w.uint32(641815778).fork()).ldelim();
  1913. return w;
  1914. };
  1915. BrowserContinuation2.Request = function() {
  1916. function Request(p) {
  1917. if (p) {
  1918. for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
  1919. if (p[ks[i]] != null)
  1920. this[ks[i]] = p[ks[i]];
  1921. }
  1922. }
  1923. Request.prototype.description = "";
  1924. Request.prototype.continuationBase64 = "";
  1925. Request.encode = function encode(m, w) {
  1926. if (!w)
  1927. w = $Writer.create();
  1928. if (m.description != null && Object.hasOwnProperty.call(m, "description"))
  1929. w.uint32(18).string(m.description);
  1930. if (m.continuationBase64 != null && Object.hasOwnProperty.call(m, "continuationBase64"))
  1931. w.uint32(26).string(m.continuationBase64);
  1932. return w;
  1933. };
  1934. return Request;
  1935. }();
  1936. return BrowserContinuation2;
  1937. })();
  1938. const BrowserCommentListContinuation = $root$2.BrowserCommentListContinuation = (() => {
  1939. function BrowserCommentListContinuation2(p) {
  1940. if (p) {
  1941. for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
  1942. if (p[ks[i]] != null)
  1943. this[ks[i]] = p[ks[i]];
  1944. }
  1945. }
  1946. BrowserCommentListContinuation2.prototype.description = "";
  1947. BrowserCommentListContinuation2.prototype.mainCommentRequest = null;
  1948. BrowserCommentListContinuation2.encode = function encode(m, w) {
  1949. if (!w)
  1950. w = $Writer.create();
  1951. if (m.description != null && Object.hasOwnProperty.call(m, "description"))
  1952. w.uint32(18).string(m.description);
  1953. if (m.mainCommentRequest != null && Object.hasOwnProperty.call(m, "mainCommentRequest"))
  1954. $root$2.MainCommentRequest.encode(m.mainCommentRequest, w.uint32(426).fork()).ldelim();
  1955. return w;
  1956. };
  1957. return BrowserCommentListContinuation2;
  1958. })();
  1959. const $Reader$1 = minimalExports.Reader;
  1960. const $root$1 = minimalExports.roots["default"] || (minimalExports.roots["default"] = {});
  1961. const CommentAction = $root$1.CommentAction = (() => {
  1962. function CommentAction2(p) {
  1963. if (p) {
  1964. for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
  1965. if (p[ks[i]] != null)
  1966. this[ks[i]] = p[ks[i]];
  1967. }
  1968. }
  1969. CommentAction2.prototype.action = 0;
  1970. CommentAction2.prototype.commentId = "";
  1971. CommentAction2.decode = function decode(r, l, e) {
  1972. if (!(r instanceof $Reader$1))
  1973. r = $Reader$1.create(r);
  1974. var c = l === void 0 ? r.len : r.pos + l, m = new $root$1.CommentAction();
  1975. while (r.pos < c) {
  1976. var t = r.uint32();
  1977. if (t === e)
  1978. break;
  1979. switch (t >>> 3) {
  1980. case 1: {
  1981. m.action = r.int32();
  1982. break;
  1983. }
  1984. case 3: {
  1985. m.commentId = r.string();
  1986. break;
  1987. }
  1988. default:
  1989. r.skipType(t & 7);
  1990. break;
  1991. }
  1992. }
  1993. return m;
  1994. };
  1995. return CommentAction2;
  1996. })();
  1997. $root$1.Action = (() => {
  1998. const valuesById = {}, values = Object.create(valuesById);
  1999. values[valuesById[0] = "DEFAULT"] = 0;
  2000. values[valuesById[5] = "LIKE"] = 5;
  2001. values[valuesById[6] = "DELETE"] = 6;
  2002. return values;
  2003. })();
  2004. const $Reader = minimalExports.Reader;
  2005. const $root = minimalExports.roots["default"] || (minimalExports.roots["default"] = {});
  2006. const UpdateCommentParams = $root.UpdateCommentParams = (() => {
  2007. function UpdateCommentParams2(p) {
  2008. if (p) {
  2009. for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
  2010. if (p[ks[i]] != null)
  2011. this[ks[i]] = p[ks[i]];
  2012. }
  2013. }
  2014. UpdateCommentParams2.prototype.commentId = "";
  2015. UpdateCommentParams2.decode = function decode(r, l, e) {
  2016. if (!(r instanceof $Reader))
  2017. r = $Reader.create(r);
  2018. var c = l === void 0 ? r.len : r.pos + l, m = new $root.UpdateCommentParams();
  2019. while (r.pos < c) {
  2020. var t = r.uint32();
  2021. if (t === e)
  2022. break;
  2023. switch (t >>> 3) {
  2024. case 1: {
  2025. m.commentId = r.string();
  2026. break;
  2027. }
  2028. default:
  2029. r.skipType(t & 7);
  2030. break;
  2031. }
  2032. }
  2033. return m;
  2034. };
  2035. return UpdateCommentParams2;
  2036. })();
  2037. var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
  2038. var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)();
  2039. const cssLoader = (e) => {
  2040. const t = GM_getResourceText(e);
  2041. return GM_addStyle(t), t;
  2042. };
  2043. cssLoader("element-plus/dist/index.css");
  2044. const _hoisted_1$1 = {
  2045. key: 0,
  2046. class: "hot-ban-checker"
  2047. };
  2048. const _hoisted_2$1 = { class: "message" };
  2049. const _hoisted_3$1 = { class: "buttons" };
  2050. const _hoisted_4$1 = { class: "actions" };
  2051. const _sfc_main$1 = {
  2052. __name: "CommentActions",
  2053. props: ["comment"],
  2054. emits: ["delete", "checkHotBan"],
  2055. setup(__props, { emit: __emit }) {
  2056. const props = __props;
  2057. const emit = __emit;
  2058. const comment = props.comment;
  2059. const check2 = vue.inject("check");
  2060. const hotBanCheck2 = vue.inject("hotBanCheck");
  2061. const updating = vue.ref(false);
  2062. const showHotBanChecker = vue.ref(false);
  2063. const hotBanCheckerMessage = vue.ref("等待检查中……");
  2064. let hotBanCheckerController = vue.reactive({ isCancelled: false });
  2065. function updateState() {
  2066. updating.value = true;
  2067. check2(comment).then(() => {
  2068. updating.value = false;
  2069. ElementPlus.ElMessage({
  2070. type: comment.currentState == "NORMAL" ? "success" : "warning",
  2071. message: "更新成功,当前状态:" + translateState(comment.currentState)
  2072. });
  2073. }).catch((err) => {
  2074. updating.value = false;
  2075. let msg = err.message;
  2076. if (msg == "COMMENT_AREA_CLOSED") {
  2077. msg = "评论区已关闭";
  2078. }
  2079. ElementPlus.ElMessage.error("更新失败,因为:" + msg);
  2080. });
  2081. }
  2082. function copyComment(commentText) {
  2083. if (navigator.clipboard) {
  2084. navigator.clipboard.writeText(commentText).then(() => {
  2085. ElementPlus.ElMessage({
  2086. message: "评论已复制到剪贴板",
  2087. type: "success"
  2088. });
  2089. }).catch((err) => {
  2090. ElementPlus.ElMessage.error("无法复制文本,因为: " + err);
  2091. });
  2092. } else {
  2093. const textArea = document.createElement("textarea");
  2094. textArea.value = commentText;
  2095. document.body.appendChild(textArea);
  2096. textArea.select();
  2097. try {
  2098. document.execCommand("copy");
  2099. ElementPlus.ElMessage({
  2100. message: "评论已复制到剪贴板",
  2101. type: "success"
  2102. });
  2103. } catch (err) {
  2104. ElementPlus.ElMessage.error("无法复制文本,因为: " + err);
  2105. }
  2106. document.body.removeChild(textArea);
  2107. }
  2108. }
  2109. function askDelete() {
  2110. ElementPlus.ElMessageBox.confirm("确定要删除这条记录吗(这不会删除你在YouTube上发布的评论)?删除操作无法撤销!").then(() => {
  2111. emit("delete");
  2112. }).catch(() => {
  2113. });
  2114. }
  2115. async function toHotBanCheck() {
  2116. if (Date.now() - comment.recordedTime < 120 * 1e3) {
  2117. ElementPlus.ElMessage.warning(`当前时间距评论记录时间不足2分钟,状态不可信,请到 ${formatTimestamp(comment.recordedTime + 120 * 1e3)} 来检查`);
  2118. return;
  2119. }
  2120. if (comment.commentId.indexOf(".") == -1) {
  2121. try {
  2122. await ElementPlus.ElMessageBox.confirm(
  2123. "确认检查吗?该检查需要遍历热门评论区,请注意评论区的评论数量(总数大于3000的评论区慎重考虑)!数量太多将导致漫长的检查过程,同时频繁调用API可能会引发不可预料的后果!",
  2124. "警告",
  2125. {
  2126. confirmButtonText: "确定",
  2127. cancelButtonText: "取消"
  2128. }
  2129. );
  2130. } catch (err) {
  2131. return;
  2132. }
  2133. }
  2134. hotBanCheckerMessage.value = "正在重新检查评论状态……";
  2135. hotBanCheckerController.isCancelled = false;
  2136. showHotBanChecker.value = true;
  2137. try {
  2138. await check2(comment);
  2139. if (comment.currentState != "NORMAL") {
  2140. ElementPlus.ElMessage.error(`评论状态重新检查后为${translateState(comment.currentState)},无法继续进行检查`);
  2141. showHotBanChecker.value = false;
  2142. return;
  2143. }
  2144. } catch (err) {
  2145. let msg = err.message;
  2146. if (msg == "COMMENT_AREA_CLOSED") {
  2147. msg = "评论区已关闭";
  2148. }
  2149. ElementPlus.ElMessage.error("检查失败,因为" + msg);
  2150. showHotBanChecker.value = false;
  2151. return;
  2152. }
  2153. let observer = {
  2154. onCountChange(c, p) {
  2155. hotBanCheckerMessage.value = `正在搜索热门列表,已搜寻至:第${c}个 ${p}页`;
  2156. }
  2157. };
  2158. let notCancelled;
  2159. try {
  2160. notCancelled = await hotBanCheck2(comment, observer, hotBanCheckerController);
  2161. } catch (err) {
  2162. showHotBanChecker.value = false;
  2163. ElementPlus.ElMessage.error(err.message);
  2164. return;
  2165. }
  2166. if (notCancelled) {
  2167. if (comment.hotBan) {
  2168. ElementPlus.ElMessage.warning("你的评论未在热门列表找到,已被热门屏蔽,检查完成");
  2169. } else {
  2170. ElementPlus.ElMessage.success("你的评论已在热门列表找到,没有被热门屏蔽,检查完成");
  2171. }
  2172. }
  2173. showHotBanChecker.value = false;
  2174. }
  2175. return (_ctx, _cache) => {
  2176. const _component_el_button = vue.resolveComponent("el-button");
  2177. return vue.openBlock(), vue.createElementBlock("div", null, [
  2178. showHotBanChecker.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1, [
  2179. _cache[2] || (_cache[2] = vue.createElementVNode("div", { class: "title" }, "热门屏蔽检查", -1)),
  2180. vue.createElementVNode("div", _hoisted_2$1, vue.toDisplayString(hotBanCheckerMessage.value), 1),
  2181. vue.createElementVNode("div", _hoisted_3$1, [
  2182. vue.createElementVNode("span", {
  2183. onClick: _cache[0] || (_cache[0] = ($event) => vue.unref(hotBanCheckerController).isCancelled = true)
  2184. }, "终止检查")
  2185. ])
  2186. ])) : vue.createCommentVNode("", true),
  2187. vue.createElementVNode("div", _hoisted_4$1, [
  2188. vue.unref(comment).isUserDelete == false ? (vue.openBlock(), vue.createBlock(_component_el_button, {
  2189. key: 0,
  2190. type: "primary",
  2191. plain: "",
  2192. onClick: updateState,
  2193. loading: updating.value
  2194. }, {
  2195. default: vue.withCtx(() => _cache[3] || (_cache[3] = [
  2196. vue.createTextVNode("更新状态")
  2197. ])),
  2198. _: 1,
  2199. __: [3]
  2200. }, 8, ["loading"])) : vue.createCommentVNode("", true),
  2201. vue.unref(comment).currentState == "NORMAL" ? (vue.openBlock(), vue.createBlock(_component_el_button, {
  2202. key: 1,
  2203. type: "primary",
  2204. plain: "",
  2205. onClick: toHotBanCheck
  2206. }, {
  2207. default: vue.withCtx(() => _cache[4] || (_cache[4] = [
  2208. vue.createTextVNode("热门屏蔽检查")
  2209. ])),
  2210. _: 1,
  2211. __: [4]
  2212. })) : vue.createCommentVNode("", true),
  2213. vue.createVNode(_component_el_button, {
  2214. type: "primary",
  2215. plain: "",
  2216. onClick: _cache[1] || (_cache[1] = ($event) => copyComment(vue.unref(comment).content))
  2217. }, {
  2218. default: vue.withCtx(() => _cache[5] || (_cache[5] = [
  2219. vue.createTextVNode("复制")
  2220. ])),
  2221. _: 1,
  2222. __: [5]
  2223. }),
  2224. vue.createVNode(_component_el_button, {
  2225. type: "danger",
  2226. plain: "",
  2227. onClick: askDelete
  2228. }, {
  2229. default: vue.withCtx(() => _cache[6] || (_cache[6] = [
  2230. vue.createTextVNode("删除记录")
  2231. ])),
  2232. _: 1,
  2233. __: [6]
  2234. })
  2235. ])
  2236. ]);
  2237. };
  2238. }
  2239. };
  2240. const CommentActions = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-e5341f8d"]]);
  2241. const _hoisted_1 = { class: "detail" };
  2242. const _hoisted_2 = { class: "info-table" };
  2243. const _hoisted_3 = { class: "comment-content" };
  2244. const _hoisted_4 = { key: 0 };
  2245. const _hoisted_5 = { key: 3 };
  2246. const _hoisted_6 = { class: "comment-content" };
  2247. const _hoisted_7 = { class: "pagination" };
  2248. const pageSize = 20;
  2249. const _sfc_main = {
  2250. __name: "App",
  2251. setup(__props) {
  2252. const dialogVisible = vue.ref(false);
  2253. const menuListener = vue.inject("menuListener");
  2254. const deleteComment2 = vue.inject("deleteComment");
  2255. const db2 = vue.inject("db");
  2256. const comments = vue.reactive([]);
  2257. const loadingComments = vue.ref(false);
  2258. const prevTime = vue.ref(null);
  2259. const nextTime = vue.ref(null);
  2260. var prevStack = [null];
  2261. function loadComments(direction = "next") {
  2262. loadingComments.value = true;
  2263. comments.length = 0;
  2264. let time = null;
  2265. if (direction == "next") {
  2266. time = nextTime.value;
  2267. prevStack.push(time ? time : -1);
  2268. prevTime.value = prevStack[prevStack.length - 2];
  2269. } else if (direction == "prev") {
  2270. time = prevStack[prevStack.length - 2];
  2271. time = time == -1 ? null : time;
  2272. prevStack.pop();
  2273. prevTime.value = prevStack[prevStack.length - 2];
  2274. }
  2275. db2.transaction("comments").objectStore("comments").index("recordedTime").openCursor(time ? IDBKeyRange.upperBound(time) : null, "prev").onsuccess = (event) => {
  2276. var cursor = event.target.result;
  2277. if (cursor) {
  2278. if (comments.length < pageSize) {
  2279. comments.push(cursor.value);
  2280. cursor.continue();
  2281. } else {
  2282. nextTime.value = cursor.value.recordedTime;
  2283. loadingComments.value = false;
  2284. }
  2285. } else {
  2286. nextTime.value = null;
  2287. loadingComments.value = false;
  2288. }
  2289. };
  2290. }
  2291. menuListener.onOpenHistory = () => {
  2292. dialogVisible.value = true;
  2293. nextTime.value = null;
  2294. prevStack = [null];
  2295. loadComments();
  2296. };
  2297. function formatStateDesc(comment) {
  2298. switch (comment.currentState) {
  2299. case "NORMAL":
  2300. if (comment.hotBan === true) {
  2301. return "热门屏蔽";
  2302. } else if (comment.hotBan === false) {
  2303. return "完全正常";
  2304. } else {
  2305. return "正常";
  2306. }
  2307. case "DELETED":
  2308. if (comment.isUserDelete) {
  2309. return "用户删除";
  2310. } else {
  2311. return "已删除";
  2312. }
  2313. case "SHADOW_BAN":
  2314. return "仅自己可见";
  2315. case "NOT_CHECK":
  2316. return "还未检查";
  2317. }
  2318. }
  2319. function formatCommentArea(comment, needEmojiHead) {
  2320. var commentAreaInfo = comment.commentAreaInfo;
  2321. switch (comment.webPageType) {
  2322. case "WEB_PAGE_TYPE_WATCH":
  2323. return "📺 " + commentAreaInfo.videoId;
  2324. case "WEB_PAGE_TYPE_BROWSE":
  2325. return "📰" + commentAreaInfo.postId;
  2326. }
  2327. }
  2328. function formatHotBan(hotBan) {
  2329. if (hotBan == null) {
  2330. return "未检查";
  2331. }
  2332. return hotBan ? "是" : "否";
  2333. }
  2334. function deleteCommentItem(comment) {
  2335. deleteComment2(comment.commentId).then(() => {
  2336. const index = comments.findIndex((item) => item.commentId == comment.commentId);
  2337. if (index !== -1) {
  2338. comments.splice(index, 1);
  2339. ElementPlus.ElMessage.success("评论删除成功");
  2340. }
  2341. }).catch((err) => {
  2342. ElementPlus.ElMessage.error("评论删除失败");
  2343. console.error("delete comment from database failed", err);
  2344. });
  2345. }
  2346. return (_ctx, _cache) => {
  2347. const _component_el_table_column = vue.resolveComponent("el-table-column");
  2348. const _component_el_link = vue.resolveComponent("el-link");
  2349. const _component_el_table = vue.resolveComponent("el-table");
  2350. const _component_el_button = vue.resolveComponent("el-button");
  2351. const _component_el_dialog = vue.resolveComponent("el-dialog");
  2352. return vue.openBlock(), vue.createElementBlock("div", null, [
  2353. vue.createVNode(_component_el_dialog, {
  2354. modelValue: dialogVisible.value,
  2355. "onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => dialogVisible.value = $event),
  2356. "z-index": 3e3,
  2357. title: "历史评论列表",
  2358. width: "80%",
  2359. style: { "height": "92vh" },
  2360. "body-class": "dialog-body",
  2361. "align-center": ""
  2362. }, {
  2363. default: vue.withCtx(() => [
  2364. vue.createVNode(_component_el_table, {
  2365. data: comments,
  2366. "row-key": "commentId",
  2367. height: "100%",
  2368. class: "comment-list"
  2369. }, {
  2370. default: vue.withCtx(() => [
  2371. vue.createVNode(_component_el_table_column, {
  2372. prop: "content",
  2373. label: "评论内容",
  2374. align: "left",
  2375. "show-overflow-tooltip": ""
  2376. }),
  2377. vue.createVNode(_component_el_table_column, {
  2378. prop: "state",
  2379. label: "当前状态",
  2380. align: "center",
  2381. width: "136",
  2382. formatter: formatStateDesc
  2383. }),
  2384. vue.createVNode(_component_el_table_column, {
  2385. prop: "recordedTime",
  2386. label: "记录时间",
  2387. align: "center",
  2388. width: "160",
  2389. formatter: (comment) => vue.unref(formatTimestamp)(comment.recordedTime)
  2390. }, null, 8, ["formatter"]),
  2391. vue.createVNode(_component_el_table_column, {
  2392. prop: "area",
  2393. label: "所在评论区",
  2394. align: "center",
  2395. width: "240"
  2396. }, {
  2397. default: vue.withCtx(({ row }) => [
  2398. vue.createElementVNode("div", null, [
  2399. vue.createVNode(_component_el_link, {
  2400. type: "primary",
  2401. href: row.url,
  2402. class: vue.normalizeClass(["locate-link", { "post-locate-link": row.webPageType == "WEB_PAGE_TYPE_BROWSE" }])
  2403. }, {
  2404. default: vue.withCtx(() => [
  2405. vue.createTextVNode(vue.toDisplayString(formatCommentArea(row)), 1)
  2406. ]),
  2407. _: 2
  2408. }, 1032, ["href", "class"])
  2409. ])
  2410. ]),
  2411. _: 1
  2412. }),
  2413. vue.createVNode(_component_el_table_column, { type: "expand" }, {
  2414. default: vue.withCtx(({ row }) => [
  2415. vue.createElementVNode("div", _hoisted_1, [
  2416. vue.createElementVNode("table", _hoisted_2, [
  2417. vue.createElementVNode("tbody", null, [
  2418. vue.createElementVNode("tr", null, [
  2419. _cache[3] || (_cache[3] = vue.createElementVNode("td", null, "评论内容", -1)),
  2420. vue.createElementVNode("td", _hoisted_3, vue.toDisplayString(row.content), 1)
  2421. ]),
  2422. vue.createElementVNode("tr", null, [
  2423. _cache[4] || (_cache[4] = vue.createElementVNode("td", null, "当前状态", -1)),
  2424. vue.createElementVNode("td", null, vue.toDisplayString(vue.unref(translateState)(row.currentState)), 1)
  2425. ]),
  2426. row.currentState == "DELETED" ? (vue.openBlock(), vue.createElementBlock("tr", _hoisted_4, [
  2427. _cache[5] || (_cache[5] = vue.createElementVNode("td", null, "用户删除", -1)),
  2428. vue.createElementVNode("td", null, vue.toDisplayString(row.isUserDelete ? "是" : "否"), 1)
  2429. ])) : vue.createCommentVNode("", true),
  2430. vue.createElementVNode("tr", null, [
  2431. _cache[6] || (_cache[6] = vue.createElementVNode("td", null, "热门屏蔽", -1)),
  2432. vue.createElementVNode("td", null, vue.toDisplayString(formatHotBan(row.hotBan)), 1)
  2433. ]),
  2434. vue.createElementVNode("tr", null, [
  2435. _cache[7] || (_cache[7] = vue.createElementVNode("td", null, "发送者", -1)),
  2436. vue.createElementVNode("td", null, vue.toDisplayString(row.displayName), 1)
  2437. ]),
  2438. vue.createElementVNode("tr", null, [
  2439. _cache[8] || (_cache[8] = vue.createElementVNode("td", null, "评论ID", -1)),
  2440. vue.createElementVNode("td", null, vue.toDisplayString(row.commentId), 1)
  2441. ]),
  2442. row.webPageType == "WEB_PAGE_TYPE_WATCH" ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [
  2443. _cache[10] || (_cache[10] = vue.createElementVNode("tr", null, [
  2444. vue.createElementVNode("td", null, "评论区类型"),
  2445. vue.createElementVNode("td", null, "视频")
  2446. ], -1)),
  2447. vue.createElementVNode("tr", null, [
  2448. _cache[9] || (_cache[9] = vue.createElementVNode("td", null, "视频ID", -1)),
  2449. vue.createElementVNode("td", null, vue.toDisplayString(row.commentAreaInfo.videoId), 1)
  2450. ])
  2451. ], 64)) : row.webPageType == "WEB_PAGE_TYPE_BROWSE" ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 2 }, [
  2452. _cache[13] || (_cache[13] = vue.createElementVNode("tr", null, [
  2453. vue.createElementVNode("td", null, "评论区类型"),
  2454. vue.createElementVNode("td", null, "帖子")
  2455. ], -1)),
  2456. vue.createElementVNode("tr", null, [
  2457. _cache[11] || (_cache[11] = vue.createElementVNode("td", null, "帖子所属频道ID", -1)),
  2458. vue.createElementVNode("td", null, vue.toDisplayString(row.commentAreaInfo.channelId), 1)
  2459. ]),
  2460. vue.createElementVNode("tr", null, [
  2461. _cache[12] || (_cache[12] = vue.createElementVNode("td", null, "帖子ID", -1)),
  2462. vue.createElementVNode("td", null, vue.toDisplayString(row.commentAreaInfo.postId), 1)
  2463. ])
  2464. ], 64)) : vue.createCommentVNode("", true),
  2465. vue.createElementVNode("tr", null, [
  2466. _cache[14] || (_cache[14] = vue.createElementVNode("td", null, "点赞数", -1)),
  2467. vue.createElementVNode("td", null, vue.toDisplayString(row.likeCount), 1)
  2468. ]),
  2469. row.commentId.indexOf(".") == -1 ? (vue.openBlock(), vue.createElementBlock("tr", _hoisted_5, [
  2470. _cache[15] || (_cache[15] = vue.createElementVNode("td", null, "回复数", -1)),
  2471. vue.createElementVNode("td", null, vue.toDisplayString(row.replyCount), 1)
  2472. ])) : vue.createCommentVNode("", true),
  2473. vue.createElementVNode("tr", null, [
  2474. _cache[16] || (_cache[16] = vue.createElementVNode("td", null, "记录时间", -1)),
  2475. vue.createElementVNode("td", null, vue.toDisplayString(vue.unref(formatTimestamp)(row.recordedTime)), 1)
  2476. ]),
  2477. vue.createElementVNode("tr", null, [
  2478. _cache[17] || (_cache[17] = vue.createElementVNode("td", null, "更新时间", -1)),
  2479. vue.createElementVNode("td", null, vue.toDisplayString(vue.unref(formatTimestamp)(row.updatedTime)), 1)
  2480. ])
  2481. ])
  2482. ]),
  2483. vue.createElementVNode("details", null, [
  2484. _cache[18] || (_cache[18] = vue.createElementVNode("summary", null, "历史检查记录", -1)),
  2485. vue.createVNode(_component_el_table, {
  2486. data: row.histories,
  2487. style: { "width": "100%" }
  2488. }, {
  2489. default: vue.withCtx(() => [
  2490. vue.createVNode(_component_el_table_column, {
  2491. prop: "time",
  2492. label: "时间戳",
  2493. width: "160",
  2494. formatter: (history) => vue.unref(formatTimestamp)(history.time)
  2495. }, null, 8, ["formatter"]),
  2496. vue.createVNode(_component_el_table_column, {
  2497. prop: "state",
  2498. label: "状态",
  2499. width: "136",
  2500. formatter: (history) => vue.unref(translateState)(history.state)
  2501. }, null, 8, ["formatter"]),
  2502. vue.createVNode(_component_el_table_column, {
  2503. prop: "hotBan",
  2504. label: "热门屏蔽",
  2505. width: "120",
  2506. formatter: (history) => formatHotBan(history.hotBan)
  2507. }, null, 8, ["formatter"]),
  2508. vue.createVNode(_component_el_table_column, {
  2509. prop: "content",
  2510. label: "评论内容",
  2511. "show-overflow-tooltip": ""
  2512. }),
  2513. vue.createVNode(_component_el_table_column, { type: "expand" }, {
  2514. default: vue.withCtx(({ row: row2 }) => [
  2515. vue.createElementVNode("div", _hoisted_6, vue.toDisplayString(row2.content), 1)
  2516. ]),
  2517. _: 2
  2518. }, 1024)
  2519. ]),
  2520. _: 2
  2521. }, 1032, ["data"])
  2522. ]),
  2523. vue.createVNode(CommentActions, {
  2524. comment: row,
  2525. onDelete: ($event) => deleteCommentItem(row)
  2526. }, null, 8, ["comment", "onDelete"])
  2527. ])
  2528. ]),
  2529. _: 1
  2530. })
  2531. ]),
  2532. _: 1
  2533. }, 8, ["data"]),
  2534. vue.createElementVNode("div", _hoisted_7, [
  2535. prevTime.value ? (vue.openBlock(), vue.createBlock(_component_el_button, {
  2536. key: 0,
  2537. onClick: _cache[0] || (_cache[0] = ($event) => loadComments("prev")),
  2538. disabled: loadingComments.value
  2539. }, {
  2540. default: vue.withCtx(() => [
  2541. vue.createTextVNode("< " + vue.toDisplayString(prevTime.value == -1 ? "NOW" : vue.unref(formatTimestamp)(prevTime.value)), 1)
  2542. ]),
  2543. _: 1
  2544. }, 8, ["disabled"])) : vue.createCommentVNode("", true),
  2545. nextTime.value ? (vue.openBlock(), vue.createBlock(_component_el_button, {
  2546. key: 1,
  2547. onClick: _cache[1] || (_cache[1] = ($event) => loadComments("next")),
  2548. disabled: loadingComments.value
  2549. }, {
  2550. default: vue.withCtx(() => [
  2551. vue.createTextVNode(vue.toDisplayString(vue.unref(formatTimestamp)(nextTime.value)) + " >", 1)
  2552. ]),
  2553. _: 1
  2554. }, 8, ["disabled"])) : vue.createCommentVNode("", true)
  2555. ])
  2556. ]),
  2557. _: 1
  2558. }, 8, ["modelValue"])
  2559. ]);
  2560. };
  2561. }
  2562. };
  2563. const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-ff4696c9"]]);
  2564. const originalFetch = _unsafeWindow.fetch;
  2565. var authorizationCache = null;
  2566. var contextCache = null;
  2567. var trueLoaded = false;
  2568. var db = null;
  2569. const checkingCommentIdSet = /* @__PURE__ */ new Set();
  2570. function waitForElement(observeSelector, targetSelector) {
  2571. return new Promise((resolve) => {
  2572. const parent = document.querySelector(observeSelector);
  2573. if (!parent) return;
  2574. const found = parent.querySelector(targetSelector);
  2575. if (found) {
  2576. resolve(found);
  2577. return;
  2578. }
  2579. const observer = new MutationObserver(() => {
  2580. const el = parent.querySelector(targetSelector);
  2581. if (el) {
  2582. observer.disconnect();
  2583. resolve(el);
  2584. }
  2585. });
  2586. observer.observe(parent, { childList: true, subtree: true });
  2587. });
  2588. }
  2589. async function findComment(commentRecord, isLogin = true) {
  2590. let continuation;
  2591. let requestUrl;
  2592. if (commentRecord.webPageType == "WEB_PAGE_TYPE_WATCH") {
  2593. let payload = {
  2594. uField3: 6,
  2595. commentAreaWrapper: {
  2596. videoId: commentRecord.commentAreaInfo.videoId
  2597. },
  2598. mainCommentRequest: {
  2599. sectionIdentifier: "comments-section",
  2600. commentParameters: {
  2601. videoId: commentRecord.commentAreaInfo.videoId,
  2602. targetCommentId: commentRecord.commentId
  2603. }
  2604. }
  2605. };
  2606. let encoded = NextContinuation.encode(payload);
  2607. let buffer = encoded.finish();
  2608. continuation = btoa(String.fromCharCode(...buffer));
  2609. continuation = standardBase64ToUrlSafe(continuation);
  2610. requestUrl = "https://www.youtube.com/youtubei/v1/next?prettyPrint=false";
  2611. } else if (commentRecord.webPageType == "WEB_PAGE_TYPE_BROWSE") {
  2612. let payload = {
  2613. description: "community",
  2614. mainCommentRequest: {
  2615. sectionIdentifier: "comments-section",
  2616. commentParameters: {
  2617. channelId: commentRecord.commentAreaInfo.channelId,
  2618. postId: commentRecord.commentAreaInfo.postId,
  2619. targetCommentId: commentRecord.commentId
  2620. }
  2621. }
  2622. };
  2623. let encoded = BrowserCommentListContinuation.encode(payload);
  2624. let buffer = encoded.finish();
  2625. continuation = btoa(String.fromCharCode(...buffer));
  2626. continuation = standardBase64ToUrlSafe(continuation);
  2627. payload = {
  2628. request: {
  2629. description: "FEcomment_post_detail_page_web_top_level",
  2630. continuationBase64: continuation
  2631. }
  2632. };
  2633. encoded = BrowserContinuation.encode(payload);
  2634. buffer = encoded.finish();
  2635. continuation = btoa(String.fromCharCode(...buffer));
  2636. continuation = standardBase64ToUrlSafe(continuation);
  2637. requestUrl = "https://www.youtube.com/youtubei/v1/browse?prettyPrint=false";
  2638. } else {
  2639. throw new Error("Unsupported webPageType : " + commentRecord.webPageType);
  2640. }
  2641. let data = {
  2642. context: contextCache,
  2643. continuation
  2644. };
  2645. let headers = {};
  2646. if (isLogin) {
  2647. headers.authorization = authorizationCache;
  2648. }
  2649. let options = {
  2650. method: "POST",
  2651. body: JSON.stringify(data),
  2652. headers
  2653. };
  2654. let response = await (await originalFetch(requestUrl, options)).json();
  2655. let loggedOut = response.responseContext.mainAppWebResponseContext.loggedOut;
  2656. if (loggedOut == isLogin) {
  2657. console.warn("登录(不可用)状态不符,需要的:" + isLogin + " API返回的:" + !loggedOut);
  2658. }
  2659. if (!response.frameworkUpdates) {
  2660. throw new Error("COMMENT_AREA_CLOSED");
  2661. }
  2662. let mutations = response.frameworkUpdates.entityBatchUpdate.mutations;
  2663. for (let i = 0; i < mutations.length; i++) {
  2664. let mutation = mutations[i];
  2665. if (mutation.payload.commentEntityPayload) {
  2666. let entity = mutation.payload.commentEntityPayload;
  2667. let commentId = entity.properties.commentId;
  2668. if (commentId == commentRecord.commentId) {
  2669. let likeCount = parseInt(entity.toolbar.likeCountNotliked);
  2670. likeCount = likeCount ? likeCount : 0;
  2671. let replyCount = parseInt(entity.toolbar.replyCount);
  2672. replyCount = replyCount ? replyCount : 0;
  2673. return {
  2674. content: entity.properties.content.content,
  2675. commentId,
  2676. likeCount,
  2677. replyCount
  2678. };
  2679. }
  2680. }
  2681. }
  2682. }
  2683. async function insertComment() {
  2684. }
  2685. async function updateComment() {
  2686. }
  2687. async function selectComment() {
  2688. }
  2689. async function deleteComment() {
  2690. }
  2691. function appendHistory(commentRecord) {
  2692. let histories = commentRecord.histories;
  2693. let needPush = false;
  2694. if (histories.length == 0) {
  2695. needPush = true;
  2696. } else {
  2697. let lastHistory = histories[histories.length - 1];
  2698. needPush = lastHistory.state != commentRecord.currentState || lastHistory.content != commentRecord.content || lastHistory.hotBan != commentRecord.hotBan;
  2699. }
  2700. if (needPush) {
  2701. histories.push({
  2702. time: commentRecord.updatedTime,
  2703. content: commentRecord.content,
  2704. state: commentRecord.currentState,
  2705. hotBan: commentRecord.hotBan
  2706. });
  2707. }
  2708. }
  2709. function updateRecord(commentRecord, state, result) {
  2710. commentRecord.updatedTime = Date.now();
  2711. if (state) {
  2712. commentRecord.currentState = state;
  2713. }
  2714. if (result) {
  2715. commentRecord.likeCount = result.likeCount;
  2716. commentRecord.replyCount = result.replyCount;
  2717. commentRecord.content = result.content;
  2718. }
  2719. appendHistory(commentRecord);
  2720. updateComment(commentRecord);
  2721. }
  2722. async function check(commentRecord) {
  2723. let loggedOutResult = await findComment(commentRecord, false);
  2724. if (loggedOutResult) {
  2725. updateRecord(commentRecord, "NORMAL", loggedOutResult);
  2726. return;
  2727. }
  2728. let loggedInResult = await findComment(commentRecord, true);
  2729. if (loggedInResult) {
  2730. updateRecord(commentRecord, "SHADOW_BAN", loggedInResult);
  2731. } else {
  2732. updateRecord(commentRecord, "DELETED");
  2733. }
  2734. }
  2735. async function toCheck(commentRecord) {
  2736. checkingCommentIdSet.add(commentRecord.commentId);
  2737. let selector;
  2738. if (window.location.pathname.startsWith("/channel")) {
  2739. selector = "ytd-item-section-renderer#sections";
  2740. } else {
  2741. selector = "#comments";
  2742. }
  2743. let element = (await waitForElement(selector, `a[href='${commentRecord.url}']`)).parentNode.parentNode.parentNode.parentNode;
  2744. let div = document.createElement("div");
  2745. div.style.marginTop = "8px";
  2746. div.id = "checker";
  2747. element.append(div);
  2748. let app = vue.createApp(CommentChecker);
  2749. app.use(ElementPlus);
  2750. app.provide("check", check);
  2751. app.provide("hotBanCheck", hotBanCheck);
  2752. app.provide("commentRecord", commentRecord);
  2753. app.provide("interval", 5);
  2754. app.provide("onUnblock", (commentRecord2) => {
  2755. checkingCommentIdSet.delete(commentRecord2.commentId);
  2756. });
  2757. app.provide("onClose", (commentRecord2) => {
  2758. checkingCommentIdSet.delete(commentRecord2.commentId);
  2759. console.log("评论检查完成", commentRecord2);
  2760. div.remove();
  2761. });
  2762. app.mount(div);
  2763. }
  2764. function createCommentListRequest(commentRecord, isLatestSort) {
  2765. let api;
  2766. let continuation;
  2767. if (commentRecord.webPageType == "WEB_PAGE_TYPE_WATCH") {
  2768. api = "https://www.youtube.com/youtubei/v1/next?prettyPrint=false";
  2769. if (commentRecord.commentId.indexOf(".") != -1) {
  2770. let rootCommentId = commentRecord.commentId.split(".")[0];
  2771. let payload = {
  2772. uField3: 6,
  2773. commentAreaWrapper: {
  2774. videoId: commentRecord.commentAreaInfo.videoId
  2775. },
  2776. mainCommentRequest: {
  2777. sectionIdentifier: `comment-replies-item-${rootCommentId}`,
  2778. commentReplyParameters: {
  2779. rootCommentId,
  2780. channelId: commentRecord.commentAreaInfo.channelId,
  2781. videoId: commentRecord.commentAreaInfo.videoId,
  2782. pageSize: 10,
  2783. sortParam: {
  2784. sortType: 1
  2785. }
  2786. }
  2787. }
  2788. };
  2789. let encoded = NextContinuation.encode(payload);
  2790. let buffer = encoded.finish();
  2791. continuation = btoa(String.fromCharCode(...buffer));
  2792. continuation = standardBase64ToUrlSafe(continuation);
  2793. } else {
  2794. let payload = {
  2795. uField3: 6,
  2796. commentAreaWrapper: {
  2797. videoId: commentRecord.commentAreaInfo.videoId
  2798. },
  2799. mainCommentRequest: {
  2800. sectionIdentifier: "comments-section",
  2801. commentParameters: {
  2802. videoId: commentRecord.commentAreaInfo.videoId,
  2803. sortType: 0
  2804. }
  2805. }
  2806. };
  2807. let encoded = NextContinuation.encode(payload);
  2808. let buffer = encoded.finish();
  2809. continuation = btoa(String.fromCharCode(...buffer));
  2810. continuation = standardBase64ToUrlSafe(continuation);
  2811. }
  2812. } else if (commentRecord.webPageType == "WEB_PAGE_TYPE_BROWSE") {
  2813. api = "https://www.youtube.com/youtubei/v1/browse?prettyPrint=false";
  2814. if (commentRecord.commentId.indexOf(".") != -1) {
  2815. let rootCommentId = commentRecord.commentId.split(".")[0];
  2816. let payload = {
  2817. description: "community",
  2818. mainCommentRequest: {
  2819. sectionIdentifier: `comment-replies-item-${rootCommentId}`,
  2820. commentReplyParameters: {
  2821. rootCommentId,
  2822. channelId: commentRecord.commentAreaInfo.channelId,
  2823. postId: commentRecord.commentAreaInfo.postId,
  2824. pageSize: 10,
  2825. sortParam: {
  2826. sortType: 1
  2827. }
  2828. }
  2829. }
  2830. };
  2831. let encoded = BrowserCommentListContinuation.encode(payload);
  2832. let buffer = encoded.finish();
  2833. continuation = btoa(String.fromCharCode(...buffer));
  2834. continuation = standardBase64ToUrlSafe(continuation);
  2835. payload = {
  2836. request: {
  2837. description: "FEcomment_post_detail_page_web_replies_page",
  2838. continuationBase64: continuation
  2839. }
  2840. };
  2841. encoded = BrowserContinuation.encode(payload);
  2842. buffer = encoded.finish();
  2843. continuation = btoa(String.fromCharCode(...buffer));
  2844. continuation = standardBase64ToUrlSafe(continuation);
  2845. } else {
  2846. let payload = {
  2847. description: "community",
  2848. mainCommentRequest: {
  2849. sectionIdentifier: "comments-section",
  2850. commentParameters: {
  2851. channelId: commentRecord.commentAreaInfo.channelId,
  2852. postId: commentRecord.commentAreaInfo.postId,
  2853. sortType: 0
  2854. }
  2855. }
  2856. };
  2857. let encoded = BrowserCommentListContinuation.encode(payload);
  2858. let buffer = encoded.finish();
  2859. continuation = btoa(String.fromCharCode(...buffer));
  2860. continuation = standardBase64ToUrlSafe(continuation);
  2861. payload = {
  2862. request: {
  2863. description: "FEcomment_post_detail_page_web_top_level",
  2864. continuationBase64: continuation
  2865. }
  2866. };
  2867. encoded = BrowserContinuation.encode(payload);
  2868. buffer = encoded.finish();
  2869. continuation = btoa(String.fromCharCode(...buffer));
  2870. continuation = standardBase64ToUrlSafe(continuation);
  2871. }
  2872. }
  2873. return { api, continuation };
  2874. }
  2875. async function hotBanCheck(commentRecord, observer, controller) {
  2876. var _a, _b, _c, _d, _e;
  2877. if (!observer) {
  2878. observer = {
  2879. onCountChange(c, p) {
  2880. }
  2881. };
  2882. }
  2883. if (!controller) {
  2884. controller = {
  2885. isCancelled: false
  2886. };
  2887. }
  2888. let pageCpunt = 0;
  2889. let commentCount = 0;
  2890. let { api, continuation } = createCommentListRequest(commentRecord);
  2891. while (continuation) {
  2892. if (controller.isCancelled) {
  2893. return false;
  2894. }
  2895. let data = {
  2896. context: contextCache,
  2897. continuation
  2898. };
  2899. let options = {
  2900. method: "POST",
  2901. body: JSON.stringify(data)
  2902. };
  2903. let response = await (await originalFetch(api, options)).json();
  2904. pageCpunt++;
  2905. if (!response.frameworkUpdates) {
  2906. commentRecord.hotBan = true;
  2907. updateRecord(commentRecord);
  2908. return true;
  2909. }
  2910. for (let mutation of response.frameworkUpdates.entityBatchUpdate.mutations) {
  2911. let entity = mutation.payload.commentEntityPayload;
  2912. if (entity) {
  2913. let commentId = entity.properties.commentId;
  2914. commentCount++;
  2915. observer.onCountChange(commentCount, pageCpunt);
  2916. if (commentId == commentRecord.commentId) {
  2917. commentRecord.hotBan = false;
  2918. updateRecord(commentRecord);
  2919. return true;
  2920. }
  2921. }
  2922. }
  2923. continuation = null;
  2924. for (const endpoint of response.onResponseReceivedEndpoints) {
  2925. const items = ((_a = endpoint.appendContinuationItemsAction) == null ? void 0 : _a.continuationItems) || ((_b = endpoint.reloadContinuationItemsCommand) == null ? void 0 : _b.continuationItems);
  2926. if (!items) continue;
  2927. for (const item of items) {
  2928. const token = (_e = (_d = (_c = item.continuationItemRenderer) == null ? void 0 : _c.continuationEndpoint) == null ? void 0 : _d.continuationCommand) == null ? void 0 : _e.token;
  2929. if (token) {
  2930. continuation = token;
  2931. break;
  2932. }
  2933. }
  2934. if (continuation) break;
  2935. }
  2936. }
  2937. commentRecord.hotBan = true;
  2938. updateRecord(commentRecord);
  2939. return true;
  2940. }
  2941. async function handlerYoutubei(request) {
  2942. let requsetClone = request.clone();
  2943. let requestBody = await requsetClone.json();
  2944. if (requestBody && requestBody.context) {
  2945. contextCache = requestBody.context;
  2946. if (!trueLoaded) {
  2947. console.log("fetch已成功劫持");
  2948. _GM_registerMenuCommand("✅ 脚本已完全加载");
  2949. trueLoaded = true;
  2950. }
  2951. }
  2952. if (request.url.startsWith("https://www.youtube.com/youtubei/v1/comment/create_comment")) {
  2953. let response = await originalFetch(request);
  2954. if (response.status != 200) {
  2955. return response;
  2956. }
  2957. let responseClone = response.clone();
  2958. try {
  2959. let json = await responseClone.json();
  2960. if (json.frameworkUpdates.entityBatchUpdate.mutations.length == 1) {
  2961. return response;
  2962. }
  2963. let entity = json.frameworkUpdates.entityBatchUpdate.mutations[0].payload.commentEntityPayload;
  2964. let innertubeCommand = json.frameworkUpdates.entityBatchUpdate.mutations[1].payload.commentSurfaceEntityPayload.publishedTimeCommand.innertubeCommand;
  2965. let webCommandMetadata = innertubeCommand.commandMetadata.webCommandMetadata;
  2966. let webPageType = webCommandMetadata.webPageType;
  2967. let url = webCommandMetadata.url;
  2968. let commentAreaInfo = {};
  2969. if (webPageType == "WEB_PAGE_TYPE_WATCH") {
  2970. commentAreaInfo.videoId = innertubeCommand.watchEndpoint.videoId;
  2971. commentAreaInfo.channelId = json.actions[0].runAttestationCommand.ids[2].externalChannelId;
  2972. } else if (webPageType == "WEB_PAGE_TYPE_BROWSE") {
  2973. commentAreaInfo.channelId = url.split("/")[2];
  2974. commentAreaInfo.postId = createUrl(url).searchParams.get("lb");
  2975. }
  2976. let author = entity.author;
  2977. let properties = entity.properties;
  2978. let content = properties.content.content;
  2979. let recordedTime = Date.now();
  2980. let commentRecord = {
  2981. //评论ID
  2982. commentId: properties.commentId,
  2983. //@发送者
  2984. displayName: author.displayName,
  2985. //频道ID,类似UID
  2986. channelId: author.channelId,
  2987. //评论内容
  2988. content,
  2989. //webPageType 评论区类型 视频 or 帖子
  2990. webPageType,
  2991. //URL 点击可跳转“所要查看的评论” 例如 /watch?v=${视频ID}&lc=${评论ID}
  2992. url,
  2993. //评论区信息,视频{视频ID},帖子{频道ID,帖子ID}
  2994. commentAreaInfo,
  2995. //当前状态 默认从SHADOW_BAN开始,到NORMAL或DELETED
  2996. currentState: "NOT_CHECK",
  2997. //是否在热门排序中被禁止显示(搜索整个热门评论区来检查),前提条件currentState = "NORMAL",值:null | false | true
  2998. //此状态不会因为修改评论内容而解除,但会因为修改评论内容而赋予
  2999. hotBan: null,
  3000. //历史记录,时间 内容 状态 是否热门屏蔽
  3001. histories: [],
  3002. //{ time: recordedTime, state: "SHADOW_BAN", content, hotBan: null }
  3003. //点赞与回复数,不记录历史
  3004. likeCount: 0,
  3005. replyCount: 0,
  3006. //记录的时间,用的是系统当前时间,约等于评论的发布时间,API里的publishedTime距离发布时间戳多久的Shit不是时间戳(PS:YouTube开放API可查询具体发布时间戳)
  3007. recordedTime,
  3008. //更新时间
  3009. updatedTime: recordedTime,
  3010. //是否是用户自己执行的删除?用于区分是被系统删的还是自己删除。state为"DELETED"时该属性为才有意义。(劫持删除评论请求时记录)
  3011. isUserDelete: false
  3012. };
  3013. console.log(commentRecord);
  3014. insertComment(commentRecord);
  3015. console.log(createUrl(url).href);
  3016. toCheck(commentRecord);
  3017. } catch (err) {
  3018. console.error(err);
  3019. throw err;
  3020. }
  3021. return response;
  3022. } else if (request.url.startsWith("https://www.youtube.com/youtubei/v1/comment/perform_comment_action")) {
  3023. let actionBase64 = urlSafeBase64ToStandard(requestBody.actions[0]);
  3024. let actionInfo = CommentAction.decode(Uint8Array.from(atob(actionBase64), (c) => c.charCodeAt(0)));
  3025. if (actionInfo.action == 6) {
  3026. if (checkingCommentIdSet.has(actionInfo.commentId)) {
  3027. alert("现在不能删除该评论,因为评论还未完成检查,请先完成检查!");
  3028. const responseBody = {
  3029. "error": {
  3030. "code": 403,
  3031. "message": "Can't delete comment now",
  3032. "errors": [
  3033. {
  3034. "message": "Can't delete comment now",
  3035. "domain": "global",
  3036. "reason": "forbidden"
  3037. }
  3038. ],
  3039. "status": "FORBIDDEN"
  3040. }
  3041. };
  3042. return new Response(JSON.stringify(responseBody), {
  3043. status: 403,
  3044. headers: {
  3045. "Content-Type": "application/json"
  3046. }
  3047. });
  3048. } else {
  3049. let response = await originalFetch(request);
  3050. let responseBody = await response.clone().json();
  3051. if (responseBody.actions && responseBody.actions[0].removeCommentAction.actionResult.status == "STATUS_SUCCEEDED") {
  3052. let commentRecord = await selectComment(actionInfo.commentId);
  3053. if (commentRecord) {
  3054. commentRecord.isUserDelete = true;
  3055. updateRecord(commentRecord, "DELETED");
  3056. }
  3057. }
  3058. return response;
  3059. }
  3060. }
  3061. } else if (request.url.startsWith("https://www.youtube.com/youtubei/v1/comment/update_comment")) {
  3062. let updateCommentParams = urlSafeBase64ToStandard(requestBody.updateCommentParams);
  3063. let decodedParams = UpdateCommentParams.decode(Uint8Array.from(atob(updateCommentParams), (c) => c.charCodeAt(0)));
  3064. if (checkingCommentIdSet.has(decodedParams.commentId)) {
  3065. alert("现在不能修改该评论,因为评论还未完成检查,请先完成检查!");
  3066. const responseBody2 = {
  3067. "error": {
  3068. "code": 403,
  3069. "message": "Can't edit comment now",
  3070. "errors": [
  3071. {
  3072. "message": "Can't edit comment now",
  3073. "domain": "global",
  3074. "reason": "forbidden"
  3075. }
  3076. ],
  3077. "status": "FORBIDDEN"
  3078. }
  3079. };
  3080. return new Response(JSON.stringify(responseBody2), {
  3081. status: 403,
  3082. headers: {
  3083. "Content-Type": "application/json"
  3084. }
  3085. });
  3086. }
  3087. let response = await originalFetch(request);
  3088. let responseBody = await response.clone().json();
  3089. if (responseBody.actions && responseBody.actions[0].updateCommentAction.actionResult.status == "STATUS_SUCCEEDED") {
  3090. let commentRecord = await selectComment(decodedParams.commentId);
  3091. if (commentRecord) {
  3092. commentRecord.content = requestBody.commentText;
  3093. commentRecord.currentState = "NOT_CHECK";
  3094. commentRecord.hotBan = null;
  3095. updateRecord(commentRecord);
  3096. }
  3097. }
  3098. return response;
  3099. }
  3100. return await originalFetch(request);
  3101. }
  3102. const fetchProxy = function(resource, options) {
  3103. if (typeof resource == "string") {
  3104. return originalFetch(resource, options);
  3105. }
  3106. if (!resource.url.startsWith("https://www.youtube.com/youtubei/")) {
  3107. return originalFetch(resource, options);
  3108. }
  3109. let auth = resource.headers.get("Authorization");
  3110. if (auth) {
  3111. authorizationCache = auth;
  3112. if (resource.method != "POST") {
  3113. return originalFetch(resource);
  3114. } else {
  3115. return handlerYoutubei(resource);
  3116. }
  3117. }
  3118. return originalFetch(resource, options);
  3119. };
  3120. try {
  3121. _unsafeWindow.fetch = fetchProxy;
  3122. } catch (err) {
  3123. console.warn("替换 unsafeWindow.fetch 失败!相关信息:", err, Object.getOwnPropertyDescriptor(_unsafeWindow, "fetch"));
  3124. if (confirm("fetch已被提前锁定,替换失败,YouTube发评反诈可能无法正常工作。\n你可以安装本项目的 Define property blocker 插件来反制锁定。\n\n点击“确定”前往项目地址,点击“取消”忽略。")) {
  3125. window.location.href = "https://github.com/freedom-introvert/youtube-comment-censor-detector";
  3126. }
  3127. }
  3128. const _createElement = Document.prototype.createElement;
  3129. Document.prototype.createElement = function(tagName, ...args) {
  3130. const el = _createElement.call(this, tagName, ...args);
  3131. if (tagName.toLowerCase() === "iframe") {
  3132. el.addEventListener("load", () => {
  3133. var _a;
  3134. try {
  3135. const fetchFromIframe = (_a = el.contentWindow) == null ? void 0 : _a.fetch;
  3136. if (fetchFromIframe) {
  3137. el.contentWindow.fetch = fetchProxy;
  3138. console.log("已替换iframe window的fetch", el);
  3139. }
  3140. } catch (e) {
  3141. console.log("未替换该iframe的fetch", el, e);
  3142. }
  3143. });
  3144. }
  3145. return el;
  3146. };
  3147. function openDB() {
  3148. return new Promise((resolve, reject) => {
  3149. let request = indexedDB.open("YT-CCD", 1);
  3150. request.onerror = (event) => {
  3151. reject(event);
  3152. };
  3153. request.onsuccess = (event) => {
  3154. resolve(event.target.result);
  3155. };
  3156. request.onupgradeneeded = (event) => {
  3157. let db2 = event.target.result;
  3158. let objectStore = db2.createObjectStore("comments", { keyPath: "commentId" });
  3159. objectStore.createIndex("recordedTime", "recordedTime", { unique: false });
  3160. };
  3161. });
  3162. }
  3163. async function init() {
  3164. try {
  3165. db = await openDB();
  3166. insertComment = function(comment) {
  3167. return new Promise((resolve, reject) => {
  3168. let request = db.transaction("comments", "readwrite").objectStore("comments").add(comment);
  3169. request.onsuccess = (event) => {
  3170. resolve(event);
  3171. };
  3172. request.onerror = (event) => {
  3173. reject(event);
  3174. };
  3175. });
  3176. };
  3177. updateComment = function(comment) {
  3178. return new Promise((resolve, reject) => {
  3179. let request = db.transaction("comments", "readwrite").objectStore("comments").put(vue.toRaw(comment));
  3180. request.onsuccess = (event) => {
  3181. resolve(event);
  3182. };
  3183. request.onerror = (event) => {
  3184. reject(event);
  3185. };
  3186. });
  3187. };
  3188. selectComment = function(commentId) {
  3189. return new Promise((resolve, reject) => {
  3190. let request = db.transaction("comments").objectStore("comments").get(commentId);
  3191. request.onsuccess = (event) => {
  3192. resolve(request.result);
  3193. };
  3194. request.onerror = (event) => {
  3195. reject(event);
  3196. };
  3197. });
  3198. };
  3199. deleteComment = function(commentId) {
  3200. return new Promise((resolve, reject) => {
  3201. let request = db.transaction("comments", "readwrite").objectStore("comments").delete(commentId);
  3202. request.onsuccess = (event) => {
  3203. resolve(request.result);
  3204. };
  3205. request.onerror = (event) => {
  3206. reject(event);
  3207. };
  3208. });
  3209. };
  3210. } catch (err) {
  3211. console.log("indexedDB数据库打开失败,评论历史记录相关功能已禁用,错误信息:", err);
  3212. }
  3213. const menuListener = {
  3214. onOpenHistory: () => {
  3215. alert("脚本正在初始化,请稍后……");
  3216. }
  3217. };
  3218. _GM_registerMenuCommand("🧾 历史评论记录", () => {
  3219. menuListener.onOpenHistory();
  3220. });
  3221. const div = document.createElement("div");
  3222. div.id = "yt-ccd";
  3223. div.style.position = "absolute";
  3224. document.body.append(div);
  3225. let app = vue.createApp(App);
  3226. app.use(ElementPlus);
  3227. app.provide("menuListener", menuListener);
  3228. app.provide("db", db);
  3229. app.provide("check", check);
  3230. app.provide("hotBanCheck", hotBanCheck);
  3231. app.provide("deleteComment", deleteComment);
  3232. app.mount(div);
  3233. }
  3234. window.addEventListener("load", () => {
  3235. init().then(() => {
  3236. console.log("YouTube反诈加载完成");
  3237. }).catch((err) => {
  3238. console.error("YouTube反诈加载失败", err);
  3239. });
  3240. });
  3241.  
  3242. })(Vue, ElementPlus);

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址