// ==UserScript==
// @name youtube-comment-censor-detector
// @name:zh-CN YouTube发评反诈
// @name:zh-TW YouTube發評反詐
// @namespace npm/vite-plugin-monkey
// @version 2.3.5
// @author freedom-introvert
// @description A real-time comment checker, Fuck YouTube’s opaque comment censorship
// @description:zh-CN Fuck YouTube版“阿瓦隆系统”,实时检查评论状态,防止评论被儿童偷偷误食你还被蒙在鼓里
// @description:zh-TW Fuck YouTube版“阿瓦隆系統”,即時檢查評論狀態,防止評論被兒童偷偷誤食你還被蒙在鼓裡
// @license GPL
// @icon https://raw.githubusercontent.com/freedom-introvert/youtube-comment-censor-detector/refs/heads/main/logo/logo_256x256.avif
// @match *://*.youtube.com/*
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.global.prod.js
// @require https://unpkg.com/vue-demi@latest/lib/index.iife.js
// @require data:application/javascript,window.Vue%3DVue%3B
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/index.full.min.js
// @resource element-plus/dist/index.css https://cdn.jsdelivr.net/npm/[email protected]/dist/index.css
// @grant GM_addStyle
// @grant GM_getResourceText
// @grant GM_registerMenuCommand
// @grant unsafeWindow
// @run-at document-start
// ==/UserScript==
(a=>{if(typeof GM_addStyle=="function"){GM_addStyle(a);return}const e=document.createElement("style");e.textContent=a,document.head.append(e)})(" .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}.pagination[data-v-80f074da]{margin-top:6px}.detail[data-v-80f074da]{margin-left:10px}.info-table td[data-v-80f074da]:nth-child(1){white-space:nowrap;vertical-align:top}.info-table td[data-v-80f074da]:nth-child(2){padding-left:16px}.comment-content[data-v-80f074da]{white-space:break-spaces}summary[data-v-80f074da]{cursor:pointer;margin-top:2px;-webkit-user-select:none;user-select:none}.locate-link[data-v-80f074da]{width:100%}[data-v-80f074da] .locate-link>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.post-locate-link[data-v-80f074da]{font-size:10px}.youtube-comment[data-v-2a518d4b]{display:flex;align-items:flex-start;padding:16px;gap:16px;font-family:Roboto,sans-serif}.avatar-container[data-v-2a518d4b]{flex-shrink:0}.avatar[data-v-2a518d4b]{width:40px;height:40px;border-radius:50%;object-fit:cover}.comment-content[data-v-2a518d4b]{flex:1;display:flex;flex-direction:column;gap:4px}.comment-header[data-v-2a518d4b]{display:flex;align-items:center;gap:8px}.author-name[data-v-2a518d4b]{font-size:13px;font-weight:500;color:#000;text-decoration:none;transition:color .2s ease}.published-at[data-v-2a518d4b]{font-size:12px;color:#aaa}.comment-text[data-v-2a518d4b]{font-size:14px;line-height:1.5;white-space:pre-wrap;word-break:break-word;margin:0}.comment-actions[data-v-2a518d4b]{display:flex;align-items:center;gap:8px;margin-top:8px}.button[data-v-2a518d4b]{display:flex;align-items:center;gap:4px;background-color:transparent;border:none;cursor:pointer;color:#aaa;font-size:12px;transition:color .2s ease;text-decoration:none;padding:1px 6px}.button[data-v-2a518d4b]:hover{color:#f1f1f1}.icon[data-v-2a518d4b]{width:16px;height:16px;fill:currentColor}.action-text[data-v-2a518d4b]{line-height:100%}.hot-ban-comment-searcher[data-v-b5a0c87e],.not-comment-section[data-v-b5a0c87e]{height:100%}.warning[data-v-b5a0c87e]{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%}.search-progress[data-v-b5a0c87e]{display:flex;height:100%;flex-direction:column;justify-content:center;align-items:center;gap:15px}.warning-title[data-v-b5a0c87e]{margin-bottom:4px}.warning-text[data-v-b5a0c87e]{text-align:center;max-width:500px}.warning-divider[data-v-b5a0c87e]{max-width:800px}.el-progress[data-v-b5a0c87e]{width:300px}.footer[data-v-b5a0c87e]{display:flex;flex-direction:column;align-items:center}[data-v-1d7cd9ea] .dialog-body{height:calc(100% - 40px);display:flex;flex-direction:column} ");
(function (vue, ElementPlus) {
'use strict';
function sleep(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, time);
});
}
function urlSafeBase64ToStandard(urlSafeBase64) {
let standardBase64 = urlSafeBase64.replace(/%3D/g, "=").replace(/-/g, "+").replace(/_/g, "/");
return standardBase64;
}
function standardBase64ToUrlSafe(standardBase64) {
let urlSafeBase64 = standardBase64.replace(/=/g, "%3D").replace(/\+/g, "-").replace(/\//g, "_");
return urlSafeBase64;
}
function createUrl(path) {
if (path) {
return new URL(new URL(window.location.href).origin + path);
}
return new URL(window.location.href);
}
function formatSecondsToMMSS(seconds) {
const sec = parseInt(seconds, 10);
const minutes = Math.floor(sec / 60);
const remainingSeconds = sec % 60;
const formattedMinutes = String(minutes).padStart(2, "0");
const formattedSeconds = String(remainingSeconds).padStart(2, "0");
return `${formattedMinutes}:${formattedSeconds}`;
}
function formatTimestamp(timestamp) {
if (!timestamp) {
return "--:--:--";
}
const date = new Date(timestamp);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
const hours = String(date.getHours()).padStart(2, "0");
const minutes = String(date.getMinutes()).padStart(2, "0");
const seconds = String(date.getSeconds()).padStart(2, "0");
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
function translateState(state) {
switch (state) {
case "NORMAL":
return "正常";
case "DELETED":
return "已删除";
case "SHADOW_BAN":
return "仅自己可见";
case "NOT_CHECK":
return "还未检查";
}
}
function findValueInSingleEntryArray(data, key) {
for (const item of data) {
if (item.hasOwnProperty(key)) {
return item[key];
}
}
return void 0;
}
const _export_sfc = (sfc, props) => {
const target = sfc.__vccOpts || sfc;
for (const [key, val] of props) {
target[key] = val;
}
return target;
};
const _hoisted_1$4 = { class: "title" };
const _hoisted_2$4 = { class: "message" };
const _hoisted_3$4 = { key: 0 };
const _hoisted_4$4 = { class: "message" };
const _hoisted_5$3 = { class: "buttons" };
const maxTimeSec = 120;
const _sfc_main$5 = {
__name: "CommentChecker",
setup(__props) {
const check2 = vue.inject("check");
const hotBanCheck2 = vue.inject("hotBanCheck");
const commentRecord = vue.inject("commentRecord");
const onClose = vue.inject("onClose");
const onUnblock = vue.inject("onUnblock");
const interval = vue.inject("interval");
const showCancelButton = vue.ref(true);
const showConfirmButton = vue.ref(false);
const showCloseButton = vue.ref(false);
const showHotBanCheckButton = vue.ref(false);
const showStopHotBanCheckButton = vue.ref(false);
const showLetMeAccessButtton = vue.ref(false);
const showHotBanChecker = vue.ref(false);
const stateClass = vue.ref("not-check");
const title = vue.ref("等待检查中……");
const message = vue.ref("");
const messageByHotCheck = vue.ref("等待检查中……");
let completed = false;
let netErr = false;
let hotBanCheckerController = {
isCancelled: false
};
let skipHotBanCheckWait = false;
const stripedFlow = vue.ref(false);
const currentTimeSec = vue.ref(0);
const percentage = vue.computed(() => {
if (currentTimeSec.value < 0 || currentTimeSec.value > maxTimeSec) {
return 100;
} else {
return currentTimeSec.value / maxTimeSec * 100;
}
});
function format() {
if (currentTimeSec.value < 0) {
return `--:-- / ${formatSecondsToMMSS(maxTimeSec)}`;
} else {
return `${formatSecondsToMMSS(currentTimeSec.value)} / ${formatSecondsToMMSS(maxTimeSec)}`;
}
}
let shown = null;
let startTime = Date.now() / 1e3;
async function startCheck() {
while (currentTimeSec.value < maxTimeSec || netErr) {
if (!netErr) {
for (let i = interval; i > 0; i--) {
message.value = "等待 " + i + "s 后检查评论状态";
await sleep(1e3);
currentTimeSec.value = Date.now() / 1e3 - startTime;
if (completed) {
onStateCheckComplete();
return;
}
}
} else {
currentTimeSec.value = Date.now() / 1e3 - startTime;
if (completed) {
onStateCheckComplete();
return;
}
}
message.value = "检查评论状态中……";
stripedFlow.value = true;
try {
await check2(commentRecord);
} catch (err) {
netErr = true;
title.value = "网络错误,获取当前状态失败";
showConfirmButton.value = false;
showCloseButton.value = true;
stripedFlow.value = false;
console.error(err);
continue;
}
netErr = false;
showCancelButton.value = false;
showCloseButton.value = false;
stripedFlow.value = false;
if (commentRecord.currentState == "NORMAL") {
title.value = "当前状态:正常";
stateClass.value = "normal";
shown = commentRecord.currentState;
} else if (commentRecord.currentState == "SHADOW_BAN") {
title.value = "当前状态:仅自己可见";
stateClass.value = "shadow-ban";
shown = commentRecord.currentState;
} else if (commentRecord.currentState == "DELETED") {
title.value = "当前状态:已被删除";
stateClass.value = "deleted";
if (shown) {
completed = true;
message.value = `不用等了,你的评论检查到的状态先从『${shown == "NORMAL" ? "正常" : "仅自己可见"}』再到删除,系统偷偷删了无疑。如果不信,你可以尝试编辑评论或添加回复来求证`;
onStateCheckComplete();
return;
}
}
showConfirmButton.value = true;
}
onStateCheckComplete();
completed = true;
message.value = "观察时间已足够,当前状态可信,检查完毕";
buttonText.value = "关闭";
}
function onStateCheckComplete() {
showConfirmButton.value = false;
showCloseButton.value = true;
if (commentRecord.currentState == "NORMAL") {
showHotBanCheckButton.value = true;
} else if (commentRecord.currentState == "DELETED") {
onUnblock(commentRecord);
}
}
startCheck();
function cancelCheck() {
completed = true;
onClose(commentRecord);
}
function confirmCurrentState() {
completed = true;
message.value = "您已确认当前状态,检查完毕";
}
function close() {
onClose(commentRecord);
}
async function checkHotBan() {
if (commentRecord.commentId.indexOf(".") == -1) {
try {
await ElementPlus.ElMessageBox.confirm(
"确认检查吗?该检查需要遍历热门评论区,请注意评论区的评论数量(总数大于3000的评论区慎重考虑)!数量太多将导致漫长的检查过程,同时频繁调用API可能会引发不可预料的后果!",
"警告",
{
confirmButtonText: "确定",
cancelButtonText: "取消"
}
);
} catch (err) {
return;
}
}
showCloseButton.value = false;
showHotBanCheckButton.value = false;
showHotBanChecker.value = true;
showStopHotBanCheckButton.value = true;
while (currentTimeSec.value < maxTimeSec && !hotBanCheckerController.isCancelled) {
messageByHotCheck.value = `为避免检查误判,检查需要等待至状态可信任时开始,剩余 ${Math.floor(maxTimeSec - currentTimeSec.value)}s`;
if (!skipHotBanCheckWait && currentTimeSec.value > 50) {
showLetMeAccessButtton.value = true;
}
if (skipHotBanCheckWait) {
break;
}
await sleep(1e3);
if (hotBanCheckerController.isCancelled) {
return;
}
currentTimeSec.value = Date.now() / 1e3 - startTime;
}
showLetMeAccessButtton.value = false;
messageByHotCheck.value = "正在重新检查评论状态……";
await check2(commentRecord);
if (commentRecord.currentState != "NORMAL") {
if (commentRecord.currentState == "SHADOW_BAN") {
title.value = "当前状态:仅自己可见";
stateClass.value = "shadow-ban";
messageByHotCheck.value = "评论已被ShadowBan,热门的屏蔽的检查已取消";
} else if (commentRecord.currentState == "DELETED") {
title.value = "当前状态:已被删除";
stateClass.value = "deleted";
messageByHotCheck.value = "评论已被删除,热门的屏蔽的检查已取消";
}
showStopHotBanCheckButton.value = false;
showCloseButton.value = true;
return;
}
messageByHotCheck.value = "评论状态正常,准备检查中……";
let observer = {
onCountChange(c, p) {
messageByHotCheck.value = `正在搜索热门列表,已搜寻至:第${c}个 第${p}页`;
}
};
if (await hotBanCheck2(commentRecord, observer, hotBanCheckerController)) {
if (commentRecord.hotBan) {
messageByHotCheck.value = "⚠ 你的评论未在热门列表找到,已被热门屏蔽,检查完成";
} else {
messageByHotCheck.value = "✔ 你的评论已在热门列表找到,没有被热门屏蔽,检查完成";
}
}
showStopHotBanCheckButton.value = false;
showCloseButton.value = true;
}
function stopHotBanCheck() {
hotBanCheckerController.isCancelled = true;
messageByHotCheck.value = "你已终止热门屏蔽的检查";
showStopHotBanCheckButton.value = false;
showCloseButton.value = true;
}
function letMeAccess() {
skipHotBanCheckWait = true;
showLetMeAccessButtton.value = false;
}
return (_ctx, _cache) => {
const _component_el_progress = vue.resolveComponent("el-progress");
return vue.openBlock(), vue.createElementBlock("div", {
class: vue.normalizeClass(["comment-checker", stateClass.value])
}, [
vue.createElementVNode("div", _hoisted_1$4, vue.toDisplayString(title.value), 1),
vue.createElementVNode("div", _hoisted_2$4, vue.toDisplayString(message.value), 1),
vue.createVNode(_component_el_progress, {
percentage: percentage.value,
striped: "",
format,
"striped-flow": stripedFlow.value
}, null, 8, ["percentage", "striped-flow"]),
showHotBanChecker.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$4, [
_cache[0] || (_cache[0] = vue.createElementVNode("div", { class: "title" }, "热门屏蔽检查", -1)),
vue.createElementVNode("div", _hoisted_4$4, vue.toDisplayString(messageByHotCheck.value), 1)
])) : vue.createCommentVNode("", true),
vue.createElementVNode("div", _hoisted_5$3, [
showCancelButton.value ? (vue.openBlock(), vue.createElementBlock("span", {
key: 0,
onClick: cancelCheck
}, "取消")) : vue.createCommentVNode("", true),
showConfirmButton.value ? (vue.openBlock(), vue.createElementBlock("span", {
key: 1,
onClick: confirmCurrentState
}, "确认当前状态")) : vue.createCommentVNode("", true),
showCloseButton.value ? (vue.openBlock(), vue.createElementBlock("span", {
key: 2,
onClick: close
}, "关闭")) : vue.createCommentVNode("", true),
showHotBanCheckButton.value ? (vue.openBlock(), vue.createElementBlock("span", {
key: 3,
onClick: checkHotBan
}, "热门屏蔽检查")) : vue.createCommentVNode("", true),
showStopHotBanCheckButton.value ? (vue.openBlock(), vue.createElementBlock("span", {
key: 4,
onClick: stopHotBanCheck
}, "终止检查")) : vue.createCommentVNode("", true),
showLetMeAccessButtton.value ? (vue.openBlock(), vue.createElementBlock("span", {
key: 5,
onClick: letMeAccess
}, "让我检查!")) : vue.createCommentVNode("", true)
])
], 2);
};
}
};
const CommentChecker = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__scopeId", "data-v-684910ce"]]);
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
var indexMinimal = {};
var minimal$1 = {};
var aspromise;
var hasRequiredAspromise;
function requireAspromise() {
if (hasRequiredAspromise) return aspromise;
hasRequiredAspromise = 1;
aspromise = asPromise;
function asPromise(fn, ctx) {
var params = new Array(arguments.length - 1), offset = 0, index = 2, pending = true;
while (index < arguments.length)
params[offset++] = arguments[index++];
return new Promise(function executor(resolve, reject) {
params[offset] = function callback(err) {
if (pending) {
pending = false;
if (err)
reject(err);
else {
var params2 = new Array(arguments.length - 1), offset2 = 0;
while (offset2 < params2.length)
params2[offset2++] = arguments[offset2];
resolve.apply(null, params2);
}
}
};
try {
fn.apply(ctx || null, params);
} catch (err) {
if (pending) {
pending = false;
reject(err);
}
}
});
}
return aspromise;
}
var base64 = {};
var hasRequiredBase64;
function requireBase64() {
if (hasRequiredBase64) return base64;
hasRequiredBase64 = 1;
(function(exports) {
var base642 = exports;
base642.length = function length(string) {
var p = string.length;
if (!p)
return 0;
var n = 0;
while (--p % 4 > 1 && string.charAt(p) === "=")
++n;
return Math.ceil(string.length * 3) / 4 - n;
};
var b64 = new Array(64);
var s64 = new Array(123);
for (var i = 0; i < 64; )
s64[b64[i] = i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i - 59 | 43] = i++;
base642.encode = function encode(buffer, start, end) {
var parts = null, chunk = [];
var i2 = 0, j = 0, t;
while (start < end) {
var b = buffer[start++];
switch (j) {
case 0:
chunk[i2++] = b64[b >> 2];
t = (b & 3) << 4;
j = 1;
break;
case 1:
chunk[i2++] = b64[t | b >> 4];
t = (b & 15) << 2;
j = 2;
break;
case 2:
chunk[i2++] = b64[t | b >> 6];
chunk[i2++] = b64[b & 63];
j = 0;
break;
}
if (i2 > 8191) {
(parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));
i2 = 0;
}
}
if (j) {
chunk[i2++] = b64[t];
chunk[i2++] = 61;
if (j === 1)
chunk[i2++] = 61;
}
if (parts) {
if (i2)
parts.push(String.fromCharCode.apply(String, chunk.slice(0, i2)));
return parts.join("");
}
return String.fromCharCode.apply(String, chunk.slice(0, i2));
};
var invalidEncoding = "invalid encoding";
base642.decode = function decode(string, buffer, offset) {
var start = offset;
var j = 0, t;
for (var i2 = 0; i2 < string.length; ) {
var c = string.charCodeAt(i2++);
if (c === 61 && j > 1)
break;
if ((c = s64[c]) === void 0)
throw Error(invalidEncoding);
switch (j) {
case 0:
t = c;
j = 1;
break;
case 1:
buffer[offset++] = t << 2 | (c & 48) >> 4;
t = c;
j = 2;
break;
case 2:
buffer[offset++] = (t & 15) << 4 | (c & 60) >> 2;
t = c;
j = 3;
break;
case 3:
buffer[offset++] = (t & 3) << 6 | c;
j = 0;
break;
}
}
if (j === 1)
throw Error(invalidEncoding);
return offset - start;
};
base642.test = function test(string) {
return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(string);
};
})(base64);
return base64;
}
var eventemitter;
var hasRequiredEventemitter;
function requireEventemitter() {
if (hasRequiredEventemitter) return eventemitter;
hasRequiredEventemitter = 1;
eventemitter = EventEmitter;
function EventEmitter() {
this._listeners = {};
}
EventEmitter.prototype.on = function on(evt, fn, ctx) {
(this._listeners[evt] || (this._listeners[evt] = [])).push({
fn,
ctx: ctx || this
});
return this;
};
EventEmitter.prototype.off = function off(evt, fn) {
if (evt === void 0)
this._listeners = {};
else {
if (fn === void 0)
this._listeners[evt] = [];
else {
var listeners = this._listeners[evt];
for (var i = 0; i < listeners.length; )
if (listeners[i].fn === fn)
listeners.splice(i, 1);
else
++i;
}
}
return this;
};
EventEmitter.prototype.emit = function emit(evt) {
var listeners = this._listeners[evt];
if (listeners) {
var args = [], i = 1;
for (; i < arguments.length; )
args.push(arguments[i++]);
for (i = 0; i < listeners.length; )
listeners[i].fn.apply(listeners[i++].ctx, args);
}
return this;
};
return eventemitter;
}
var float;
var hasRequiredFloat;
function requireFloat() {
if (hasRequiredFloat) return float;
hasRequiredFloat = 1;
float = factory(factory);
function factory(exports) {
if (typeof Float32Array !== "undefined") (function() {
var f32 = new Float32Array([-0]), f8b = new Uint8Array(f32.buffer), le = f8b[3] === 128;
function writeFloat_f32_cpy(val, buf, pos) {
f32[0] = val;
buf[pos] = f8b[0];
buf[pos + 1] = f8b[1];
buf[pos + 2] = f8b[2];
buf[pos + 3] = f8b[3];
}
function writeFloat_f32_rev(val, buf, pos) {
f32[0] = val;
buf[pos] = f8b[3];
buf[pos + 1] = f8b[2];
buf[pos + 2] = f8b[1];
buf[pos + 3] = f8b[0];
}
exports.writeFloatLE = le ? writeFloat_f32_cpy : writeFloat_f32_rev;
exports.writeFloatBE = le ? writeFloat_f32_rev : writeFloat_f32_cpy;
function readFloat_f32_cpy(buf, pos) {
f8b[0] = buf[pos];
f8b[1] = buf[pos + 1];
f8b[2] = buf[pos + 2];
f8b[3] = buf[pos + 3];
return f32[0];
}
function readFloat_f32_rev(buf, pos) {
f8b[3] = buf[pos];
f8b[2] = buf[pos + 1];
f8b[1] = buf[pos + 2];
f8b[0] = buf[pos + 3];
return f32[0];
}
exports.readFloatLE = le ? readFloat_f32_cpy : readFloat_f32_rev;
exports.readFloatBE = le ? readFloat_f32_rev : readFloat_f32_cpy;
})();
else (function() {
function writeFloat_ieee754(writeUint, val, buf, pos) {
var sign = val < 0 ? 1 : 0;
if (sign)
val = -val;
if (val === 0)
writeUint(1 / val > 0 ? (
/* positive */
0
) : (
/* negative 0 */
2147483648
), buf, pos);
else if (isNaN(val))
writeUint(2143289344, buf, pos);
else if (val > 34028234663852886e22)
writeUint((sign << 31 | 2139095040) >>> 0, buf, pos);
else if (val < 11754943508222875e-54)
writeUint((sign << 31 | Math.round(val / 1401298464324817e-60)) >>> 0, buf, pos);
else {
var exponent = Math.floor(Math.log(val) / Math.LN2), mantissa = Math.round(val * Math.pow(2, -exponent) * 8388608) & 8388607;
writeUint((sign << 31 | exponent + 127 << 23 | mantissa) >>> 0, buf, pos);
}
}
exports.writeFloatLE = writeFloat_ieee754.bind(null, writeUintLE);
exports.writeFloatBE = writeFloat_ieee754.bind(null, writeUintBE);
function readFloat_ieee754(readUint, buf, pos) {
var uint = readUint(buf, pos), sign = (uint >> 31) * 2 + 1, exponent = uint >>> 23 & 255, mantissa = uint & 8388607;
return exponent === 255 ? mantissa ? NaN : sign * Infinity : exponent === 0 ? sign * 1401298464324817e-60 * mantissa : sign * Math.pow(2, exponent - 150) * (mantissa + 8388608);
}
exports.readFloatLE = readFloat_ieee754.bind(null, readUintLE);
exports.readFloatBE = readFloat_ieee754.bind(null, readUintBE);
})();
if (typeof Float64Array !== "undefined") (function() {
var f64 = new Float64Array([-0]), f8b = new Uint8Array(f64.buffer), le = f8b[7] === 128;
function writeDouble_f64_cpy(val, buf, pos) {
f64[0] = val;
buf[pos] = f8b[0];
buf[pos + 1] = f8b[1];
buf[pos + 2] = f8b[2];
buf[pos + 3] = f8b[3];
buf[pos + 4] = f8b[4];
buf[pos + 5] = f8b[5];
buf[pos + 6] = f8b[6];
buf[pos + 7] = f8b[7];
}
function writeDouble_f64_rev(val, buf, pos) {
f64[0] = val;
buf[pos] = f8b[7];
buf[pos + 1] = f8b[6];
buf[pos + 2] = f8b[5];
buf[pos + 3] = f8b[4];
buf[pos + 4] = f8b[3];
buf[pos + 5] = f8b[2];
buf[pos + 6] = f8b[1];
buf[pos + 7] = f8b[0];
}
exports.writeDoubleLE = le ? writeDouble_f64_cpy : writeDouble_f64_rev;
exports.writeDoubleBE = le ? writeDouble_f64_rev : writeDouble_f64_cpy;
function readDouble_f64_cpy(buf, pos) {
f8b[0] = buf[pos];
f8b[1] = buf[pos + 1];
f8b[2] = buf[pos + 2];
f8b[3] = buf[pos + 3];
f8b[4] = buf[pos + 4];
f8b[5] = buf[pos + 5];
f8b[6] = buf[pos + 6];
f8b[7] = buf[pos + 7];
return f64[0];
}
function readDouble_f64_rev(buf, pos) {
f8b[7] = buf[pos];
f8b[6] = buf[pos + 1];
f8b[5] = buf[pos + 2];
f8b[4] = buf[pos + 3];
f8b[3] = buf[pos + 4];
f8b[2] = buf[pos + 5];
f8b[1] = buf[pos + 6];
f8b[0] = buf[pos + 7];
return f64[0];
}
exports.readDoubleLE = le ? readDouble_f64_cpy : readDouble_f64_rev;
exports.readDoubleBE = le ? readDouble_f64_rev : readDouble_f64_cpy;
})();
else (function() {
function writeDouble_ieee754(writeUint, off0, off1, val, buf, pos) {
var sign = val < 0 ? 1 : 0;
if (sign)
val = -val;
if (val === 0) {
writeUint(0, buf, pos + off0);
writeUint(1 / val > 0 ? (
/* positive */
0
) : (
/* negative 0 */
2147483648
), buf, pos + off1);
} else if (isNaN(val)) {
writeUint(0, buf, pos + off0);
writeUint(2146959360, buf, pos + off1);
} else if (val > 17976931348623157e292) {
writeUint(0, buf, pos + off0);
writeUint((sign << 31 | 2146435072) >>> 0, buf, pos + off1);
} else {
var mantissa;
if (val < 22250738585072014e-324) {
mantissa = val / 5e-324;
writeUint(mantissa >>> 0, buf, pos + off0);
writeUint((sign << 31 | mantissa / 4294967296) >>> 0, buf, pos + off1);
} else {
var exponent = Math.floor(Math.log(val) / Math.LN2);
if (exponent === 1024)
exponent = 1023;
mantissa = val * Math.pow(2, -exponent);
writeUint(mantissa * 4503599627370496 >>> 0, buf, pos + off0);
writeUint((sign << 31 | exponent + 1023 << 20 | mantissa * 1048576 & 1048575) >>> 0, buf, pos + off1);
}
}
}
exports.writeDoubleLE = writeDouble_ieee754.bind(null, writeUintLE, 0, 4);
exports.writeDoubleBE = writeDouble_ieee754.bind(null, writeUintBE, 4, 0);
function readDouble_ieee754(readUint, off0, off1, buf, pos) {
var lo = readUint(buf, pos + off0), hi = readUint(buf, pos + off1);
var sign = (hi >> 31) * 2 + 1, exponent = hi >>> 20 & 2047, mantissa = 4294967296 * (hi & 1048575) + lo;
return exponent === 2047 ? mantissa ? NaN : sign * Infinity : exponent === 0 ? sign * 5e-324 * mantissa : sign * Math.pow(2, exponent - 1075) * (mantissa + 4503599627370496);
}
exports.readDoubleLE = readDouble_ieee754.bind(null, readUintLE, 0, 4);
exports.readDoubleBE = readDouble_ieee754.bind(null, readUintBE, 4, 0);
})();
return exports;
}
function writeUintLE(val, buf, pos) {
buf[pos] = val & 255;
buf[pos + 1] = val >>> 8 & 255;
buf[pos + 2] = val >>> 16 & 255;
buf[pos + 3] = val >>> 24;
}
function writeUintBE(val, buf, pos) {
buf[pos] = val >>> 24;
buf[pos + 1] = val >>> 16 & 255;
buf[pos + 2] = val >>> 8 & 255;
buf[pos + 3] = val & 255;
}
function readUintLE(buf, pos) {
return (buf[pos] | buf[pos + 1] << 8 | buf[pos + 2] << 16 | buf[pos + 3] << 24) >>> 0;
}
function readUintBE(buf, pos) {
return (buf[pos] << 24 | buf[pos + 1] << 16 | buf[pos + 2] << 8 | buf[pos + 3]) >>> 0;
}
return float;
}
var inquire_1;
var hasRequiredInquire;
function requireInquire() {
if (hasRequiredInquire) return inquire_1;
hasRequiredInquire = 1;
inquire_1 = inquire;
function inquire(moduleName) {
try {
var mod = eval("quire".replace(/^/, "re"))(moduleName);
if (mod && (mod.length || Object.keys(mod).length))
return mod;
} catch (e) {
}
return null;
}
return inquire_1;
}
var utf8 = {};
var hasRequiredUtf8;
function requireUtf8() {
if (hasRequiredUtf8) return utf8;
hasRequiredUtf8 = 1;
(function(exports) {
var utf82 = exports;
utf82.length = function utf8_length(string) {
var len = 0, c = 0;
for (var i = 0; i < string.length; ++i) {
c = string.charCodeAt(i);
if (c < 128)
len += 1;
else if (c < 2048)
len += 2;
else if ((c & 64512) === 55296 && (string.charCodeAt(i + 1) & 64512) === 56320) {
++i;
len += 4;
} else
len += 3;
}
return len;
};
utf82.read = function utf8_read(buffer, start, end) {
var len = end - start;
if (len < 1)
return "";
var parts = null, chunk = [], i = 0, t;
while (start < end) {
t = buffer[start++];
if (t < 128)
chunk[i++] = t;
else if (t > 191 && t < 224)
chunk[i++] = (t & 31) << 6 | buffer[start++] & 63;
else if (t > 239 && t < 365) {
t = ((t & 7) << 18 | (buffer[start++] & 63) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63) - 65536;
chunk[i++] = 55296 + (t >> 10);
chunk[i++] = 56320 + (t & 1023);
} else
chunk[i++] = (t & 15) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63;
if (i > 8191) {
(parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));
i = 0;
}
}
if (parts) {
if (i)
parts.push(String.fromCharCode.apply(String, chunk.slice(0, i)));
return parts.join("");
}
return String.fromCharCode.apply(String, chunk.slice(0, i));
};
utf82.write = function utf8_write(string, buffer, offset) {
var start = offset, c1, c2;
for (var i = 0; i < string.length; ++i) {
c1 = string.charCodeAt(i);
if (c1 < 128) {
buffer[offset++] = c1;
} else if (c1 < 2048) {
buffer[offset++] = c1 >> 6 | 192;
buffer[offset++] = c1 & 63 | 128;
} else if ((c1 & 64512) === 55296 && ((c2 = string.charCodeAt(i + 1)) & 64512) === 56320) {
c1 = 65536 + ((c1 & 1023) << 10) + (c2 & 1023);
++i;
buffer[offset++] = c1 >> 18 | 240;
buffer[offset++] = c1 >> 12 & 63 | 128;
buffer[offset++] = c1 >> 6 & 63 | 128;
buffer[offset++] = c1 & 63 | 128;
} else {
buffer[offset++] = c1 >> 12 | 224;
buffer[offset++] = c1 >> 6 & 63 | 128;
buffer[offset++] = c1 & 63 | 128;
}
}
return offset - start;
};
})(utf8);
return utf8;
}
var pool_1;
var hasRequiredPool;
function requirePool() {
if (hasRequiredPool) return pool_1;
hasRequiredPool = 1;
pool_1 = pool;
function pool(alloc, slice, size) {
var SIZE = size || 8192;
var MAX = SIZE >>> 1;
var slab = null;
var offset = SIZE;
return function pool_alloc(size2) {
if (size2 < 1 || size2 > MAX)
return alloc(size2);
if (offset + size2 > SIZE) {
slab = alloc(SIZE);
offset = 0;
}
var buf = slice.call(slab, offset, offset += size2);
if (offset & 7)
offset = (offset | 7) + 1;
return buf;
};
}
return pool_1;
}
var longbits;
var hasRequiredLongbits;
function requireLongbits() {
if (hasRequiredLongbits) return longbits;
hasRequiredLongbits = 1;
longbits = LongBits;
var util = requireMinimal$1();
function LongBits(lo, hi) {
this.lo = lo >>> 0;
this.hi = hi >>> 0;
}
var zero = LongBits.zero = new LongBits(0, 0);
zero.toNumber = function() {
return 0;
};
zero.zzEncode = zero.zzDecode = function() {
return this;
};
zero.length = function() {
return 1;
};
var zeroHash = LongBits.zeroHash = "\0\0\0\0\0\0\0\0";
LongBits.fromNumber = function fromNumber(value) {
if (value === 0)
return zero;
var sign = value < 0;
if (sign)
value = -value;
var lo = value >>> 0, hi = (value - lo) / 4294967296 >>> 0;
if (sign) {
hi = ~hi >>> 0;
lo = ~lo >>> 0;
if (++lo > 4294967295) {
lo = 0;
if (++hi > 4294967295)
hi = 0;
}
}
return new LongBits(lo, hi);
};
LongBits.from = function from(value) {
if (typeof value === "number")
return LongBits.fromNumber(value);
if (util.isString(value)) {
if (util.Long)
value = util.Long.fromString(value);
else
return LongBits.fromNumber(parseInt(value, 10));
}
return value.low || value.high ? new LongBits(value.low >>> 0, value.high >>> 0) : zero;
};
LongBits.prototype.toNumber = function toNumber(unsigned) {
if (!unsigned && this.hi >>> 31) {
var lo = ~this.lo + 1 >>> 0, hi = ~this.hi >>> 0;
if (!lo)
hi = hi + 1 >>> 0;
return -(lo + hi * 4294967296);
}
return this.lo + this.hi * 4294967296;
};
LongBits.prototype.toLong = function toLong(unsigned) {
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) };
};
var charCodeAt = String.prototype.charCodeAt;
LongBits.fromHash = function fromHash(hash) {
if (hash === zeroHash)
return zero;
return new LongBits(
(charCodeAt.call(hash, 0) | charCodeAt.call(hash, 1) << 8 | charCodeAt.call(hash, 2) << 16 | charCodeAt.call(hash, 3) << 24) >>> 0,
(charCodeAt.call(hash, 4) | charCodeAt.call(hash, 5) << 8 | charCodeAt.call(hash, 6) << 16 | charCodeAt.call(hash, 7) << 24) >>> 0
);
};
LongBits.prototype.toHash = function toHash() {
return String.fromCharCode(
this.lo & 255,
this.lo >>> 8 & 255,
this.lo >>> 16 & 255,
this.lo >>> 24,
this.hi & 255,
this.hi >>> 8 & 255,
this.hi >>> 16 & 255,
this.hi >>> 24
);
};
LongBits.prototype.zzEncode = function zzEncode() {
var mask = this.hi >> 31;
this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask) >>> 0;
this.lo = (this.lo << 1 ^ mask) >>> 0;
return this;
};
LongBits.prototype.zzDecode = function zzDecode() {
var mask = -(this.lo & 1);
this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask) >>> 0;
this.hi = (this.hi >>> 1 ^ mask) >>> 0;
return this;
};
LongBits.prototype.length = function length() {
var part0 = this.lo, part1 = (this.lo >>> 28 | this.hi << 4) >>> 0, part2 = this.hi >>> 24;
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;
};
return longbits;
}
var hasRequiredMinimal$1;
function requireMinimal$1() {
if (hasRequiredMinimal$1) return minimal$1;
hasRequiredMinimal$1 = 1;
(function(exports) {
var util = exports;
util.asPromise = requireAspromise();
util.base64 = requireBase64();
util.EventEmitter = requireEventemitter();
util.float = requireFloat();
util.inquire = requireInquire();
util.utf8 = requireUtf8();
util.pool = requirePool();
util.LongBits = requireLongbits();
util.isNode = Boolean(typeof commonjsGlobal !== "undefined" && commonjsGlobal && commonjsGlobal.process && commonjsGlobal.process.versions && commonjsGlobal.process.versions.node);
util.global = util.isNode && commonjsGlobal || typeof window !== "undefined" && window || typeof self !== "undefined" && self || minimal$1;
util.emptyArray = Object.freeze ? Object.freeze([]) : (
/* istanbul ignore next */
[]
);
util.emptyObject = Object.freeze ? Object.freeze({}) : (
/* istanbul ignore next */
{}
);
util.isInteger = Number.isInteger || /* istanbul ignore next */
function isInteger(value) {
return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
};
util.isString = function isString(value) {
return typeof value === "string" || value instanceof String;
};
util.isObject = function isObject(value) {
return value && typeof value === "object";
};
util.isset = /**
* Checks if a property on a message is considered to be present.
* @param {Object} obj Plain object or message instance
* @param {string} prop Property name
* @returns {boolean} `true` if considered to be present, otherwise `false`
*/
util.isSet = function isSet(obj, prop) {
var value = obj[prop];
if (value != null && obj.hasOwnProperty(prop))
return typeof value !== "object" || (Array.isArray(value) ? value.length : Object.keys(value).length) > 0;
return false;
};
util.Buffer = function() {
try {
var Buffer = util.inquire("buffer").Buffer;
return Buffer.prototype.utf8Write ? Buffer : (
/* istanbul ignore next */
null
);
} catch (e) {
return null;
}
}();
util._Buffer_from = null;
util._Buffer_allocUnsafe = null;
util.newBuffer = function newBuffer(sizeOrArray) {
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);
};
util.Array = typeof Uint8Array !== "undefined" ? Uint8Array : Array;
util.Long = /* istanbul ignore next */
util.global.dcodeIO && /* istanbul ignore next */
util.global.dcodeIO.Long || /* istanbul ignore next */
util.global.Long || util.inquire("long");
util.key2Re = /^true|false|0|1$/;
util.key32Re = /^-?(?:0|[1-9][0-9]*)$/;
util.key64Re = /^(?:[\\x00-\\xff]{8}|-?(?:0|[1-9][0-9]*))$/;
util.longToHash = function longToHash(value) {
return value ? util.LongBits.from(value).toHash() : util.LongBits.zeroHash;
};
util.longFromHash = function longFromHash(hash, unsigned) {
var bits = util.LongBits.fromHash(hash);
if (util.Long)
return util.Long.fromBits(bits.lo, bits.hi, unsigned);
return bits.toNumber(Boolean(unsigned));
};
function merge(dst, src, ifNotSet) {
for (var keys = Object.keys(src), i = 0; i < keys.length; ++i)
if (dst[keys[i]] === void 0 || !ifNotSet)
dst[keys[i]] = src[keys[i]];
return dst;
}
util.merge = merge;
util.lcFirst = function lcFirst(str) {
return str.charAt(0).toLowerCase() + str.substring(1);
};
function newError(name) {
function CustomError(message, properties) {
if (!(this instanceof CustomError))
return new CustomError(message, properties);
Object.defineProperty(this, "message", { get: function() {
return message;
} });
if (Error.captureStackTrace)
Error.captureStackTrace(this, CustomError);
else
Object.defineProperty(this, "stack", { value: new Error().stack || "" });
if (properties)
merge(this, properties);
}
CustomError.prototype = Object.create(Error.prototype, {
constructor: {
value: CustomError,
writable: true,
enumerable: false,
configurable: true
},
name: {
get: function get() {
return name;
},
set: void 0,
enumerable: false,
// configurable: false would accurately preserve the behavior of
// the original, but I'm guessing that was not intentional.
// For an actual error subclass, this property would
// be configurable.
configurable: true
},
toString: {
value: function value() {
return this.name + ": " + this.message;
},
writable: true,
enumerable: false,
configurable: true
}
});
return CustomError;
}
util.newError = newError;
util.ProtocolError = newError("ProtocolError");
util.oneOfGetter = function getOneOf(fieldNames) {
var fieldMap = {};
for (var i = 0; i < fieldNames.length; ++i)
fieldMap[fieldNames[i]] = 1;
return function() {
for (var keys = Object.keys(this), i2 = keys.length - 1; i2 > -1; --i2)
if (fieldMap[keys[i2]] === 1 && this[keys[i2]] !== void 0 && this[keys[i2]] !== null)
return keys[i2];
};
};
util.oneOfSetter = function setOneOf(fieldNames) {
return function(name) {
for (var i = 0; i < fieldNames.length; ++i)
if (fieldNames[i] !== name)
delete this[fieldNames[i]];
};
};
util.toJSONOptions = {
longs: String,
enums: String,
bytes: String,
json: true
};
util._configure = function() {
var Buffer = util.Buffer;
if (!Buffer) {
util._Buffer_from = util._Buffer_allocUnsafe = null;
return;
}
util._Buffer_from = Buffer.from !== Uint8Array.from && Buffer.from || /* istanbul ignore next */
function Buffer_from(value, encoding) {
return new Buffer(value, encoding);
};
util._Buffer_allocUnsafe = Buffer.allocUnsafe || /* istanbul ignore next */
function Buffer_allocUnsafe(size) {
return new Buffer(size);
};
};
})(minimal$1);
return minimal$1;
}
var writer;
var hasRequiredWriter;
function requireWriter() {
if (hasRequiredWriter) return writer;
hasRequiredWriter = 1;
writer = Writer;
var util = requireMinimal$1();
var BufferWriter;
var LongBits = util.LongBits, base642 = util.base64, utf82 = util.utf8;
function Op(fn, len, val) {
this.fn = fn;
this.len = len;
this.next = void 0;
this.val = val;
}
function noop() {
}
function State(writer2) {
this.head = writer2.head;
this.tail = writer2.tail;
this.len = writer2.len;
this.next = writer2.states;
}
function Writer() {
this.len = 0;
this.head = new Op(noop, 0, 0);
this.tail = this.head;
this.states = null;
}
var create = function create2() {
return util.Buffer ? function create_buffer_setup() {
return (Writer.create = function create_buffer() {
return new BufferWriter();
})();
} : function create_array() {
return new Writer();
};
};
Writer.create = create();
Writer.alloc = function alloc(size) {
return new util.Array(size);
};
if (util.Array !== Array)
Writer.alloc = util.pool(Writer.alloc, util.Array.prototype.subarray);
Writer.prototype._push = function push(fn, len, val) {
this.tail = this.tail.next = new Op(fn, len, val);
this.len += len;
return this;
};
function writeByte(val, buf, pos) {
buf[pos] = val & 255;
}
function writeVarint32(val, buf, pos) {
while (val > 127) {
buf[pos++] = val & 127 | 128;
val >>>= 7;
}
buf[pos] = val;
}
function VarintOp(len, val) {
this.len = len;
this.next = void 0;
this.val = val;
}
VarintOp.prototype = Object.create(Op.prototype);
VarintOp.prototype.fn = writeVarint32;
Writer.prototype.uint32 = function write_uint32(value) {
this.len += (this.tail = this.tail.next = new VarintOp(
(value = value >>> 0) < 128 ? 1 : value < 16384 ? 2 : value < 2097152 ? 3 : value < 268435456 ? 4 : 5,
value
)).len;
return this;
};
Writer.prototype.int32 = function write_int32(value) {
return value < 0 ? this._push(writeVarint64, 10, LongBits.fromNumber(value)) : this.uint32(value);
};
Writer.prototype.sint32 = function write_sint32(value) {
return this.uint32((value << 1 ^ value >> 31) >>> 0);
};
function writeVarint64(val, buf, pos) {
while (val.hi) {
buf[pos++] = val.lo & 127 | 128;
val.lo = (val.lo >>> 7 | val.hi << 25) >>> 0;
val.hi >>>= 7;
}
while (val.lo > 127) {
buf[pos++] = val.lo & 127 | 128;
val.lo = val.lo >>> 7;
}
buf[pos++] = val.lo;
}
Writer.prototype.uint64 = function write_uint64(value) {
var bits = LongBits.from(value);
return this._push(writeVarint64, bits.length(), bits);
};
Writer.prototype.int64 = Writer.prototype.uint64;
Writer.prototype.sint64 = function write_sint64(value) {
var bits = LongBits.from(value).zzEncode();
return this._push(writeVarint64, bits.length(), bits);
};
Writer.prototype.bool = function write_bool(value) {
return this._push(writeByte, 1, value ? 1 : 0);
};
function writeFixed32(val, buf, pos) {
buf[pos] = val & 255;
buf[pos + 1] = val >>> 8 & 255;
buf[pos + 2] = val >>> 16 & 255;
buf[pos + 3] = val >>> 24;
}
Writer.prototype.fixed32 = function write_fixed32(value) {
return this._push(writeFixed32, 4, value >>> 0);
};
Writer.prototype.sfixed32 = Writer.prototype.fixed32;
Writer.prototype.fixed64 = function write_fixed64(value) {
var bits = LongBits.from(value);
return this._push(writeFixed32, 4, bits.lo)._push(writeFixed32, 4, bits.hi);
};
Writer.prototype.sfixed64 = Writer.prototype.fixed64;
Writer.prototype.float = function write_float(value) {
return this._push(util.float.writeFloatLE, 4, value);
};
Writer.prototype.double = function write_double(value) {
return this._push(util.float.writeDoubleLE, 8, value);
};
var writeBytes = util.Array.prototype.set ? function writeBytes_set(val, buf, pos) {
buf.set(val, pos);
} : function writeBytes_for(val, buf, pos) {
for (var i = 0; i < val.length; ++i)
buf[pos + i] = val[i];
};
Writer.prototype.bytes = function write_bytes(value) {
var len = value.length >>> 0;
if (!len)
return this._push(writeByte, 1, 0);
if (util.isString(value)) {
var buf = Writer.alloc(len = base642.length(value));
base642.decode(value, buf, 0);
value = buf;
}
return this.uint32(len)._push(writeBytes, len, value);
};
Writer.prototype.string = function write_string(value) {
var len = utf82.length(value);
return len ? this.uint32(len)._push(utf82.write, len, value) : this._push(writeByte, 1, 0);
};
Writer.prototype.fork = function fork() {
this.states = new State(this);
this.head = this.tail = new Op(noop, 0, 0);
this.len = 0;
return this;
};
Writer.prototype.reset = function reset() {
if (this.states) {
this.head = this.states.head;
this.tail = this.states.tail;
this.len = this.states.len;
this.states = this.states.next;
} else {
this.head = this.tail = new Op(noop, 0, 0);
this.len = 0;
}
return this;
};
Writer.prototype.ldelim = function ldelim() {
var head = this.head, tail = this.tail, len = this.len;
this.reset().uint32(len);
if (len) {
this.tail.next = head.next;
this.tail = tail;
this.len += len;
}
return this;
};
Writer.prototype.finish = function finish() {
var head = this.head.next, buf = this.constructor.alloc(this.len), pos = 0;
while (head) {
head.fn(head.val, buf, pos);
pos += head.len;
head = head.next;
}
return buf;
};
Writer._configure = function(BufferWriter_) {
BufferWriter = BufferWriter_;
Writer.create = create();
BufferWriter._configure();
};
return writer;
}
var writer_buffer;
var hasRequiredWriter_buffer;
function requireWriter_buffer() {
if (hasRequiredWriter_buffer) return writer_buffer;
hasRequiredWriter_buffer = 1;
writer_buffer = BufferWriter;
var Writer = requireWriter();
(BufferWriter.prototype = Object.create(Writer.prototype)).constructor = BufferWriter;
var util = requireMinimal$1();
function BufferWriter() {
Writer.call(this);
}
BufferWriter._configure = function() {
BufferWriter.alloc = util._Buffer_allocUnsafe;
BufferWriter.writeBytesBuffer = util.Buffer && util.Buffer.prototype instanceof Uint8Array && util.Buffer.prototype.set.name === "set" ? function writeBytesBuffer_set(val, buf, pos) {
buf.set(val, pos);
} : function writeBytesBuffer_copy(val, buf, pos) {
if (val.copy)
val.copy(buf, pos, 0, val.length);
else for (var i = 0; i < val.length; )
buf[pos++] = val[i++];
};
};
BufferWriter.prototype.bytes = function write_bytes_buffer(value) {
if (util.isString(value))
value = util._Buffer_from(value, "base64");
var len = value.length >>> 0;
this.uint32(len);
if (len)
this._push(BufferWriter.writeBytesBuffer, len, value);
return this;
};
function writeStringBuffer(val, buf, pos) {
if (val.length < 40)
util.utf8.write(val, buf, pos);
else if (buf.utf8Write)
buf.utf8Write(val, pos);
else
buf.write(val, pos);
}
BufferWriter.prototype.string = function write_string_buffer(value) {
var len = util.Buffer.byteLength(value);
this.uint32(len);
if (len)
this._push(writeStringBuffer, len, value);
return this;
};
BufferWriter._configure();
return writer_buffer;
}
var reader;
var hasRequiredReader;
function requireReader() {
if (hasRequiredReader) return reader;
hasRequiredReader = 1;
reader = Reader;
var util = requireMinimal$1();
var BufferReader;
var LongBits = util.LongBits, utf82 = util.utf8;
function indexOutOfRange(reader2, writeLength) {
return RangeError("index out of range: " + reader2.pos + " + " + (writeLength || 1) + " > " + reader2.len);
}
function Reader(buffer) {
this.buf = buffer;
this.pos = 0;
this.len = buffer.length;
}
var create_array = typeof Uint8Array !== "undefined" ? function create_typed_array(buffer) {
if (buffer instanceof Uint8Array || Array.isArray(buffer))
return new Reader(buffer);
throw Error("illegal buffer");
} : function create_array2(buffer) {
if (Array.isArray(buffer))
return new Reader(buffer);
throw Error("illegal buffer");
};
var create = function create2() {
return util.Buffer ? function create_buffer_setup(buffer) {
return (Reader.create = function create_buffer(buffer2) {
return util.Buffer.isBuffer(buffer2) ? new BufferReader(buffer2) : create_array(buffer2);
})(buffer);
} : create_array;
};
Reader.create = create();
Reader.prototype._slice = util.Array.prototype.subarray || /* istanbul ignore next */
util.Array.prototype.slice;
Reader.prototype.uint32 = /* @__PURE__ */ function read_uint32_setup() {
var value = 4294967295;
return function read_uint32() {
value = (this.buf[this.pos] & 127) >>> 0;
if (this.buf[this.pos++] < 128) return value;
value = (value | (this.buf[this.pos] & 127) << 7) >>> 0;
if (this.buf[this.pos++] < 128) return value;
value = (value | (this.buf[this.pos] & 127) << 14) >>> 0;
if (this.buf[this.pos++] < 128) return value;
value = (value | (this.buf[this.pos] & 127) << 21) >>> 0;
if (this.buf[this.pos++] < 128) return value;
value = (value | (this.buf[this.pos] & 15) << 28) >>> 0;
if (this.buf[this.pos++] < 128) return value;
if ((this.pos += 5) > this.len) {
this.pos = this.len;
throw indexOutOfRange(this, 10);
}
return value;
};
}();
Reader.prototype.int32 = function read_int32() {
return this.uint32() | 0;
};
Reader.prototype.sint32 = function read_sint32() {
var value = this.uint32();
return value >>> 1 ^ -(value & 1) | 0;
};
function readLongVarint() {
var bits = new LongBits(0, 0);
var i = 0;
if (this.len - this.pos > 4) {
for (; i < 4; ++i) {
bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;
if (this.buf[this.pos++] < 128)
return bits;
}
bits.lo = (bits.lo | (this.buf[this.pos] & 127) << 28) >>> 0;
bits.hi = (bits.hi | (this.buf[this.pos] & 127) >> 4) >>> 0;
if (this.buf[this.pos++] < 128)
return bits;
i = 0;
} else {
for (; i < 3; ++i) {
if (this.pos >= this.len)
throw indexOutOfRange(this);
bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;
if (this.buf[this.pos++] < 128)
return bits;
}
bits.lo = (bits.lo | (this.buf[this.pos++] & 127) << i * 7) >>> 0;
return bits;
}
if (this.len - this.pos > 4) {
for (; i < 5; ++i) {
bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0;
if (this.buf[this.pos++] < 128)
return bits;
}
} else {
for (; i < 5; ++i) {
if (this.pos >= this.len)
throw indexOutOfRange(this);
bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0;
if (this.buf[this.pos++] < 128)
return bits;
}
}
throw Error("invalid varint encoding");
}
Reader.prototype.bool = function read_bool() {
return this.uint32() !== 0;
};
function readFixed32_end(buf, end) {
return (buf[end - 4] | buf[end - 3] << 8 | buf[end - 2] << 16 | buf[end - 1] << 24) >>> 0;
}
Reader.prototype.fixed32 = function read_fixed32() {
if (this.pos + 4 > this.len)
throw indexOutOfRange(this, 4);
return readFixed32_end(this.buf, this.pos += 4);
};
Reader.prototype.sfixed32 = function read_sfixed32() {
if (this.pos + 4 > this.len)
throw indexOutOfRange(this, 4);
return readFixed32_end(this.buf, this.pos += 4) | 0;
};
function readFixed64() {
if (this.pos + 8 > this.len)
throw indexOutOfRange(this, 8);
return new LongBits(readFixed32_end(this.buf, this.pos += 4), readFixed32_end(this.buf, this.pos += 4));
}
Reader.prototype.float = function read_float() {
if (this.pos + 4 > this.len)
throw indexOutOfRange(this, 4);
var value = util.float.readFloatLE(this.buf, this.pos);
this.pos += 4;
return value;
};
Reader.prototype.double = function read_double() {
if (this.pos + 8 > this.len)
throw indexOutOfRange(this, 4);
var value = util.float.readDoubleLE(this.buf, this.pos);
this.pos += 8;
return value;
};
Reader.prototype.bytes = function read_bytes() {
var length = this.uint32(), start = this.pos, end = this.pos + length;
if (end > this.len)
throw indexOutOfRange(this, length);
this.pos += length;
if (Array.isArray(this.buf))
return this.buf.slice(start, end);
if (start === end) {
var nativeBuffer = util.Buffer;
return nativeBuffer ? nativeBuffer.alloc(0) : new this.buf.constructor(0);
}
return this._slice.call(this.buf, start, end);
};
Reader.prototype.string = function read_string() {
var bytes = this.bytes();
return utf82.read(bytes, 0, bytes.length);
};
Reader.prototype.skip = function skip(length) {
if (typeof length === "number") {
if (this.pos + length > this.len)
throw indexOutOfRange(this, length);
this.pos += length;
} else {
do {
if (this.pos >= this.len)
throw indexOutOfRange(this);
} while (this.buf[this.pos++] & 128);
}
return this;
};
Reader.prototype.skipType = function(wireType) {
switch (wireType) {
case 0:
this.skip();
break;
case 1:
this.skip(8);
break;
case 2:
this.skip(this.uint32());
break;
case 3:
while ((wireType = this.uint32() & 7) !== 4) {
this.skipType(wireType);
}
break;
case 5:
this.skip(4);
break;
/* istanbul ignore next */
default:
throw Error("invalid wire type " + wireType + " at offset " + this.pos);
}
return this;
};
Reader._configure = function(BufferReader_) {
BufferReader = BufferReader_;
Reader.create = create();
BufferReader._configure();
var fn = util.Long ? "toLong" : (
/* istanbul ignore next */
"toNumber"
);
util.merge(Reader.prototype, {
int64: function read_int64() {
return readLongVarint.call(this)[fn](false);
},
uint64: function read_uint64() {
return readLongVarint.call(this)[fn](true);
},
sint64: function read_sint64() {
return readLongVarint.call(this).zzDecode()[fn](false);
},
fixed64: function read_fixed64() {
return readFixed64.call(this)[fn](true);
},
sfixed64: function read_sfixed64() {
return readFixed64.call(this)[fn](false);
}
});
};
return reader;
}
var reader_buffer;
var hasRequiredReader_buffer;
function requireReader_buffer() {
if (hasRequiredReader_buffer) return reader_buffer;
hasRequiredReader_buffer = 1;
reader_buffer = BufferReader;
var Reader = requireReader();
(BufferReader.prototype = Object.create(Reader.prototype)).constructor = BufferReader;
var util = requireMinimal$1();
function BufferReader(buffer) {
Reader.call(this, buffer);
}
BufferReader._configure = function() {
if (util.Buffer)
BufferReader.prototype._slice = util.Buffer.prototype.slice;
};
BufferReader.prototype.string = function read_string_buffer() {
var len = this.uint32();
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));
};
BufferReader._configure();
return reader_buffer;
}
var rpc = {};
var service;
var hasRequiredService;
function requireService() {
if (hasRequiredService) return service;
hasRequiredService = 1;
service = Service;
var util = requireMinimal$1();
(Service.prototype = Object.create(util.EventEmitter.prototype)).constructor = Service;
function Service(rpcImpl, requestDelimited, responseDelimited) {
if (typeof rpcImpl !== "function")
throw TypeError("rpcImpl must be a function");
util.EventEmitter.call(this);
this.rpcImpl = rpcImpl;
this.requestDelimited = Boolean(requestDelimited);
this.responseDelimited = Boolean(responseDelimited);
}
Service.prototype.rpcCall = function rpcCall(method, requestCtor, responseCtor, request, callback) {
if (!request)
throw TypeError("request must be specified");
var self2 = this;
if (!callback)
return util.asPromise(rpcCall, self2, method, requestCtor, responseCtor, request);
if (!self2.rpcImpl) {
setTimeout(function() {
callback(Error("already ended"));
}, 0);
return void 0;
}
try {
return self2.rpcImpl(
method,
requestCtor[self2.requestDelimited ? "encodeDelimited" : "encode"](request).finish(),
function rpcCallback(err, response) {
if (err) {
self2.emit("error", err, method);
return callback(err);
}
if (response === null) {
self2.end(
/* endedByRPC */
true
);
return void 0;
}
if (!(response instanceof responseCtor)) {
try {
response = responseCtor[self2.responseDelimited ? "decodeDelimited" : "decode"](response);
} catch (err2) {
self2.emit("error", err2, method);
return callback(err2);
}
}
self2.emit("data", response, method);
return callback(null, response);
}
);
} catch (err) {
self2.emit("error", err, method);
setTimeout(function() {
callback(err);
}, 0);
return void 0;
}
};
Service.prototype.end = function end(endedByRPC) {
if (this.rpcImpl) {
if (!endedByRPC)
this.rpcImpl(null, null, null);
this.rpcImpl = null;
this.emit("end").off();
}
return this;
};
return service;
}
var hasRequiredRpc;
function requireRpc() {
if (hasRequiredRpc) return rpc;
hasRequiredRpc = 1;
(function(exports) {
var rpc2 = exports;
rpc2.Service = requireService();
})(rpc);
return rpc;
}
var roots;
var hasRequiredRoots;
function requireRoots() {
if (hasRequiredRoots) return roots;
hasRequiredRoots = 1;
roots = {};
return roots;
}
var hasRequiredIndexMinimal;
function requireIndexMinimal() {
if (hasRequiredIndexMinimal) return indexMinimal;
hasRequiredIndexMinimal = 1;
(function(exports) {
var protobuf = exports;
protobuf.build = "minimal";
protobuf.Writer = requireWriter();
protobuf.BufferWriter = requireWriter_buffer();
protobuf.Reader = requireReader();
protobuf.BufferReader = requireReader_buffer();
protobuf.util = requireMinimal$1();
protobuf.rpc = requireRpc();
protobuf.roots = requireRoots();
protobuf.configure = configure;
function configure() {
protobuf.util._configure();
protobuf.Writer._configure(protobuf.BufferWriter);
protobuf.Reader._configure(protobuf.BufferReader);
}
configure();
})(indexMinimal);
return indexMinimal;
}
var minimal;
var hasRequiredMinimal;
function requireMinimal() {
if (hasRequiredMinimal) return minimal;
hasRequiredMinimal = 1;
minimal = requireIndexMinimal();
return minimal;
}
var minimalExports = requireMinimal();
const $Writer = minimalExports.Writer;
const $root$2 = minimalExports.roots["default"] || (minimalExports.roots["default"] = {});
const NextContinuation = $root$2.NextContinuation = (() => {
function NextContinuation2(p) {
if (p) {
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
}
NextContinuation2.prototype.commentAreaWrapper = null;
NextContinuation2.prototype.uField3 = 0;
NextContinuation2.prototype.mainCommentRequest = null;
NextContinuation2.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.commentAreaWrapper != null && Object.hasOwnProperty.call(m, "commentAreaWrapper"))
$root$2.CommentAreaWrapper.encode(m.commentAreaWrapper, w.uint32(18).fork()).ldelim();
if (m.uField3 != null && Object.hasOwnProperty.call(m, "uField3"))
w.uint32(24).int32(m.uField3);
if (m.mainCommentRequest != null && Object.hasOwnProperty.call(m, "mainCommentRequest"))
$root$2.MainCommentRequest.encode(m.mainCommentRequest, w.uint32(50).fork()).ldelim();
return w;
};
return NextContinuation2;
})();
$root$2.CommentAreaWrapper = (() => {
function CommentAreaWrapper(p) {
if (p) {
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
}
CommentAreaWrapper.prototype.videoId = "";
CommentAreaWrapper.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.videoId != null && Object.hasOwnProperty.call(m, "videoId"))
w.uint32(18).string(m.videoId);
return w;
};
return CommentAreaWrapper;
})();
$root$2.MainCommentRequest = (() => {
function MainCommentRequest(p) {
if (p) {
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
}
MainCommentRequest.prototype.commentParameters = null;
MainCommentRequest.prototype.commentReplyParameters = null;
MainCommentRequest.prototype.sectionIdentifier = "";
MainCommentRequest.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.commentReplyParameters != null && Object.hasOwnProperty.call(m, "commentReplyParameters"))
$root$2.CommentReplyParameters.encode(m.commentReplyParameters, w.uint32(26).fork()).ldelim();
if (m.commentParameters != null && Object.hasOwnProperty.call(m, "commentParameters"))
$root$2.CommentParameters.encode(m.commentParameters, w.uint32(34).fork()).ldelim();
if (m.sectionIdentifier != null && Object.hasOwnProperty.call(m, "sectionIdentifier"))
w.uint32(66).string(m.sectionIdentifier);
return w;
};
return MainCommentRequest;
})();
$root$2.CommentParameters = (() => {
function CommentParameters(p) {
if (p) {
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
}
CommentParameters.prototype.videoId = "";
CommentParameters.prototype.postId = "";
CommentParameters.prototype.channelId = "";
CommentParameters.prototype.sortType = 0;
CommentParameters.prototype.targetCommentId = "";
CommentParameters.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.videoId != null && Object.hasOwnProperty.call(m, "videoId"))
w.uint32(34).string(m.videoId);
if (m.sortType != null && Object.hasOwnProperty.call(m, "sortType"))
w.uint32(48).int32(m.sortType);
if (m.targetCommentId != null && Object.hasOwnProperty.call(m, "targetCommentId"))
w.uint32(130).string(m.targetCommentId);
if (m.postId != null && Object.hasOwnProperty.call(m, "postId"))
w.uint32(234).string(m.postId);
if (m.channelId != null && Object.hasOwnProperty.call(m, "channelId"))
w.uint32(242).string(m.channelId);
return w;
};
CommentParameters.SortType = function() {
const valuesById = {}, values = Object.create(valuesById);
values[valuesById[0] = "HOT"] = 0;
values[valuesById[1] = "LATEST"] = 1;
return values;
}();
return CommentParameters;
})();
$root$2.CommentReplyParameters = (() => {
function CommentReplyParameters(p) {
if (p) {
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
}
CommentReplyParameters.prototype.rootCommentId = "";
CommentReplyParameters.prototype.channelId = "";
CommentReplyParameters.prototype.videoId = "";
CommentReplyParameters.prototype.postId = "";
CommentReplyParameters.prototype.pageSize = 0;
CommentReplyParameters.prototype.sortParam = null;
CommentReplyParameters.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.rootCommentId != null && Object.hasOwnProperty.call(m, "rootCommentId"))
w.uint32(18).string(m.rootCommentId);
if (m.channelId != null && Object.hasOwnProperty.call(m, "channelId"))
w.uint32(42).string(m.channelId);
if (m.videoId != null && Object.hasOwnProperty.call(m, "videoId"))
w.uint32(50).string(m.videoId);
if (m.pageSize != null && Object.hasOwnProperty.call(m, "pageSize"))
w.uint32(72).int32(m.pageSize);
if (m.postId != null && Object.hasOwnProperty.call(m, "postId"))
w.uint32(122).string(m.postId);
if (m.sortParam != null && Object.hasOwnProperty.call(m, "sortParam"))
$root$2.CommentReplyParameters.SortParam.encode(m.sortParam, w.uint32(130).fork()).ldelim();
return w;
};
CommentReplyParameters.SortParam = function() {
function SortParam(p) {
if (p) {
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
}
SortParam.prototype.sortType = 0;
SortParam.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.sortType != null && Object.hasOwnProperty.call(m, "sortType"))
w.uint32(8).int32(m.sortType);
return w;
};
SortParam.SortType = function() {
const valuesById = {}, values = Object.create(valuesById);
values[valuesById[0] = "DEFAULT"] = 0;
values[valuesById[1] = "HOT"] = 1;
values[valuesById[2] = "LATEST"] = 2;
return values;
}();
return SortParam;
}();
return CommentReplyParameters;
})();
const BrowserContinuation = $root$2.BrowserContinuation = (() => {
function BrowserContinuation2(p) {
if (p) {
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
}
BrowserContinuation2.prototype.request = null;
BrowserContinuation2.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.request != null && Object.hasOwnProperty.call(m, "request"))
$root$2.BrowserContinuation.Request.encode(m.request, w.uint32(641815778).fork()).ldelim();
return w;
};
BrowserContinuation2.Request = function() {
function Request(p) {
if (p) {
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
}
Request.prototype.description = "";
Request.prototype.continuationBase64 = "";
Request.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.description != null && Object.hasOwnProperty.call(m, "description"))
w.uint32(18).string(m.description);
if (m.continuationBase64 != null && Object.hasOwnProperty.call(m, "continuationBase64"))
w.uint32(26).string(m.continuationBase64);
return w;
};
return Request;
}();
return BrowserContinuation2;
})();
const BrowserCommentListContinuation = $root$2.BrowserCommentListContinuation = (() => {
function BrowserCommentListContinuation2(p) {
if (p) {
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
}
BrowserCommentListContinuation2.prototype.description = "";
BrowserCommentListContinuation2.prototype.mainCommentRequest = null;
BrowserCommentListContinuation2.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.description != null && Object.hasOwnProperty.call(m, "description"))
w.uint32(18).string(m.description);
if (m.mainCommentRequest != null && Object.hasOwnProperty.call(m, "mainCommentRequest"))
$root$2.MainCommentRequest.encode(m.mainCommentRequest, w.uint32(426).fork()).ldelim();
return w;
};
return BrowserCommentListContinuation2;
})();
const $Reader$1 = minimalExports.Reader;
const $root$1 = minimalExports.roots["default"] || (minimalExports.roots["default"] = {});
const CommentAction = $root$1.CommentAction = (() => {
function CommentAction2(p) {
if (p) {
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
}
CommentAction2.prototype.action = 0;
CommentAction2.prototype.commentId = "";
CommentAction2.decode = function decode(r, l, e) {
if (!(r instanceof $Reader$1))
r = $Reader$1.create(r);
var c = l === void 0 ? r.len : r.pos + l, m = new $root$1.CommentAction();
while (r.pos < c) {
var t = r.uint32();
if (t === e)
break;
switch (t >>> 3) {
case 1: {
m.action = r.int32();
break;
}
case 3: {
m.commentId = r.string();
break;
}
default:
r.skipType(t & 7);
break;
}
}
return m;
};
return CommentAction2;
})();
$root$1.Action = (() => {
const valuesById = {}, values = Object.create(valuesById);
values[valuesById[0] = "DEFAULT"] = 0;
values[valuesById[5] = "LIKE"] = 5;
values[valuesById[6] = "DELETE"] = 6;
return values;
})();
const $Reader = minimalExports.Reader;
const $root = minimalExports.roots["default"] || (minimalExports.roots["default"] = {});
const UpdateCommentParams = $root.UpdateCommentParams = (() => {
function UpdateCommentParams2(p) {
if (p) {
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
}
UpdateCommentParams2.prototype.commentId = "";
UpdateCommentParams2.decode = function decode(r, l, e) {
if (!(r instanceof $Reader))
r = $Reader.create(r);
var c = l === void 0 ? r.len : r.pos + l, m = new $root.UpdateCommentParams();
while (r.pos < c) {
var t = r.uint32();
if (t === e)
break;
switch (t >>> 3) {
case 1: {
m.commentId = r.string();
break;
}
default:
r.skipType(t & 7);
break;
}
}
return m;
};
return UpdateCommentParams2;
})();
var _GM_registerMenuCommand = /* @__PURE__ */ (() => typeof GM_registerMenuCommand != "undefined" ? GM_registerMenuCommand : void 0)();
var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)();
const cssLoader = (e) => {
const t = GM_getResourceText(e);
return GM_addStyle(t), t;
};
cssLoader("element-plus/dist/index.css");
const _hoisted_1$3 = {
key: 0,
class: "hot-ban-checker"
};
const _hoisted_2$3 = { class: "message" };
const _hoisted_3$3 = { class: "buttons" };
const _hoisted_4$3 = { class: "actions" };
const _sfc_main$4 = {
__name: "CommentActions",
props: ["comment"],
emits: ["delete", "checkHotBan"],
setup(__props, { emit: __emit }) {
const props = __props;
const emit = __emit;
const comment = props.comment;
const check2 = vue.inject("check");
const hotBanCheck2 = vue.inject("hotBanCheck");
const updating = vue.ref(false);
const showHotBanChecker = vue.ref(false);
const hotBanCheckerMessage = vue.ref("等待检查中……");
let hotBanCheckerController = vue.reactive({ isCancelled: false });
function updateState() {
updating.value = true;
check2(comment).then(() => {
updating.value = false;
ElementPlus.ElMessage({
type: comment.currentState == "NORMAL" ? "success" : "warning",
message: "更新成功,当前状态:" + translateState(comment.currentState)
});
}).catch((err) => {
updating.value = false;
let msg = err.message;
if (msg == "COMMENT_AREA_CLOSED") {
msg = "评论区已关闭";
}
ElementPlus.ElMessage.error("更新失败,因为:" + msg);
});
}
function copyComment(commentText) {
if (navigator.clipboard) {
navigator.clipboard.writeText(commentText).then(() => {
ElementPlus.ElMessage({
message: "评论已复制到剪贴板",
type: "success"
});
}).catch((err) => {
ElementPlus.ElMessage.error("无法复制文本,因为: " + err);
});
} else {
const textArea = document.createElement("textarea");
textArea.value = commentText;
document.body.appendChild(textArea);
textArea.select();
try {
document.execCommand("copy");
ElementPlus.ElMessage({
message: "评论已复制到剪贴板",
type: "success"
});
} catch (err) {
ElementPlus.ElMessage.error("无法复制文本,因为: " + err);
}
document.body.removeChild(textArea);
}
}
function askDelete() {
ElementPlus.ElMessageBox.confirm("确定要删除这条记录吗(这不会删除你在YouTube上发布的评论)?删除操作无法撤销!").then(() => {
emit("delete");
}).catch(() => {
});
}
async function toHotBanCheck() {
if (Date.now() - comment.recordedTime < 120 * 1e3) {
ElementPlus.ElMessage.warning(`当前时间距评论记录时间不足2分钟,状态不可信,请到 ${formatTimestamp(comment.recordedTime + 120 * 1e3)} 来检查`);
return;
}
if (comment.commentId.indexOf(".") == -1) {
try {
await ElementPlus.ElMessageBox.confirm(
"确认检查吗?该检查需要遍历热门评论区,请注意评论区的评论数量(总数大于3000的评论区慎重考虑)!数量太多将导致漫长的检查过程,同时频繁调用API可能会引发不可预料的后果!",
"警告",
{
confirmButtonText: "确定",
cancelButtonText: "取消"
}
);
} catch (err) {
return;
}
}
hotBanCheckerMessage.value = "正在重新检查评论状态……";
hotBanCheckerController.isCancelled = false;
showHotBanChecker.value = true;
try {
await check2(comment);
if (comment.currentState != "NORMAL") {
ElementPlus.ElMessage.error(`评论状态重新检查后为${translateState(comment.currentState)},无法继续进行检查`);
showHotBanChecker.value = false;
return;
}
} catch (err) {
let msg = err.message;
if (msg == "COMMENT_AREA_CLOSED") {
msg = "评论区已关闭";
}
ElementPlus.ElMessage.error("检查失败,因为" + msg);
showHotBanChecker.value = false;
return;
}
let observer = {
onCountChange(c, p) {
hotBanCheckerMessage.value = `正在搜索热门列表,已搜寻至:第${c}个 第${p}页`;
}
};
let notCancelled;
try {
notCancelled = await hotBanCheck2(comment, observer, hotBanCheckerController);
} catch (err) {
showHotBanChecker.value = false;
ElementPlus.ElMessage.error(err.message);
return;
}
if (notCancelled) {
if (comment.hotBan) {
ElementPlus.ElMessage.warning("你的评论未在热门列表找到,已被热门屏蔽,检查完成");
} else {
ElementPlus.ElMessage.success("你的评论已在热门列表找到,没有被热门屏蔽,检查完成");
}
}
showHotBanChecker.value = false;
}
return (_ctx, _cache) => {
const _component_el_button = vue.resolveComponent("el-button");
return vue.openBlock(), vue.createElementBlock("div", null, [
showHotBanChecker.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$3, [
_cache[2] || (_cache[2] = vue.createElementVNode("div", { class: "title" }, "热门屏蔽检查", -1)),
vue.createElementVNode("div", _hoisted_2$3, vue.toDisplayString(hotBanCheckerMessage.value), 1),
vue.createElementVNode("div", _hoisted_3$3, [
vue.createElementVNode("span", {
onClick: _cache[0] || (_cache[0] = ($event) => vue.unref(hotBanCheckerController).isCancelled = true)
}, "终止检查")
])
])) : vue.createCommentVNode("", true),
vue.createElementVNode("div", _hoisted_4$3, [
vue.unref(comment).isUserDelete == false ? (vue.openBlock(), vue.createBlock(_component_el_button, {
key: 0,
type: "primary",
plain: "",
onClick: updateState,
loading: updating.value
}, {
default: vue.withCtx(() => _cache[3] || (_cache[3] = [
vue.createTextVNode("更新状态")
])),
_: 1,
__: [3]
}, 8, ["loading"])) : vue.createCommentVNode("", true),
vue.unref(comment).currentState == "NORMAL" ? (vue.openBlock(), vue.createBlock(_component_el_button, {
key: 1,
type: "primary",
plain: "",
onClick: toHotBanCheck
}, {
default: vue.withCtx(() => _cache[4] || (_cache[4] = [
vue.createTextVNode("热门屏蔽检查")
])),
_: 1,
__: [4]
})) : vue.createCommentVNode("", true),
vue.createVNode(_component_el_button, {
type: "primary",
plain: "",
onClick: _cache[1] || (_cache[1] = ($event) => copyComment(vue.unref(comment).content))
}, {
default: vue.withCtx(() => _cache[5] || (_cache[5] = [
vue.createTextVNode("复制")
])),
_: 1,
__: [5]
}),
vue.createVNode(_component_el_button, {
type: "danger",
plain: "",
onClick: askDelete
}, {
default: vue.withCtx(() => _cache[6] || (_cache[6] = [
vue.createTextVNode("删除记录")
])),
_: 1,
__: [6]
})
])
]);
};
}
};
const CommentActions = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-e5341f8d"]]);
const _hoisted_1$2 = { class: "detail" };
const _hoisted_2$2 = { class: "info-table" };
const _hoisted_3$2 = { class: "comment-content" };
const _hoisted_4$2 = { key: 0 };
const _hoisted_5$2 = { key: 3 };
const _hoisted_6$2 = { class: "comment-content" };
const _hoisted_7$1 = { class: "pagination" };
const pageSize = 20;
const _sfc_main$3 = {
__name: "CommentHistories",
setup(__props) {
const deleteComment2 = vue.inject("deleteComment");
const db2 = vue.inject("db");
const comments = vue.reactive([]);
const loadingComments = vue.ref(false);
const prevTime = vue.ref(null);
const nextTime = vue.ref(null);
var prevStack = [null];
function loadComments(direction = "next") {
loadingComments.value = true;
comments.length = 0;
let time = null;
if (direction == "next") {
time = nextTime.value;
prevStack.push(time ? time : -1);
prevTime.value = prevStack[prevStack.length - 2];
} else if (direction == "prev") {
time = prevStack[prevStack.length - 2];
time = time == -1 ? null : time;
prevStack.pop();
prevTime.value = prevStack[prevStack.length - 2];
}
db2.transaction("comments").objectStore("comments").index("recordedTime").openCursor(time ? IDBKeyRange.upperBound(time) : null, "prev").onsuccess = (event) => {
var cursor = event.target.result;
if (cursor) {
if (comments.length < pageSize) {
comments.push(cursor.value);
cursor.continue();
} else {
nextTime.value = cursor.value.recordedTime;
loadingComments.value = false;
}
} else {
nextTime.value = null;
loadingComments.value = false;
}
};
}
loadComments();
function formatStateDesc(comment) {
switch (comment.currentState) {
case "NORMAL":
if (comment.hotBan === true) {
return "热门屏蔽";
} else if (comment.hotBan === false) {
return "完全正常";
} else {
return "正常";
}
case "DELETED":
if (comment.isUserDelete) {
return "用户删除";
} else {
return "已删除";
}
case "SHADOW_BAN":
return "仅自己可见";
case "NOT_CHECK":
return "还未检查";
}
}
function formatCommentArea(comment, needEmojiHead) {
var commentAreaInfo = comment.commentAreaInfo;
switch (comment.webPageType) {
case "WEB_PAGE_TYPE_WATCH":
return "📺 " + commentAreaInfo.videoId;
case "WEB_PAGE_TYPE_BROWSE":
return "📰" + commentAreaInfo.postId;
}
}
function formatHotBan(hotBan) {
if (hotBan == null) {
return "未检查";
}
return hotBan ? "是" : "否";
}
function deleteCommentItem(comment) {
deleteComment2(comment.commentId).then(() => {
const index = comments.findIndex((item) => item.commentId == comment.commentId);
if (index !== -1) {
comments.splice(index, 1);
ElementPlus.ElMessage.success("评论删除成功");
}
}).catch((err) => {
ElementPlus.ElMessage.error("评论删除失败");
console.error("delete comment from database failed", err);
});
}
return (_ctx, _cache) => {
const _component_el_table_column = vue.resolveComponent("el-table-column");
const _component_el_link = vue.resolveComponent("el-link");
const _component_el_table = vue.resolveComponent("el-table");
const _component_el_button = vue.resolveComponent("el-button");
return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
vue.createVNode(_component_el_table, {
data: comments,
"row-key": "commentId",
height: "100%",
class: "comment-list"
}, {
default: vue.withCtx(() => [
vue.createVNode(_component_el_table_column, {
prop: "content",
label: "评论内容",
align: "left",
"show-overflow-tooltip": ""
}),
vue.createVNode(_component_el_table_column, {
prop: "state",
label: "当前状态",
align: "center",
width: "136",
formatter: formatStateDesc
}),
vue.createVNode(_component_el_table_column, {
prop: "recordedTime",
label: "记录时间",
align: "center",
width: "160",
formatter: (comment) => vue.unref(formatTimestamp)(comment.recordedTime)
}, null, 8, ["formatter"]),
vue.createVNode(_component_el_table_column, {
prop: "area",
label: "所在评论区",
align: "center",
width: "240"
}, {
default: vue.withCtx(({ row }) => [
vue.createElementVNode("div", null, [
vue.createVNode(_component_el_link, {
type: "primary",
href: row.url,
class: vue.normalizeClass(["locate-link", { "post-locate-link": row.webPageType == "WEB_PAGE_TYPE_BROWSE" }])
}, {
default: vue.withCtx(() => [
vue.createTextVNode(vue.toDisplayString(formatCommentArea(row)), 1)
]),
_: 2
}, 1032, ["href", "class"])
])
]),
_: 1
}),
vue.createVNode(_component_el_table_column, { type: "expand" }, {
default: vue.withCtx(({ row }) => [
vue.createElementVNode("div", _hoisted_1$2, [
vue.createElementVNode("table", _hoisted_2$2, [
vue.createElementVNode("tbody", null, [
vue.createElementVNode("tr", null, [
_cache[2] || (_cache[2] = vue.createElementVNode("td", null, "评论内容", -1)),
vue.createElementVNode("td", _hoisted_3$2, vue.toDisplayString(row.content), 1)
]),
vue.createElementVNode("tr", null, [
_cache[3] || (_cache[3] = vue.createElementVNode("td", null, "当前状态", -1)),
vue.createElementVNode("td", null, vue.toDisplayString(vue.unref(translateState)(row.currentState)), 1)
]),
row.currentState == "DELETED" ? (vue.openBlock(), vue.createElementBlock("tr", _hoisted_4$2, [
_cache[4] || (_cache[4] = vue.createElementVNode("td", null, "用户删除", -1)),
vue.createElementVNode("td", null, vue.toDisplayString(row.isUserDelete ? "是" : "否"), 1)
])) : vue.createCommentVNode("", true),
vue.createElementVNode("tr", null, [
_cache[5] || (_cache[5] = vue.createElementVNode("td", null, "热门屏蔽", -1)),
vue.createElementVNode("td", null, vue.toDisplayString(formatHotBan(row.hotBan)), 1)
]),
vue.createElementVNode("tr", null, [
_cache[6] || (_cache[6] = vue.createElementVNode("td", null, "发送者", -1)),
vue.createElementVNode("td", null, vue.toDisplayString(row.displayName), 1)
]),
vue.createElementVNode("tr", null, [
_cache[7] || (_cache[7] = vue.createElementVNode("td", null, "评论ID", -1)),
vue.createElementVNode("td", null, vue.toDisplayString(row.commentId), 1)
]),
row.webPageType == "WEB_PAGE_TYPE_WATCH" ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [
_cache[9] || (_cache[9] = vue.createElementVNode("tr", null, [
vue.createElementVNode("td", null, "评论区类型"),
vue.createElementVNode("td", null, "视频")
], -1)),
vue.createElementVNode("tr", null, [
_cache[8] || (_cache[8] = vue.createElementVNode("td", null, "视频ID", -1)),
vue.createElementVNode("td", null, vue.toDisplayString(row.commentAreaInfo.videoId), 1)
])
], 64)) : row.webPageType == "WEB_PAGE_TYPE_BROWSE" ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 2 }, [
_cache[12] || (_cache[12] = vue.createElementVNode("tr", null, [
vue.createElementVNode("td", null, "评论区类型"),
vue.createElementVNode("td", null, "帖子")
], -1)),
vue.createElementVNode("tr", null, [
_cache[10] || (_cache[10] = vue.createElementVNode("td", null, "帖子所属频道ID", -1)),
vue.createElementVNode("td", null, vue.toDisplayString(row.commentAreaInfo.channelId), 1)
]),
vue.createElementVNode("tr", null, [
_cache[11] || (_cache[11] = vue.createElementVNode("td", null, "帖子ID", -1)),
vue.createElementVNode("td", null, vue.toDisplayString(row.commentAreaInfo.postId), 1)
])
], 64)) : vue.createCommentVNode("", true),
vue.createElementVNode("tr", null, [
_cache[13] || (_cache[13] = vue.createElementVNode("td", null, "点赞数", -1)),
vue.createElementVNode("td", null, vue.toDisplayString(row.likeCount), 1)
]),
row.commentId.indexOf(".") == -1 ? (vue.openBlock(), vue.createElementBlock("tr", _hoisted_5$2, [
_cache[14] || (_cache[14] = vue.createElementVNode("td", null, "回复数", -1)),
vue.createElementVNode("td", null, vue.toDisplayString(row.replyCount), 1)
])) : vue.createCommentVNode("", true),
vue.createElementVNode("tr", null, [
_cache[15] || (_cache[15] = vue.createElementVNode("td", null, "记录时间", -1)),
vue.createElementVNode("td", null, vue.toDisplayString(vue.unref(formatTimestamp)(row.recordedTime)), 1)
]),
vue.createElementVNode("tr", null, [
_cache[16] || (_cache[16] = vue.createElementVNode("td", null, "更新时间", -1)),
vue.createElementVNode("td", null, vue.toDisplayString(vue.unref(formatTimestamp)(row.updatedTime)), 1)
])
])
]),
vue.createElementVNode("details", null, [
_cache[17] || (_cache[17] = vue.createElementVNode("summary", null, "历史检查记录", -1)),
vue.createVNode(_component_el_table, {
data: row.histories,
style: { "width": "100%" }
}, {
default: vue.withCtx(() => [
vue.createVNode(_component_el_table_column, {
prop: "time",
label: "时间戳",
width: "160",
formatter: (history) => vue.unref(formatTimestamp)(history.time)
}, null, 8, ["formatter"]),
vue.createVNode(_component_el_table_column, {
prop: "state",
label: "状态",
width: "136",
formatter: (history) => vue.unref(translateState)(history.state)
}, null, 8, ["formatter"]),
vue.createVNode(_component_el_table_column, {
prop: "hotBan",
label: "热门屏蔽",
width: "120",
formatter: (history) => formatHotBan(history.hotBan)
}, null, 8, ["formatter"]),
vue.createVNode(_component_el_table_column, {
prop: "content",
label: "评论内容",
"show-overflow-tooltip": ""
}),
vue.createVNode(_component_el_table_column, { type: "expand" }, {
default: vue.withCtx(({ row: row2 }) => [
vue.createElementVNode("div", _hoisted_6$2, vue.toDisplayString(row2.content), 1)
]),
_: 2
}, 1024)
]),
_: 2
}, 1032, ["data"])
]),
vue.createVNode(CommentActions, {
comment: row,
onDelete: ($event) => deleteCommentItem(row)
}, null, 8, ["comment", "onDelete"])
])
]),
_: 1
})
]),
_: 1
}, 8, ["data"]),
vue.createElementVNode("div", _hoisted_7$1, [
prevTime.value ? (vue.openBlock(), vue.createBlock(_component_el_button, {
key: 0,
onClick: _cache[0] || (_cache[0] = ($event) => loadComments("prev")),
disabled: loadingComments.value
}, {
default: vue.withCtx(() => [
vue.createTextVNode("< " + vue.toDisplayString(prevTime.value == -1 ? "NOW" : vue.unref(formatTimestamp)(prevTime.value)), 1)
]),
_: 1
}, 8, ["disabled"])) : vue.createCommentVNode("", true),
nextTime.value ? (vue.openBlock(), vue.createBlock(_component_el_button, {
key: 1,
onClick: _cache[1] || (_cache[1] = ($event) => loadComments("next")),
disabled: loadingComments.value
}, {
default: vue.withCtx(() => [
vue.createTextVNode(vue.toDisplayString(vue.unref(formatTimestamp)(nextTime.value)) + " >", 1)
]),
_: 1
}, 8, ["disabled"])) : vue.createCommentVNode("", true)
])
], 64);
};
}
};
const CommentHistories = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-80f074da"]]);
function createVideoRootCommentListContinuation(channelId, videoId, isLatestSort) {
let payload = {
uField3: 6,
commentAreaWrapper: {
videoId
},
mainCommentRequest: {
sectionIdentifier: "comments-section",
commentParameters: {
videoId,
sortType: isLatestSort ? 1 : 0
}
}
};
let encoded = NextContinuation.encode(payload);
let buffer = encoded.finish();
let continuation = btoa(String.fromCharCode(...buffer));
return standardBase64ToUrlSafe(continuation);
}
function createVideoReplyCommentListContinuation(channelId, videoId, rootCommentId, isLatestSort) {
let payload = {
uField3: 6,
commentAreaWrapper: {
videoId
},
mainCommentRequest: {
sectionIdentifier: `comment-replies-item-${rootCommentId}`,
commentReplyParameters: {
rootCommentId,
channelId,
videoId,
pageSize: 10,
sortParam: {
sortType: 1
}
}
}
};
let encoded = NextContinuation.encode(payload);
let buffer = encoded.finish();
let continuation = btoa(String.fromCharCode(...buffer));
return standardBase64ToUrlSafe(continuation);
}
function createPostRootCommentListContinuation(channelId, postId, isLatestSort) {
let payload = {
description: "community",
mainCommentRequest: {
sectionIdentifier: "comments-section",
commentParameters: {
channelId,
postId,
sortType: isLatestSort ? 1 : 0
}
}
};
let encoded = BrowserCommentListContinuation.encode(payload);
let buffer = encoded.finish();
let continuation = btoa(String.fromCharCode(...buffer));
continuation = standardBase64ToUrlSafe(continuation);
payload = {
request: {
description: "FEcomment_post_detail_page_web_top_level",
continuationBase64: continuation
}
};
encoded = BrowserContinuation.encode(payload);
buffer = encoded.finish();
continuation = btoa(String.fromCharCode(...buffer));
return standardBase64ToUrlSafe(continuation);
}
function createPostReplyCommentListContinuation(channelId, postId, rootCommentId, isLatestSort) {
let payload = {
description: "community",
mainCommentRequest: {
sectionIdentifier: `comment-replies-item-${rootCommentId}`,
commentReplyParameters: {
rootCommentId,
channelId,
postId,
pageSize: 10,
sortParam: {
sortType: 1
}
}
}
};
let encoded = BrowserCommentListContinuation.encode(payload);
let buffer = encoded.finish();
continuation = btoa(String.fromCharCode(...buffer));
continuation = standardBase64ToUrlSafe(continuation);
payload = {
request: {
description: "FEcomment_post_detail_page_web_replies_page",
continuationBase64: continuation
}
};
encoded = BrowserContinuation.encode(payload);
buffer = encoded.finish();
let continuation = btoa(String.fromCharCode(...buffer));
return standardBase64ToUrlSafe(continuation);
}
const _hoisted_1$1 = { class: "youtube-comment" };
const _hoisted_2$1 = { class: "avatar-container" };
const _hoisted_3$1 = ["href"];
const _hoisted_4$1 = ["src", "alt"];
const _hoisted_5$1 = { class: "comment-content" };
const _hoisted_6$1 = { class: "comment-header" };
const _hoisted_7 = ["href"];
const _hoisted_8 = { class: "published-at" };
const _hoisted_9 = { class: "comment-text" };
const _hoisted_10 = { class: "comment-actions" };
const _hoisted_11 = { class: "action-text" };
const _hoisted_12 = { class: "action-text" };
const _hoisted_13 = ["href"];
const _sfc_main$2 = {
__name: "YouTubeComment",
props: ["comment"],
setup(__props) {
return (_ctx, _cache) => {
return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1, [
vue.createElementVNode("div", _hoisted_2$1, [
vue.createElementVNode("a", {
href: "https://www.youtube.com/" + __props.comment.userDisplayName,
target: "_blank",
rel: "noopener noreferrer"
}, [
vue.createElementVNode("img", {
src: __props.comment.userProfileImageUrl,
alt: __props.comment.authorDisplayName,
class: "avatar"
}, null, 8, _hoisted_4$1)
], 8, _hoisted_3$1)
]),
vue.createElementVNode("div", _hoisted_5$1, [
vue.createElementVNode("div", _hoisted_6$1, [
vue.createElementVNode("a", {
href: "https://www.youtube.com/" + __props.comment.userDisplayName,
target: "_blank",
rel: "noopener noreferrer",
class: "author-name"
}, vue.toDisplayString(__props.comment.userDisplayName), 9, _hoisted_7),
vue.createElementVNode("span", _hoisted_8, vue.toDisplayString(__props.comment.publishedTime), 1)
]),
vue.createElementVNode("p", _hoisted_9, vue.toDisplayString(__props.comment.contentText), 1),
vue.createElementVNode("div", _hoisted_10, [
vue.createElementVNode("button", {
class: "button",
onClick: _cache[0] || (_cache[0] = ($event) => vue.unref(ElementPlus.ElMessage).info("需要点赞评论请定位至评论"))
}, [
_cache[2] || (_cache[2] = vue.createElementVNode("svg", {
class: "icon",
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 24 24"
}, [
vue.createElementVNode("path", { d: "M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.31C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3z" })
], -1)),
vue.createElementVNode("span", _hoisted_11, vue.toDisplayString(__props.comment.likeCount), 1)
]),
vue.createElementVNode("button", {
class: "button",
onClick: _cache[1] || (_cache[1] = ($event) => vue.unref(ElementPlus.ElMessage).info("需要查看回复请定位评论查看"))
}, [
_cache[3] || (_cache[3] = vue.createElementVNode("svg", {
t: "1756005965374",
class: "icon",
viewBox: "0 0 1024 1024",
version: "1.1",
xmlns: "http://www.w3.org/2000/svg",
"p-id": "5216",
width: "200",
height: "200"
}, [
vue.createElementVNode("path", {
d: "M1024 640l-3.5 41.6c-6.5 78.1-27.7 154-62.2 223.9-7.5 15.2-30.4 10-30.4-7V800c0-61.9-25.1-117.9-65.6-158.4C821.9 601.1 765.9 576 704 576H552c-4.4 0-8 3.6-8 8v179.6c0 13.9-16.5 21.2-26.8 11.8L160 447.9 516.5 76.7c10-10.4 27.5-3.3 27.5 11.1V280c0 4.4 3.6 8 8 8h120c97.2 0 185.2 39.4 248.9 103.1S1024 542.8 1024 640z",
"p-id": "5217"
}),
vue.createElementVNode("path", {
d: "M356.7 95.1L0 453.1l357.3 326.1c10.3 9.4 26.8 2.1 26.8-11.8 0-32.1-13.5-62.7-37.2-84.4L92.5 450.9l258.2-259.1c21.3-21.4 33.3-50.4 33.3-80.6v-4.8c0-14.3-17.3-21.4-27.3-11.3z",
"p-id": "5218"
})
], -1)),
vue.createElementVNode("span", _hoisted_12, vue.toDisplayString(__props.comment.replyCount), 1)
]),
vue.createElementVNode("a", {
class: "button",
href: __props.comment.url,
target: "_blank"
}, _cache[4] || (_cache[4] = [
vue.createElementVNode("svg", {
t: "1756007306700",
class: "icon",
viewBox: "0 0 1024 1024",
version: "1.1",
xmlns: "http://www.w3.org/2000/svg",
"p-id": "7302",
width: "200",
height: "200"
}, [
vue.createElementVNode("path", {
d: "M511.36599 512.177066m-201.557982 0a201.557983 201.557983 0 1 0 403.115965 0 201.557983 201.557983 0 1 0-403.115965 0Z",
"p-id": "7303"
}),
vue.createElementVNode("path", {
d: "M990.163299 477.654949h-78.434431a34.350763 34.350763 0 0 0-5.883154 0.514062c-16.278629-191.288167-168.532358-343.770368-359.706288-360.357433a33.619652 33.619652 0 0 0 0.376979-5.060655V34.270797a34.270797 34.270797 0 0 0-68.541595 0v78.434432a35.059026 35.059026 0 0 0 0.354132 4.923571c-191.790805 15.844532-344.798492 168.372427-361.385558 359.957608a34.556387 34.556387 0 0 0-4.226732-0.274167H34.270797a34.270797 34.270797 0 1 0 0 68.541595h78.445855a32.762882 32.762882 0 0 0 4.12392-0.262743c16.02731 192.076395 169.217774 345.17547 361.328439 361.134239a34.853401 34.853401 0 0 0-0.308437 4.569439v78.434432a34.270797 34.270797 0 0 0 68.541595 0v-78.480126a34.670623 34.670623 0 0 0-0.319861-4.649405c191.368132-16.621337 343.747521-169.377704 359.843372-360.905766a35.001908 35.001908 0 0 0 5.837459 0.502638h78.434431a34.270797 34.270797 0 0 0 34.270798-34.270797 34.270797 34.270797 0 0 0-34.305069-34.270798z m-177.065786 161.940941a328.656946 328.656946 0 1 1 25.703098-127.418824 326.440768 326.440768 0 0 1-25.748792 127.418824z",
"p-id": "7304"
})
], -1),
vue.createElementVNode("span", { class: "action-text" }, "定位", -1)
]), 8, _hoisted_13)
]),
vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
])
]);
};
}
};
const YouTubeComment = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__scopeId", "data-v-2a518d4b"]]);
const _hoisted_1 = { class: "hot-ban-comment-searcher" };
const _hoisted_2 = {
key: 1,
class: "warning"
};
const _hoisted_3 = {
key: 2,
class: "search-progress"
};
const _hoisted_4 = { "infinite-scroll-distance": 500 };
const _hoisted_5 = { class: "footer" };
const _hoisted_6 = { key: 1 };
const _sfc_main$1 = {
__name: "HotBanCommentSearcher",
setup(__props) {
const originalFetch2 = vue.inject("originalFetch");
const getAuthorization2 = vue.inject("getAuthorization");
const getContext2 = vue.inject("getContext");
const showNcs = vue.ref(true);
const showWarning = vue.ref(false);
const showSearchProgress = vue.ref(false);
const showResults = vue.ref(false);
const progressMsg = vue.ref("加载中...");
const comments = vue.reactive([]);
const hasNext = vue.ref(true);
const loading = vue.ref(false);
const progStatus = vue.ref("");
let nextContinuation;
let cancelled = false;
let hotCommentIdSet = /* @__PURE__ */ new Set();
let url = createUrl();
let api;
let channelId;
let TYPE = null;
if (url.searchParams.has("v")) {
TYPE = "WEB_PAGE_TYPE_WATCH";
api = "https://www.youtube.com/youtubei/v1/next?prettyPrint=false";
} else if (url.pathname.split("/").includes("post")) {
TYPE = "WEB_PAGE_TYPE_BROWSE";
api = "https://www.youtube.com/youtubei/v1/browse?prettyPrint=false";
}
if (TYPE) {
showNcs.value = false;
showWarning.value = true;
}
async function onSearch() {
var _a, _b, _c, _d, _e, _f, _g;
showWarning.value = false;
showSearchProgress.value = true;
let continuation = null;
if (TYPE === "WEB_PAGE_TYPE_WATCH") {
continuation = createVideoRootCommentListContinuation(null, url.searchParams.get("v"), false);
nextContinuation = createVideoRootCommentListContinuation(null, url.searchParams.get("v"), true);
} else if (TYPE === "WEB_PAGE_TYPE_BROWSE") {
channelId = (_b = (_a = ytInitialData.metadata) == null ? void 0 : _a.channelMetadataRenderer) == null ? void 0 : _b.externalId;
if (!channelId) {
progressMsg.value = "无法获取频道ID,请尝试刷新页面后重试!";
}
continuation = createPostRootCommentListContinuation(channelId, url.pathname.split("/")[2], false);
nextContinuation = createPostRootCommentListContinuation(channelId, url.pathname.split("/")[2], true);
}
let count = 0;
while (continuation) {
let data = {
context: getContext2(),
continuation
};
let options = {
method: "POST",
body: JSON.stringify(data),
headers: {
//因为我搜索的是别人的热门屏蔽评论,所以带上认证信息也没啥(还能减轻风控?)
authorization: getAuthorization2()
}
};
if (cancelled) {
return;
}
let response;
try {
response = await (await originalFetch2(api, options)).json();
} catch (err) {
progressMsg.value = "获取热门列表失败,您可以关闭后重试!";
return;
}
let mutations = response.frameworkUpdates.entityBatchUpdate.mutations;
for (let mutation of mutations) {
if (mutation.payload.commentEntityPayload) {
hotCommentIdSet.add(mutation.payload.commentEntityPayload.properties.commentId);
count++;
progressMsg.value = `正在获取热门评论(已获取 ${count} 个)……`;
}
}
continuation = null;
for (const endpoint of response.onResponseReceivedEndpoints) {
const items = ((_c = endpoint.appendContinuationItemsAction) == null ? void 0 : _c.continuationItems) || ((_d = endpoint.reloadContinuationItemsCommand) == null ? void 0 : _d.continuationItems);
if (!items) continue;
for (const item of items) {
const token = (_g = (_f = (_e = item.continuationItemRenderer) == null ? void 0 : _e.continuationEndpoint) == null ? void 0 : _f.continuationCommand) == null ? void 0 : _g.token;
if (token) {
continuation = token;
break;
}
}
if (continuation) break;
}
}
next();
}
async function next() {
var _a, _b, _c, _d, _e;
if (!hasNext.value || loading.value || cancelled) {
return;
}
loading.value = true;
showSearchProgress.value = false;
showResults.value = true;
let count = 0;
while (count < 20) {
let data = {
context: getContext2(),
continuation: nextContinuation
};
let options = {
method: "POST",
body: JSON.stringify(data),
headers: {
authorization: getAuthorization2()
}
};
if (cancelled) {
return;
}
let response;
try {
response = await (await originalFetch2(api, options)).json();
} catch (err) {
progStatus.value = "exception";
return;
}
nextContinuation = null;
for (const endpoint of response.onResponseReceivedEndpoints) {
const items = ((_a = endpoint.appendContinuationItemsAction) == null ? void 0 : _a.continuationItems) || ((_b = endpoint.reloadContinuationItemsCommand) == null ? void 0 : _b.continuationItems);
if (!items) continue;
for (const item of items) {
const token = (_e = (_d = (_c = item.continuationItemRenderer) == null ? void 0 : _c.continuationEndpoint) == null ? void 0 : _d.continuationCommand) == null ? void 0 : _e.token;
if (token) {
nextContinuation = token;
break;
}
}
if (nextContinuation) break;
}
let mutations = response.frameworkUpdates.entityBatchUpdate.mutations;
for (let i = 0; i < mutations.length; i++) {
let mutation = mutations[i];
if (mutation.payload.commentEntityPayload) {
let entity = mutation.payload.commentEntityPayload;
let commentId = entity.properties.commentId;
if (!hotCommentIdSet.has(commentId)) {
let likeCount = parseInt(entity.toolbar.likeCountNotliked);
likeCount = likeCount ? likeCount : 0;
let replyCount = parseInt(entity.toolbar.replyCount);
replyCount = replyCount ? replyCount : 0;
let url2 = mutations[i + 1].payload.commentSurfaceEntityPayload.publishedTimeCommand.innertubeCommand.commandMetadata.webCommandMetadata.url;
count++;
comments.push({
commentId,
url: url2,
userDisplayName: entity.author.displayName,
userProfileImageUrl: entity.avatar.image.sources[0].url,
likeCount,
replyCount,
publishedTime: entity.properties.publishedTime,
contentText: entity.properties.content.content
});
}
}
}
if (!nextContinuation) {
hasNext.value = false;
break;
}
}
loading.value = false;
}
vue.onUnmounted(() => {
cancelled = true;
});
return (_ctx, _cache) => {
const _component_el_empty = vue.resolveComponent("el-empty");
const _component_el_divider = vue.resolveComponent("el-divider");
const _component_el_button = vue.resolveComponent("el-button");
const _component_el_progress = vue.resolveComponent("el-progress");
const _component_el_scrollbar = vue.resolveComponent("el-scrollbar");
const _directive_infinite_scroll = vue.resolveDirective("infinite-scroll");
return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
showNcs.value ? (vue.openBlock(), vue.createBlock(_component_el_empty, {
key: 0,
description: "请在有评论区(视频、帖子)的页面使用此功能",
class: "not-comment-section"
})) : vue.createCommentVNode("", true),
showWarning.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2, [
_cache[1] || (_cache[1] = vue.createElementVNode("svg", {
t: "1756953289758",
class: "warn-icon",
viewBox: "0 0 1024 1024",
version: "1.1",
xmlns: "http://www.w3.org/2000/svg",
"p-id": "4518",
width: "64",
height: "64"
}, [
vue.createElementVNode("path", {
d: "M1001.661867 796.544c48.896 84.906667 7.68 157.013333-87.552 157.013333H110.781867c-97.834667 0-139.050667-69.504-90.112-157.013333l401.664-666.88c48.896-87.552 128.725333-87.552 177.664 0l401.664 666.88zM479.165867 296.533333v341.333334a32 32 0 1 0 64 0v-341.333334a32 32 0 1 0-64 0z m0 469.333334v42.666666a32 32 0 1 0 64 0v-42.666666a32 32 0 1 0-64 0z",
fill: "#FAAD14",
"p-id": "4519"
})
], -1)),
_cache[2] || (_cache[2] = vue.createElementVNode("h2", { class: "warning-title" }, "警告", -1)),
_cache[3] || (_cache[3] = vue.createElementVNode("p", { class: "warning-text" }, [
vue.createTextVNode("将会获取所有热门评论,之后懒加载按时间评论"),
vue.createElementVNode("br"),
vue.createTextVNode(" 评论区数量过多(例如超过 5000 条),获取热门评论的过程将非常漫长,且过多的API调用可能导致不可预料的后果,请酌情使用! ")
], -1)),
vue.createVNode(_component_el_divider, { class: "warning-divider" }),
vue.createVNode(_component_el_button, {
type: "primary",
onClick: onSearch
}, {
default: vue.withCtx(() => _cache[0] || (_cache[0] = [
vue.createTextVNode("搜索")
])),
_: 1,
__: [0]
})
])) : vue.createCommentVNode("", true),
showSearchProgress.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3, [
vue.createElementVNode("p", null, vue.toDisplayString(progressMsg.value), 1),
vue.createVNode(_component_el_progress, {
percentage: 50,
indeterminate: true,
"show-text": false
})
])) : vue.createCommentVNode("", true),
showResults.value ? (vue.openBlock(), vue.createBlock(_component_el_scrollbar, {
key: 3,
class: "search-results"
}, {
default: vue.withCtx(() => [
vue.withDirectives((vue.openBlock(), vue.createElementBlock("div", _hoisted_4, [
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(comments, (comment) => {
return vue.openBlock(), vue.createBlock(YouTubeComment, {
key: comment.commentId,
comment
}, null, 8, ["comment"]);
}), 128)),
vue.createElementVNode("div", _hoisted_5, [
loading.value ? (vue.openBlock(), vue.createBlock(_component_el_progress, {
key: 0,
percentage: 50,
indeterminate: true,
"show-text": false,
status: progStatus.value,
duration: 1
}, null, 8, ["status"])) : vue.createCommentVNode("", true),
!hasNext.value ? (vue.openBlock(), vue.createElementBlock("span", _hoisted_6, "- PAGE END -")) : vue.createCommentVNode("", true)
])
])), [
[_directive_infinite_scroll, next]
])
]),
_: 1
})) : vue.createCommentVNode("", true)
]);
};
}
};
const HotBanCommentSearcher = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-b5a0c87e"]]);
const _sfc_main = {
__name: "App",
setup(__props) {
let historiesVisible = vue.ref(false);
let searchHotBanVisible = vue.ref(false);
const menuListener = vue.inject("menuListener");
menuListener.onOpenHistory = () => {
historiesVisible.value = true;
};
menuListener.onSearchHotBan = () => {
searchHotBanVisible.value = true;
};
return (_ctx, _cache) => {
const _component_el_dialog = vue.resolveComponent("el-dialog");
return vue.openBlock(), vue.createElementBlock("div", null, [
vue.createVNode(_component_el_dialog, {
modelValue: vue.unref(historiesVisible),
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.isRef(historiesVisible) ? historiesVisible.value = $event : historiesVisible = $event),
"z-index": 3e3,
title: "历史评论列表",
width: "80%",
style: { "height": "92vh" },
"body-class": "dialog-body",
"align-center": "",
"destroy-on-close": ""
}, {
default: vue.withCtx(() => [
vue.createVNode(CommentHistories)
]),
_: 1
}, 8, ["modelValue"]),
vue.createVNode(_component_el_dialog, {
modelValue: vue.unref(searchHotBanVisible),
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => vue.isRef(searchHotBanVisible) ? searchHotBanVisible.value = $event : searchHotBanVisible = $event),
"z-index": 3e3,
title: "热门屏蔽评论搜索",
width: "80%",
style: { "height": "92vh" },
"body-class": "dialog-body",
"align-center": "",
"destroy-on-close": ""
}, {
default: vue.withCtx(() => [
vue.createVNode(HotBanCommentSearcher)
]),
_: 1
}, 8, ["modelValue"])
]);
};
}
};
const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-1d7cd9ea"]]);
const originalFetch = _unsafeWindow.fetch;
var authorizationCache = null;
var contextCache = null;
var trueLoaded = false;
var db = null;
const checkingCommentIdSet = /* @__PURE__ */ new Set();
function getAuthorization() {
return authorizationCache;
}
function getContext() {
return contextCache;
}
function waitForElement(observeSelector, targetSelector) {
return new Promise((resolve) => {
const parent = document.querySelector(observeSelector);
if (!parent) return;
const found = parent.querySelector(targetSelector);
if (found) {
resolve(found);
return;
}
const observer = new MutationObserver(() => {
const el = parent.querySelector(targetSelector);
if (el) {
observer.disconnect();
resolve(el);
}
});
observer.observe(parent, { childList: true, subtree: true });
});
}
async function findComment(commentRecord, isLogin = true) {
let continuation;
let requestUrl;
if (commentRecord.webPageType == "WEB_PAGE_TYPE_WATCH") {
let payload = {
uField3: 6,
commentAreaWrapper: {
videoId: commentRecord.commentAreaInfo.videoId
},
mainCommentRequest: {
sectionIdentifier: "comments-section",
commentParameters: {
videoId: commentRecord.commentAreaInfo.videoId,
targetCommentId: commentRecord.commentId
}
}
};
let encoded = NextContinuation.encode(payload);
let buffer = encoded.finish();
continuation = btoa(String.fromCharCode(...buffer));
continuation = standardBase64ToUrlSafe(continuation);
requestUrl = "https://www.youtube.com/youtubei/v1/next?prettyPrint=false";
} else if (commentRecord.webPageType == "WEB_PAGE_TYPE_BROWSE") {
let payload = {
description: "community",
mainCommentRequest: {
sectionIdentifier: "comments-section",
commentParameters: {
channelId: commentRecord.commentAreaInfo.channelId,
postId: commentRecord.commentAreaInfo.postId,
targetCommentId: commentRecord.commentId
}
}
};
let encoded = BrowserCommentListContinuation.encode(payload);
let buffer = encoded.finish();
continuation = btoa(String.fromCharCode(...buffer));
continuation = standardBase64ToUrlSafe(continuation);
payload = {
request: {
description: "FEcomment_post_detail_page_web_top_level",
continuationBase64: continuation
}
};
encoded = BrowserContinuation.encode(payload);
buffer = encoded.finish();
continuation = btoa(String.fromCharCode(...buffer));
continuation = standardBase64ToUrlSafe(continuation);
requestUrl = "https://www.youtube.com/youtubei/v1/browse?prettyPrint=false";
} else {
throw new Error("Unsupported webPageType : " + commentRecord.webPageType);
}
let data = {
context: contextCache,
continuation
};
let headers = {};
if (isLogin) {
headers.authorization = authorizationCache;
}
let options = {
method: "POST",
body: JSON.stringify(data),
headers
};
let response = await (await originalFetch(requestUrl, options)).json();
let loggedOut = response.responseContext.mainAppWebResponseContext.loggedOut;
if (loggedOut == isLogin) {
console.warn("登录状态不符,需要的:" + isLogin + " API返回的:" + !loggedOut);
}
if (!response.frameworkUpdates) {
throw new Error("COMMENT_AREA_CLOSED");
}
let mutations = response.frameworkUpdates.entityBatchUpdate.mutations;
for (let i = 0; i < mutations.length; i++) {
let mutation = mutations[i];
if (mutation.payload.commentEntityPayload) {
let entity = mutation.payload.commentEntityPayload;
let commentId = entity.properties.commentId;
if (commentId == commentRecord.commentId) {
let likeCount = parseInt(entity.toolbar.likeCountNotliked);
likeCount = likeCount ? likeCount : 0;
let replyCount = parseInt(entity.toolbar.replyCount);
replyCount = replyCount ? replyCount : 0;
return {
content: entity.properties.content.content,
commentId,
likeCount,
replyCount
};
}
}
}
}
async function insertComment() {
}
async function updateComment() {
}
async function selectComment() {
}
async function deleteComment() {
}
function appendHistory(commentRecord) {
let histories = commentRecord.histories;
let needPush = false;
if (histories.length == 0) {
needPush = true;
} else {
let lastHistory = histories[histories.length - 1];
needPush = lastHistory.state != commentRecord.currentState || lastHistory.content != commentRecord.content || lastHistory.hotBan != commentRecord.hotBan;
}
if (needPush) {
histories.push({
time: commentRecord.updatedTime,
content: commentRecord.content,
state: commentRecord.currentState,
hotBan: commentRecord.hotBan
});
}
}
function updateRecord(commentRecord, state, result) {
commentRecord.updatedTime = Date.now();
if (state) {
commentRecord.currentState = state;
}
if (result) {
commentRecord.likeCount = result.likeCount;
commentRecord.replyCount = result.replyCount;
commentRecord.content = result.content;
}
appendHistory(commentRecord);
updateComment(commentRecord);
}
async function check(commentRecord) {
let loggedOutResult = await findComment(commentRecord, false);
if (loggedOutResult) {
updateRecord(commentRecord, "NORMAL", loggedOutResult);
return;
}
let loggedInResult = await findComment(commentRecord, true);
if (loggedInResult) {
updateRecord(commentRecord, "SHADOW_BAN", loggedInResult);
} else {
updateRecord(commentRecord, "DELETED");
}
}
async function toCheck(commentRecord) {
checkingCommentIdSet.add(commentRecord.commentId);
let selector;
let pathname = window.location.pathname;
if (pathname.startsWith("/post") || pathname.startsWith("/channel")) {
selector = "ytd-item-section-renderer#sections";
} else {
selector = "#comments";
}
let element = (await waitForElement(selector, `a[href='${commentRecord.url}']`)).parentNode.parentNode.parentNode.parentNode;
let div = document.createElement("div");
div.style.marginTop = "8px";
div.id = "checker";
element.append(div);
let app = vue.createApp(CommentChecker);
app.use(ElementPlus);
app.provide("check", check);
app.provide("hotBanCheck", hotBanCheck);
app.provide("commentRecord", commentRecord);
app.provide("interval", 5);
app.provide("onUnblock", (commentRecord2) => {
checkingCommentIdSet.delete(commentRecord2.commentId);
});
app.provide("onClose", (commentRecord2) => {
checkingCommentIdSet.delete(commentRecord2.commentId);
console.log("评论检查完成", commentRecord2);
div.remove();
});
app.mount(div);
}
function createCommentListRequest(commentRecord, isLatestSort) {
let api;
let continuation;
if (commentRecord.webPageType == "WEB_PAGE_TYPE_WATCH") {
api = "https://www.youtube.com/youtubei/v1/next?prettyPrint=false";
if (commentRecord.commentId.indexOf(".") != -1) {
let rootCommentId = commentRecord.commentId.split(".")[0];
continuation = createVideoReplyCommentListContinuation(
commentRecord.commentAreaInfo.channelId,
commentRecord.commentAreaInfo.videoId,
rootCommentId
);
} else {
continuation = createVideoRootCommentListContinuation(
commentRecord.commentAreaInfo.channelId,
commentRecord.commentAreaInfo.videoId,
isLatestSort
);
}
} else if (commentRecord.webPageType == "WEB_PAGE_TYPE_BROWSE") {
api = "https://www.youtube.com/youtubei/v1/browse?prettyPrint=false";
if (commentRecord.commentId.indexOf(".") != -1) {
let rootCommentId = commentRecord.commentId.split(".")[0];
continuation = createPostReplyCommentListContinuation(
commentRecord.commentAreaInfo.channelId,
commentRecord.commentAreaInfo.postId,
rootCommentId
);
} else {
continuation = createPostRootCommentListContinuation(
commentRecord.commentAreaInfo.channelId,
commentRecord.commentAreaInfo.postId,
isLatestSort
);
}
}
return { api, continuation };
}
async function hotBanCheck(commentRecord, observer, controller) {
var _a, _b, _c, _d, _e;
if (!observer) {
observer = {
onCountChange(c, p) {
}
};
}
if (!controller) {
controller = {
isCancelled: false
};
}
let pageCpunt = 0;
let commentCount = 0;
let { api, continuation } = createCommentListRequest(commentRecord);
while (continuation) {
if (controller.isCancelled) {
return false;
}
let data = {
context: contextCache,
continuation
};
let options = {
method: "POST",
body: JSON.stringify(data)
};
let response = await (await originalFetch(api, options)).json();
pageCpunt++;
if (!response.frameworkUpdates) {
commentRecord.hotBan = true;
updateRecord(commentRecord);
return true;
}
for (let mutation of response.frameworkUpdates.entityBatchUpdate.mutations) {
let entity = mutation.payload.commentEntityPayload;
if (entity) {
let commentId = entity.properties.commentId;
commentCount++;
observer.onCountChange(commentCount, pageCpunt);
if (commentId == commentRecord.commentId) {
commentRecord.hotBan = false;
updateRecord(commentRecord);
return true;
}
}
}
continuation = null;
for (const endpoint of response.onResponseReceivedEndpoints) {
const items = ((_a = endpoint.appendContinuationItemsAction) == null ? void 0 : _a.continuationItems) || ((_b = endpoint.reloadContinuationItemsCommand) == null ? void 0 : _b.continuationItems);
if (!items) continue;
for (const item of items) {
const token = (_e = (_d = (_c = item.continuationItemRenderer) == null ? void 0 : _c.continuationEndpoint) == null ? void 0 : _d.continuationCommand) == null ? void 0 : _e.token;
if (token) {
continuation = token;
break;
}
}
if (continuation) break;
}
}
commentRecord.hotBan = true;
updateRecord(commentRecord);
return true;
}
async function handlerYoutubei(request) {
let requsetClone = request.clone();
let requestBody = await requsetClone.json();
if (requestBody && requestBody.context) {
contextCache = requestBody.context;
if (!trueLoaded) {
console.log("fetch已成功劫持");
_GM_registerMenuCommand("✅ 脚本已完全加载");
trueLoaded = true;
}
}
if (request.url.startsWith("https://www.youtube.com/youtubei/v1/comment/create_comment")) {
let response = await originalFetch(request);
if (response.status != 200) {
return response;
}
let responseClone = response.clone();
try {
let json = await responseClone.json();
if (json.frameworkUpdates.entityBatchUpdate.mutations.length == 1) {
return response;
}
let entity = json.frameworkUpdates.entityBatchUpdate.mutations[0].payload.commentEntityPayload;
let innertubeCommand = json.frameworkUpdates.entityBatchUpdate.mutations[1].payload.commentSurfaceEntityPayload.publishedTimeCommand.innertubeCommand;
let webCommandMetadata = innertubeCommand.commandMetadata.webCommandMetadata;
let webPageType = webCommandMetadata.webPageType;
let url = webCommandMetadata.url;
let commentAreaInfo = {};
commentAreaInfo.channelId = findValueInSingleEntryArray(json.actions[0].runAttestationCommand.ids, "externalChannelId");
if (webPageType == "WEB_PAGE_TYPE_WATCH") {
commentAreaInfo.videoId = innertubeCommand.watchEndpoint.videoId;
} else if (webPageType == "WEB_PAGE_TYPE_BROWSE") {
commentAreaInfo.postId = createUrl(url).pathname.split("/")[2];
}
let author = entity.author;
let properties = entity.properties;
let content = properties.content.content;
let recordedTime = Date.now();
let commentRecord = {
//评论ID
commentId: properties.commentId,
//@发送者
displayName: author.displayName,
//频道ID,类似UID
channelId: author.channelId,
//评论内容
content,
//webPageType 评论区类型 视频 or 帖子
webPageType,
//URL 点击可跳转“所要查看的评论” 例如 /watch?v=${视频ID}&lc=${评论ID}
url,
//评论区信息,视频{视频ID},帖子{频道ID,帖子ID}
commentAreaInfo,
//当前状态 默认从SHADOW_BAN开始,到NORMAL或DELETED
currentState: "NOT_CHECK",
//是否在热门排序中被禁止显示(搜索整个热门评论区来检查),前提条件currentState = "NORMAL",值:null | false | true
//此状态不会因为修改评论内容而解除,但会因为修改评论内容而赋予
hotBan: null,
//历史记录,时间 内容 状态 是否热门屏蔽
histories: [],
//{ time: recordedTime, state: "SHADOW_BAN", content, hotBan: null }
//点赞与回复数,不记录历史
likeCount: 0,
replyCount: 0,
//记录的时间,用的是系统当前时间,约等于评论的发布时间,API里的publishedTime距离发布时间戳多久的Shit不是时间戳(PS:YouTube开放API可查询具体发布时间戳)
recordedTime,
//更新时间
updatedTime: recordedTime,
//是否是用户自己执行的删除?用于区分是被系统删的还是自己删除。state为"DELETED"时该属性为才有意义。(劫持删除评论请求时记录)
isUserDelete: false
};
console.log(commentRecord);
insertComment(commentRecord);
console.log(createUrl(url).href);
toCheck(commentRecord);
} catch (err) {
console.error(err);
throw err;
}
return response;
} else if (request.url.startsWith("https://www.youtube.com/youtubei/v1/comment/perform_comment_action")) {
let actionBase64 = urlSafeBase64ToStandard(requestBody.actions[0]);
let actionInfo = CommentAction.decode(Uint8Array.from(atob(actionBase64), (c) => c.charCodeAt(0)));
if (actionInfo.action == 6) {
if (checkingCommentIdSet.has(actionInfo.commentId)) {
alert("现在不能删除该评论,因为评论还未完成检查,请先完成检查!");
const responseBody = {
"error": {
"code": 403,
"message": "Can't delete comment now",
"errors": [
{
"message": "Can't delete comment now",
"domain": "global",
"reason": "forbidden"
}
],
"status": "FORBIDDEN"
}
};
return new Response(JSON.stringify(responseBody), {
status: 403,
headers: {
"Content-Type": "application/json"
}
});
} else {
let response = await originalFetch(request);
let responseBody = await response.clone().json();
if (responseBody.actions && responseBody.actions[0].removeCommentAction.actionResult.status == "STATUS_SUCCEEDED") {
let commentRecord = await selectComment(actionInfo.commentId);
if (commentRecord) {
commentRecord.isUserDelete = true;
updateRecord(commentRecord, "DELETED");
}
}
return response;
}
}
} else if (request.url.startsWith("https://www.youtube.com/youtubei/v1/comment/update_comment")) {
let updateCommentParams = urlSafeBase64ToStandard(requestBody.updateCommentParams);
let decodedParams = UpdateCommentParams.decode(Uint8Array.from(atob(updateCommentParams), (c) => c.charCodeAt(0)));
if (checkingCommentIdSet.has(decodedParams.commentId)) {
alert("现在不能修改该评论,因为评论还未完成检查,请先完成检查!");
const responseBody2 = {
"error": {
"code": 403,
"message": "Can't edit comment now",
"errors": [
{
"message": "Can't edit comment now",
"domain": "global",
"reason": "forbidden"
}
],
"status": "FORBIDDEN"
}
};
return new Response(JSON.stringify(responseBody2), {
status: 403,
headers: {
"Content-Type": "application/json"
}
});
}
let response = await originalFetch(request);
let responseBody = await response.clone().json();
if (responseBody.actions && responseBody.actions[0].updateCommentAction.actionResult.status == "STATUS_SUCCEEDED") {
let commentRecord = await selectComment(decodedParams.commentId);
if (commentRecord) {
commentRecord.content = requestBody.commentText;
commentRecord.currentState = "NOT_CHECK";
commentRecord.hotBan = null;
updateRecord(commentRecord);
}
}
return response;
}
return await originalFetch(request);
}
const fetchProxy = function(resource, options) {
if (typeof resource == "string") {
return originalFetch(resource, options);
}
if (!resource.url.startsWith("https://www.youtube.com/youtubei/")) {
return originalFetch(resource, options);
}
let auth = resource.headers.get("Authorization");
if (auth) {
authorizationCache = auth;
if (resource.method != "POST") {
return originalFetch(resource);
} else {
return handlerYoutubei(resource);
}
}
return originalFetch(resource, options);
};
try {
_unsafeWindow.fetch = fetchProxy;
} catch (err) {
console.warn("替换 unsafeWindow.fetch 失败!相关信息:", err, Object.getOwnPropertyDescriptor(_unsafeWindow, "fetch"));
if (confirm("fetch已被提前锁定,替换失败,YouTube发评反诈可能无法正常工作。\n你可以安装本项目的 Define property blocker 插件来反制锁定。\n\n点击“确定”前往项目地址,点击“取消”忽略。")) {
window.location.href = "https://github.com/freedom-introvert/youtube-comment-censor-detector";
}
}
const _createElement = Document.prototype.createElement;
Document.prototype.createElement = function(tagName, ...args) {
const el = _createElement.call(this, tagName, ...args);
if (tagName.toLowerCase() === "iframe") {
el.addEventListener("load", () => {
var _a;
try {
const fetchFromIframe = (_a = el.contentWindow) == null ? void 0 : _a.fetch;
if (fetchFromIframe) {
el.contentWindow.fetch = fetchProxy;
console.log("已替换iframe window的fetch", el);
}
} catch (e) {
console.log("未替换该iframe的fetch", el, e);
}
});
}
return el;
};
function openDB() {
return new Promise((resolve, reject) => {
let request = indexedDB.open("YT-CCD", 1);
request.onerror = (event) => {
reject(event);
};
request.onsuccess = (event) => {
resolve(event.target.result);
};
request.onupgradeneeded = (event) => {
let db2 = event.target.result;
let objectStore = db2.createObjectStore("comments", { keyPath: "commentId" });
objectStore.createIndex("recordedTime", "recordedTime", { unique: false });
};
});
}
async function init() {
try {
db = await openDB();
insertComment = function(comment) {
return new Promise((resolve, reject) => {
let request = db.transaction("comments", "readwrite").objectStore("comments").add(comment);
request.onsuccess = (event) => {
resolve(event);
};
request.onerror = (event) => {
reject(event);
};
});
};
updateComment = function(comment) {
return new Promise((resolve, reject) => {
let request = db.transaction("comments", "readwrite").objectStore("comments").put(vue.toRaw(comment));
request.onsuccess = (event) => {
resolve(event);
};
request.onerror = (event) => {
reject(event);
};
});
};
selectComment = function(commentId) {
return new Promise((resolve, reject) => {
let request = db.transaction("comments").objectStore("comments").get(commentId);
request.onsuccess = (event) => {
resolve(request.result);
};
request.onerror = (event) => {
reject(event);
};
});
};
deleteComment = function(commentId) {
return new Promise((resolve, reject) => {
let request = db.transaction("comments", "readwrite").objectStore("comments").delete(commentId);
request.onsuccess = (event) => {
resolve(request.result);
};
request.onerror = (event) => {
reject(event);
};
});
};
} catch (err) {
console.log("indexedDB数据库打开失败,评论历史记录相关功能已禁用,错误信息:", err);
}
const menuListener = {
onOpenHistory: () => {
alert("脚本正在初始化,请稍后……");
}
};
_GM_registerMenuCommand("🧾 历史评论记录", () => {
menuListener.onOpenHistory();
});
_GM_registerMenuCommand("🔍 搜索热门屏蔽评论", () => {
menuListener.onSearchHotBan();
});
const div = document.createElement("div");
div.id = "yt-ccd";
div.style.position = "absolute";
document.body.append(div);
let app = vue.createApp(App);
app.use(ElementPlus);
app.provide("menuListener", menuListener);
app.provide("db", db);
app.provide("check", check);
app.provide("hotBanCheck", hotBanCheck);
app.provide("deleteComment", deleteComment);
app.provide("getAuthorization", getAuthorization);
app.provide("getContext", getContext);
app.provide("originalFetch", originalFetch);
app.mount(div);
}
window.addEventListener("load", () => {
init().then(() => {
console.log("YouTube反诈加载完成");
}).catch((err) => {
console.error("YouTube反诈加载失败", err);
});
});
})(Vue, ElementPlus);