恢復 YouTube 評論名稱

此腳本將 YouTube 評論部分中的“handle”替換為用戶名

目前為 2024-03-07 提交的版本,檢視 最新版本

// ==UserScript==
// @name Return YouTube Comment Username
// @name:ja YouTubeコメント欄の名前を元に戻す
// @name:zh-CN 恢復 YouTube 评论用户名
// @name:zh-TW 恢復 YouTube 評論名稱
// @version 0.4.2
// @author yakisova41
// @license MIT
// @icon data:image/png;base64,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
// @namespace https://yt-returnname-api.pages.dev/extension/
// @description This script replaces the "handle" in the YouTube comments section to user name
// @description:ja YouTubeのコメント欄の名前をハンドル(@...)からユーザー名に書き換えます。
// @description:zh-TW 此腳本將 YouTube 評論部分中的“handle”替換為用戶名
// @description:zh-CN 此脚本将 YouTube 评论部分中的“handle”替换为用户名
// @match https://www.youtube.com/*
// @grant unsafeWindow
// @run-at document-end
// ==/UserScript==

const inject = ()=>{// src/utils/isCommentRenderer.ts
function isCommentRenderer(continuationItems) {
  if (continuationItems.length > 0) {
    if ("commentThreadRenderer" in continuationItems[0]) {
      return false;
    }
    if ("commentRenderer" in continuationItems[0]) {
      return true;
    }
  }
  return false;
}
function isCommentRendererV2(continuationItems) {
  if (continuationItems.length > 0) {
    if ("commentThreadRenderer" in continuationItems[0]) {
      return false;
    }
    if ("commentViewModel" in continuationItems[0]) {
      return true;
    }
  }
  return false;
}

// src/utils/debugLog.ts
function debugLog(message, value = "") {
  console.log(`[rycu] ${message} %c${value}`, "color:cyan;");
}
function debugErr(message) {
  console.error(`[rycu] ${message}`);
}

// src/utils/findElementByTrackingParams.ts
function findElementByTrackingParams(trackingParams, elementSelector) {
  let returnElement = null;
  let errorAlerted = false;
  const elems = document.querySelectorAll(elementSelector);
  for (let i = 0; i < elems.length; i++) {
    if (elems[i]?.trackedParams === void 0 && elems[i]?.polymerController?.trackedParams === void 0) {
      debugErr("TrackedParams property is not found");
    }
    if (elems[i].trackedParams === trackingParams) {
      returnElement = elems[i];
      break;
    } else if (elems[i]?.polymerController?.trackedParams === trackingParams) {
      returnElement = elems[i];
      break;
    } else {
      if (!errorAlerted) {
        void searchTrackedParamsByObject(trackingParams, elems[i]);
        errorAlerted = true;
      }
    }
  }
  return returnElement;
}
async function reSearchElement(trackingParams, selector) {
  return await new Promise((resolve) => {
    let isFinding = true;
    const search = () => {
      const el = findElementByTrackingParams(trackingParams, selector);
      if (el !== null) {
        resolve(el);
        isFinding = false;
      }
      if (isFinding) {
        setTimeout(() => {
          search();
        }, 100);
      }
    };
    search();
  });
}
function findElementAllByCommentId(commnetId, elementSelector) {
  const returnElements = [];
  const elems = document.querySelectorAll(elementSelector);
  for (let i = 0; i < elems.length; i++) {
    if (elems[i] !== void 0) {
      if (elems[i]?.__data?.data?.commentId === void 0 && elems[i]?.polymerController?.__data?.data?.commentId === void 0) {
        debugErr("Reply CommentId is not found");
      } else if (elems[i]?.__data?.data?.commentId !== void 0 && elems[i].__data.data.commentId === commnetId) {
        returnElements.push(elems[i]);
      } else if (elems[i]?.polymerController?.__data?.data?.commentId !== void 0 && elems[i].polymerController.__data.data.commentId === commnetId) {
        returnElements.push(elems[i]);
      }
    }
  }
  return returnElements;
}
async function reSearchElementAllByCommentId(commnetId, selector) {
  return await new Promise((resolve) => {
    let isFinding = true;
    const search = () => {
      const el = findElementAllByCommentId(commnetId, selector);
      if (el !== null) {
        resolve(el);
        isFinding = false;
      }
      if (isFinding) {
        setTimeout(() => {
          search();
        }, 100);
      }
    };
    search();
  });
}
async function searchTrackedParamsByObject(param, elem) {
  const elemObj = Object(elem);
  const search = (obj, history) => {
    Object.keys(obj).forEach((k) => {
      if (typeof obj[k] === "object") {
        search(obj[k], [...history, k]);
      } else if (obj[k] === param) {
        history.push(k);
        debugErr(`Unknown Object format!
"${history.join(">")}"`);
      }
    });
  };
  search(elemObj, []);
}

// src/types/AppendContinuationItemsAction.ts
function isReplyContinuationItemsV1(obj) {
  return Object.hasOwn(obj[0], "commentRenderer");
}
function isReplyContinuationItemsV2(obj) {
  return Object.hasOwn(obj[0], "commentViewModel");
}
function isConfinuationItemV2(obj) {
  return Object.hasOwn(obj, "commentViewModel");
}
function isConfinuationItemV1(obj) {
  return Object.hasOwn(obj, "comment");
}

// src/utils/getShadyChildren.ts
var isAleated = false;
function getShadyChildren(parentElement, index, id) {
  let returnElem;
  const child = parentElement.__shady_native_children[index];
  if (child === null || child.id !== id) {
    returnElem = parentElement.querySelector(`#${id}`);
    if (!isAleated) {
      console.log(
        `%cReturn YouTube Comment Username Warning%c %cChildren Cannot Get by Index!%c
%cid of element attempting to retrieve: #${id}
If you find this debug log, please report it to the github issue%c`,
        "background:#f0e68c; color:#000;font-size:20px;",
        "",
        "color:#00c72e;font-size:16px;",
        "",
        "color: #13ebdc;",
        "",
        "\nhttps://github.com/yakisova41/return-youtube-comment-username/issues/new?assignees=&labels=bug&projects=&template=bug_report.yaml&title=%5BBug%5D%3A+Children%20Cannot%20Get%20by%20Index"
      );
      isAleated = true;
    }
  } else {
    returnElem = child;
  }
  return returnElem;
}

// src/utils/escapeString.ts
function escapeString(text) {
  return text.replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, `&quot;`).replace(/'/g, `&#39;`).replace(/&/g, `&amp;`);
}
function decodeString(text) {
  return text.replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, `"`).replace(/&#39;/g, `'`).replace(/&amp;/g, `&`);
}

// src/utils/getUserName.ts
var isUseFeed = true;
async function getUserName(id) {
  return new Promise((resolve) => {
    if (isUseFeed) {
      fetchFeed(id).then((name) => {
        resolve(name);
      }).catch(() => {
        isUseFeed = false;
        debugErr("Catch Feed API Error\nChange to Browse mode");
        fetchBrowse(id).then((name) => {
          resolve(name);
        });
      });
    } else {
      fetchBrowse(id).then((name) => {
        resolve(name);
      });
    }
  });
}
async function fetchFeed(id) {
  return await fetch(
    `https://www.youtube.com/feeds/videos.xml?channel_id=${id}`,
    {
      method: "GET",
      cache: "default",
      keepalive: true
    }
  ).then(async (res) => {
    if (res.status !== 200)
      throw new Error(`Feed API Error
status: ${res.status}`);
    return await res.text();
  }).then((text) => {
    const match = text.match("<title>([^<].*)</title>");
    if (match !== null) {
      return decodeString(match[1]);
    } else {
      debugErr("XML title not found");
      return "";
    }
  });
}
async function fetchBrowse(id) {
  return await fetch(
    `https://www.youtube.com/youtubei/v1/browse?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8&prettyPrint=false`,
    {
      method: "POST",
      headers: {
        cache: "default",
        accept: "*/*",
        "accept-encoding": "gzip, deflate, br",
        "accept-language": "en",
        "content-type": "application/json",
        dnt: "1",
        referer: `https://www.youtube.com/channel/${id}`
      },
      body: JSON.stringify({
        context: {
          client: {
            hl: window.yt.config_.HL,
            gl: window.yt.config_.GL,
            clientName: "WEB",
            clientVersion: "2.20230628.01.00",
            platform: "DESKTOP",
            acceptHeader: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"
          },
          user: { lockedSafetyMode: false },
          request: {
            useSsl: true
          }
        },
        browseId: id,
        params: "EgVhYm91dPIGBAoCEgA%3D"
      })
    }
  ).then(async (res) => {
    if (res.status !== 200)
      throw new Error(`Browse API Error
status: ${res.status}`);
    return await res.json();
  }).then((text) => {
    const name = text.header.c4TabbedHeaderRenderer.title;
    return decodeString(name);
  });
}

// src/rewrites/rewriteOfCommentRenderer/nameRewriteOfCommentRenderer.ts
function nameRewriteOfCommentRenderer(commentRenderer, isNameContainerRender, userId) {
  const commentRendererBody = getShadyChildren(
    commentRenderer,
    2,
    "body"
  );
  if (commentRendererBody === null) {
    throw new Error("[rycu] comment renderer body is null");
  }
  let nameElem = commentRendererBody.querySelector(
    "#main > #header > #header-author > h3 > a > yt-formatted-string"
  );
  if (isNameContainerRender) {
    const containerMain = getShadyChildren(commentRendererBody, 1, "main");
    if (containerMain !== null) {
      nameElem = containerMain.querySelector(
        "#header > #header-author > #author-comment-badge > ytd-author-comment-badge-renderer > a > #channel-name > #container > #text-container > yt-formatted-string"
      );
    }
  }
  void getUserName(userId).then((name) => {
    if (nameElem !== null) {
      if (nameElem.getAttribute("is-empty") !== null) {
        nameElem.removeAttribute("is-empty");
      }
      if (isNameContainerRender) {
        nameElem.__shady_native_innerHTML = escapeString(name);
      } else {
        nameElem.textContent = name;
      }
    } else {
      debugErr("Name element is null");
    }
  }).catch((e) => {
    debugErr(e);
  });
}

// src/rewrites/rewriteOfCommentRenderer/mentionRewriteOfCommentRenderer.ts
function mentionRewriteOfCommentRenderer(commentRenderer) {
  const commentRendererBody = getShadyChildren(commentRenderer, 2, "body");
  const main2 = commentRendererBody?.querySelector("#main");
  if (main2 !== void 0 && main2 !== null) {
    const aTags = main2.querySelectorAll(
      "#comment-content > ytd-expander > #content > #content-text > a"
    );
    for (let i = 0; i < aTags.length; i++) {
      if (aTags[i].getAttribute("href")?.match("/channel/.*") !== null) {
        const href = aTags[i].getAttribute("href");
        if (href !== null) {
          void getUserName(href.split("/")[2]).then((name) => {
            aTags[i].textContent = `@${name} `;
          }).catch((e) => {
            debugErr(e);
          });
        } else {
          debugErr("Mention Atag is have not Href attr");
        }
      }
    }
  }
}

// src/rewrites/rewriteOfCommentRenderer/nameRewriteOfCommentViewModel.ts
function nameRewriteOfCommentViewModel(commentRenderer) {
  const commentRendererBody = getShadyChildren(
    commentRenderer,
    2,
    "body"
  );
  if (commentRendererBody === null) {
    throw new Error("[rycu] comment renderer body is null");
  }
  if (!commentRendererBodyGuard(commentRendererBody)) {
    throw new Error(
      "[rycu] The object format of comment renderer body is invalid."
    );
  }
  const isNameContainerRender = commentRendererBody.__dataHost.$["author-text"].__dataHost.__data.authorCommentBadge !== null;
  let nameElem = commentRendererBody.querySelector(
    "#main > #header > #header-author > h3 > a > span"
  );
  const userId = commentRendererBody.__dataHost.$["author-text"].__dataHost.__data.authorEndpoint.browseEndpoint.browseId;
  if (isNameContainerRender) {
    const containerMain = getShadyChildren(commentRendererBody, 1, "main");
    if (containerMain !== null) {
      nameElem = containerMain.querySelector(
        "#header > #header-author > #author-comment-badge > ytd-author-comment-badge-renderer > a > #channel-name > #container > #text-container > yt-formatted-string"
      );
    }
  }
  void getUserName(userId).then((name) => {
    if (nameElem !== null) {
      if (nameElem.getAttribute("is-empty") !== null) {
        nameElem.removeAttribute("is-empty");
      }
      if (isNameContainerRender) {
        nameElem.__shady_native_innerHTML = escapeString(name);
      } else {
        nameElem.textContent = name;
      }
    } else {
      debugErr("Name element is null");
    }
  }).catch((e) => {
    debugErr(e);
  });
}
function commentRendererBodyGuard(elem) {
  return Object.hasOwn(elem, "__dataHost");
}

// src/rewrites/rewriteOfCommentRenderer/mentionRewriteOfCommentRendererV2.ts
function mentionRewriteOfCommentRendererV2(commentRenderer) {
  const commentRendererBody = getShadyChildren(commentRenderer, 2, "body");
  const main2 = commentRendererBody?.querySelector("#main");
  if (main2 !== void 0 && main2 !== null) {
    const aTags = main2.querySelectorAll(
      "#expander > #content > #content-text > span > span > a"
    );
    for (let i = 0; i < aTags.length; i++) {
      if (aTags[i].getAttribute("href")?.match("/channel/.*") !== null) {
        const href = aTags[i].getAttribute("href");
        if (href !== null) {
          void getUserName(href.split("/")[2]).then((name) => {
            aTags[i].textContent = `@${name} `;
          }).catch((e) => {
            debugErr(e);
          });
        } else {
          debugErr("Mention Atag is have not Href attr");
        }
      }
    }
  }
}

// src/rewrites/reply.ts
function rewriteReplytNameFromContinuationItems(continuationItems) {
  debugLog("Reply Rewrite");
  if (isReplyContinuationItemsV1(continuationItems)) {
    debugLog("Reply continuationItems V1");
    for (let i = 0; i < continuationItems.length; i++) {
      const { commentRenderer } = continuationItems[i];
      if (commentRenderer !== void 0) {
        void getReplyElem(commentRenderer.trackingParams, "V1").then(
          (replyElem) => {
            reWriteReplyElem(replyElem, commentRenderer);
          }
        );
      }
    }
  }
  if (isReplyContinuationItemsV2(continuationItems)) {
    debugLog("Reply continuationItems V2");
    for (let i = 0; i < continuationItems.length; i++) {
      const { commentViewModel } = continuationItems[i];
      if (commentViewModel !== void 0) {
        void getReplyElem(
          commentViewModel.rendererContext.loggingContext.loggingDirectives.trackingParams,
          "V2"
        ).then((replyElem) => {
          reWriteReplyElemV2(replyElem);
        });
      }
    }
  }
}
function reWriteReplyElem(replyElem, rendererData) {
  let isContainer = rendererData.authorIsChannelOwner;
  if (rendererData.authorCommentBadge !== void 0) {
    isContainer = true;
  }
  nameRewriteOfCommentRenderer(
    replyElem,
    isContainer,
    rendererData.authorEndpoint.browseEndpoint.browseId
  );
  mentionRewriteOfCommentRenderer(replyElem);
  replyInputRewrite(replyElem);
}
function reWriteReplyElemV2(replyElem) {
  nameRewriteOfCommentViewModel(replyElem);
  mentionRewriteOfCommentRendererV2(replyElem);
  replyInputRewrite(replyElem);
}
async function getReplyElem(trackedParams, version) {
  return await new Promise((resolve) => {
    const selector = "#replies > ytd-comment-replies-renderer > #expander > #expander-contents > #contents > " + (version === "V1" ? "ytd-comment-renderer" : "ytd-comment-view-model");
    const commentRenderer = findElementByTrackingParams(
      trackedParams,
      selector
    );
    if (commentRenderer !== null) {
      resolve(commentRenderer);
    } else {
      void reSearchElement(trackedParams, selector).then((commentRenderer2) => {
        resolve(commentRenderer2);
      });
    }
  });
}
function rewriteTeaserReplytNameFromContinuationItems(continuationItems) {
  debugLog("Teaser Reply Rewrite");
  for (let i = 0; i < continuationItems.length; i++) {
    const { commentRenderer } = continuationItems[i];
    if (commentRenderer !== void 0) {
      void reSearchElementAllByCommentId(
        commentRenderer.commentId,
        "ytd-comment-replies-renderer > #teaser-replies > ytd-comment-renderer"
      ).then((replyElems) => {
        replyElems.forEach((replyElem) => {
          reWriteReplyElem(replyElem, commentRenderer);
        });
      });
      void reSearchElementAllByCommentId(
        commentRenderer.commentId,
        "ytd-comment-replies-renderer > #expander > #expander-contents > #contents > ytd-comment-renderer"
      ).then((replyElems) => {
        replyElems.forEach((replyElem) => {
          reWriteReplyElem(replyElem, commentRenderer);
        });
      });
    }
  }
}
function replyInputRewrite(replyElem) {
  const replyToReplyBtn = replyElem.querySelector(
    "#reply-button-end > ytd-button-renderer"
  );
  const replyToReplyHander = () => {
    const replyLink = replyElem.querySelector("#contenteditable-root > a");
    const href = replyLink?.getAttribute("href");
    const channelId = href?.split("/")[2];
    if (channelId !== void 0 && replyLink !== null) {
      void getUserName(channelId).then((name) => {
        replyLink.textContent = ` @${name}`;
      });
    }
    replyToReplyBtn?.removeEventListener("click", replyToReplyHander);
  };
  replyToReplyBtn?.addEventListener("click", replyToReplyHander);
  document.addEventListener("rycu-pagechange", () => {
    replyToReplyBtn?.removeEventListener("click", replyToReplyHander);
  });
}

// src/rewrites/comment.ts
function rewriteCommentNameFromContinuationItems(continuationItems) {
  debugLog("Comment Rewrite");
  for (let i = 0; i < continuationItems.length; i++) {
    if (continuationItems[i].commentThreadRenderer !== void 0) {
      void getCommentElem(
        continuationItems[i].commentThreadRenderer.trackingParams
      ).then((commentElem) => {
        reWriteCommentElem(
          commentElem,
          continuationItems[i].commentThreadRenderer
        );
      });
      const teaserContents = continuationItems[i].commentThreadRenderer.replies?.commentRepliesRenderer.teaserContents;
      if (teaserContents !== void 0) {
        rewriteTeaserReplytNameFromContinuationItems(teaserContents);
      }
    }
  }
}
function reWriteCommentElem(commentElem, commentThreadRenderer) {
  const commentRenderer = getShadyChildren(commentElem, 0, "comment");
  if (commentRenderer !== null && commentRenderer !== void 0) {
    if (isConfinuationItemV1(commentThreadRenderer)) {
      debugLog("Comment continuationItems V1");
      let isContainer = commentThreadRenderer.comment.commentRenderer.authorIsChannelOwner;
      if (commentThreadRenderer.comment.commentRenderer.authorCommentBadge !== void 0) {
        isContainer = true;
      }
      nameRewriteOfCommentRenderer(
        commentRenderer,
        isContainer,
        commentThreadRenderer.comment.commentRenderer.authorEndpoint.browseEndpoint.browseId
      );
    }
    if (isConfinuationItemV2(commentThreadRenderer)) {
      debugLog("Comment continuationItems V2");
      nameRewriteOfCommentViewModel(commentRenderer);
    }
  }
}
async function getCommentElem(trackingParams) {
  return await new Promise((resolve) => {
    const commentElem = findElementByTrackingParams(
      trackingParams,
      "#comments > #sections > #contents > ytd-comment-thread-renderer"
    );
    if (commentElem !== null) {
      resolve(commentElem);
    } else {
      void reSearchElement(trackingParams, "ytd-comment-thread-renderer").then((commentElem2) => {
        resolve(commentElem2);
      }).catch((e) => {
        debugErr(e);
      });
    }
  });
}

// src/handlers/handleYtAppendContinuationItemsAction.ts
function handleYtAppendContinuationItemsAction(detail) {
  const continuationItems = detail.args[0].appendContinuationItemsAction.continuationItems;
  if (isCommentRenderer(continuationItems) || isCommentRendererV2(continuationItems)) {
    const replyDetail = detail;
    setTimeout(() => {
      rewriteReplytNameFromContinuationItems(
        replyDetail.args[0].appendContinuationItemsAction.continuationItems
      );
    }, 100);
  } else {
    const commentDetail = detail;
    setTimeout(() => {
      rewriteCommentNameFromContinuationItems(
        commentDetail.args[0].appendContinuationItemsAction.continuationItems
      );
    }, 400);
  }
}

// src/handlers/handleYtCreateCommentAction.ts
function handleYtCreateCommentAction(detail) {
  const createCommentDetail = detail;
  const continuationItems = [
    {
      commentThreadRenderer: createCommentDetail.args[0].createCommentAction.contents.commentThreadRenderer
    }
  ];
  setTimeout(() => {
    rewriteCommentNameFromContinuationItems(continuationItems);
  }, 100);
}

// src/handlers/handleYtCreateCommentReplyAction.ts
function handleYtCreateCommentReplyAction(detail) {
  const createReplyDetail = detail;
  const continuationItems = [
    {
      commentRenderer: createReplyDetail.args[0].createCommentReplyAction.contents.commentRenderer
    }
  ];
  setTimeout(() => {
    rewriteTeaserReplytNameFromContinuationItems(continuationItems);
  }, 100);
}

// src/rewrites/highlightedReply.ts
function rewriteHighlightedReply(trackedParams, isContainer, userId) {
  const elem = findElementByTrackingParams(
    trackedParams,
    "ytd-comment-renderer"
  );
  const rewriteHighlightedReplyElem = (elem2) => {
    nameRewriteOfCommentRenderer(elem2, isContainer, userId);
    replyInputRewrite(elem2);
  };
  if (elem === null) {
    void reSearchElement(trackedParams, "ytd-comment-renderer").then((elem2) => {
      rewriteHighlightedReplyElem(elem2);
    });
  } else {
    rewriteHighlightedReplyElem(elem);
  }
}

// src/handlers/handleYtGetMultiPageMenuAction.ts
function handleYtGetMultiPageMenuAction(detail) {
  const getMultiPageMenuDetail = detail;
  const continuationItems = getMultiPageMenuDetail.args[0].getMultiPageMenuAction.menu.multiPageMenuRenderer.sections[1].itemSectionRenderer?.contents;
  const highLightedTeaserContents = getMultiPageMenuDetail.args[0]?.getMultiPageMenuAction?.menu?.multiPageMenuRenderer.sections[1].itemSectionRenderer?.contents[0]?.commentThreadRenderer.replies?.commentRepliesRenderer?.teaserContents;
  if (continuationItems !== void 0) {
    setTimeout(() => {
      rewriteCommentNameFromContinuationItems(continuationItems);
      if (highLightedTeaserContents !== void 0) {
        const highLightedReplyRenderer = highLightedTeaserContents[0]?.commentRenderer;
        let isContainer = highLightedReplyRenderer.authorIsChannelOwner;
        if (highLightedReplyRenderer.authorCommentBadge !== void 0) {
          isContainer = true;
        }
        rewriteHighlightedReply(
          highLightedReplyRenderer.trackingParams,
          isContainer,
          highLightedReplyRenderer.authorEndpoint.browseEndpoint.browseId
        );
      }
    }, 100);
  }
}

// src/handlers/handleYtHistory.ts
function handleYtHistory(detail) {
  const historyDetail = detail;
  const continuationItems = historyDetail.args[1].historyEntry?.rootData.response.contents.twoColumnWatchNextResults?.results?.results?.contents[3]?.itemSectionRenderer?.contents;
  if (continuationItems !== void 0) {
    setTimeout(() => {
      rewriteCommentNameFromContinuationItems(continuationItems);
    }, 100);
  }
}

// src/handlers/handleYtReloadContinuationItemsCommand.ts
function handleYtReloadContinuationItemsCommand(detail) {
  const reloadDetail = detail;
  const { slot } = reloadDetail.args[0].reloadContinuationItemsCommand;
  if (slot === "RELOAD_CONTINUATION_SLOT_BODY") {
    const continuationItems = reloadDetail.args[0].reloadContinuationItemsCommand.continuationItems;
    if (continuationItems !== void 0) {
      setTimeout(() => {
        rewriteCommentNameFromContinuationItems(continuationItems);
      }, 100);
    }
  }
}

// package.json
var package_default = {
  name: "return-youtube-comment-username",
  version: "0.4.2",
  devDependencies: {
    eslint: "^8.31.0",
    prettier: "^3.0.3",
    "ts-extension-builder": "^0.2.6"
  },
  license: "MIT",
  scripts: {
    "esbuild-register": "node --require esbuild-register",
    "build:userscript": "npx ts-extension-builder build type=userscript",
    "build:extension": "npx ts-extension-builder build type=extension",
    dev: "npx ts-extension-builder dev type=userscript",
    lint: "npx eslint --fix src/index.ts"
  },
  type: "commonjs",
  dependencies: {
    "@typescript-eslint/eslint-plugin": "^6.6.0",
    "@typescript-eslint/parser": "^6.6.0",
    "eslint-config-prettier": "^9.0.0",
    typescript: "^5.2.2"
  }
};

// src/index.ts
function main() {
  debugLog(
    `Return Youtube comment Username v${package_default.version}`,
    [
      `INNERTUBE_CLIENT_VERSION: ${window.yt.config_.INNERTUBE_CLIENT_VERSION}`,
      `INNERTUBE_CONTEXT_CLIENT_VERSION: ${window.yt.config_.INNERTUBE_CONTEXT_CLIENT_VERSION}`,
      `Browser: ${window.yt.config_.INNERTUBE_CONTEXT.client.browserName} v${window.yt.config_.INNERTUBE_CONTEXT.client.browserVersion}`,
      `Login: ${window.yt.config_.LOGGED_IN}`
    ].join("\n")
  );
  const handleYtAction = (e) => {
    switch (e.detail.actionName) {
      case "yt-append-continuation-items-action":
        handleYtAppendContinuationItemsAction(e.detail);
        break;
      case "yt-reload-continuation-items-command":
        handleYtReloadContinuationItemsCommand(e.detail);
        break;
      case "yt-history-load":
        handleYtHistory(e.detail);
        break;
      case "yt-get-multi-page-menu-action":
        handleYtGetMultiPageMenuAction(e.detail);
        break;
      case "yt-create-comment-action":
        handleYtCreateCommentAction(e.detail);
        break;
      case "yt-create-comment-reply-action":
        handleYtCreateCommentReplyAction(e.detail);
        break;
    }
  };
  document.addEventListener("yt-action", handleYtAction);
  document.addEventListener("yt-navigate-finish", () => {
    document.dispatchEvent(new Event("rycu-pagechange"));
  });
}

// node_modules/ts-extension-builder/tmp/entry.ts
var args = {};
if (typeof GM_info !== "undefined" && GM_info.script.grant !== void 0) {
  GM_info.script.grant.forEach((propatyName) => {
    let keyName = propatyName.split("GM_")[1];
    if (keyName === "xmlhttpRequest") {
      keyName = "xmlHttpRequest";
    }
    args[propatyName] = GM[keyName];
  });
}
main(args);
}
const script = document.createElement("script");
script.innerHTML = `(${inject.toString()})()`
unsafeWindow.document.body.appendChild(script)

QingJ © 2025

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