恢復 YouTube 评论用户名

此脚本将 YouTube 评论部分中的“handle”替换为用户名

当前为 2023-08-09 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Return YouTube Comment Username
  3. // @name:ja YouTubeコメント欄の名前を元に戻す
  4. // @name:zh-CN 恢復 YouTube 评论用户名
  5. // @name:zh-TW 恢復 YouTube 評論名稱
  6. // @version 0.3.10
  7. // @author yakisova41
  8. // @license MIT
  9. // @icon data:image/png;base64,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
  10. // @namespace https://yt-returnname-api.pages.dev/extension/
  11. // @description This script replaces the "handle" in the YouTube comments section to user name
  12. // @description:ja YouTubeのコメント欄の名前をハンドル(@...)からユーザー名に書き換えます。
  13. // @description:zh-TW 此腳本將 YouTube 評論部分中的“handle”替換為用戶名
  14. // @description:zh-CN 此脚本将 YouTube 评论部分中的“handle”替换为用户名
  15. // @match https://www.youtube.com/*
  16. // @grant unsafeWindow
  17. // @run-at document-end
  18. // ==/UserScript==
  19.  
  20. const inject = ()=>{// src/utils/isCommentRenderer.ts
  21. function isCommentRenderer(continuationItems) {
  22. if (continuationItems.length > 0) {
  23. if (continuationItems[0].hasOwnProperty("commentThreadRenderer")) {
  24. return false;
  25. }
  26. if (continuationItems[0].hasOwnProperty("commentRenderer")) {
  27. return true;
  28. }
  29. }
  30. return false;
  31. }
  32.  
  33. // src/utils/debugLog.ts
  34. function debugLog(message, value = "") {
  35. console.log(`[rycu] ${message} %c${value}`, "color:cyan;");
  36. }
  37. function debugErr(message) {
  38. console.error(`[rycu] ${message}`);
  39. }
  40.  
  41. // src/utils/findElementByTrackingParams.ts
  42. function findElementByTrackingParams(trackingParams, elementSelector) {
  43. let returnElement = null;
  44. let errorAlerted = false;
  45. const elems = document.querySelectorAll(elementSelector);
  46. for (let i = 0; i < elems.length; i++) {
  47. if (elems[i]?.trackedParams === void 0 && elems[i]?.controllerProxy?.trackedParams === void 0) {
  48. debugErr("TrackdParams property is not found");
  49. }
  50. if (elems[i].trackedParams === trackingParams) {
  51. returnElement = elems[i];
  52. break;
  53. } else if (elems[i]?.controllerProxy?.trackedParams === trackingParams) {
  54. returnElement = elems[i];
  55. break;
  56. } else {
  57. if (!errorAlerted) {
  58. void searchTrackedParamsByObject(trackingParams, elems[i]);
  59. errorAlerted = true;
  60. }
  61. }
  62. }
  63. return returnElement;
  64. }
  65. async function reSearchElement(trackingParams, selector) {
  66. return await new Promise((resolve) => {
  67. let isFinding = true;
  68. const search = () => {
  69. const el = findElementByTrackingParams(trackingParams, selector);
  70. if (el !== null) {
  71. resolve(el);
  72. isFinding = false;
  73. }
  74. if (isFinding) {
  75. setTimeout(() => {
  76. search();
  77. }, 100);
  78. }
  79. };
  80. search();
  81. });
  82. }
  83. function findElementAllByCommentId(commnetId, elementSelector) {
  84. const returnElements = [];
  85. const elems = document.querySelectorAll(elementSelector);
  86. elems.forEach((elem) => {
  87. if (elem !== void 0) {
  88. if (elem?.__data?.data?.commentId === void 0 && elem?.controllerProxy?.__data?.data?.commentId === void 0) {
  89. debugErr("Reply CommentId is not found");
  90. console.log(elem);
  91. } else if (elem?.__data?.data?.commentId !== void 0 && elem.__data.data.commentId === commnetId) {
  92. returnElements.push(elem);
  93. } else if (elem?.controllerProxy?.__data?.data?.commentId !== void 0 && elem.controllerProxy.__data.data.commentId === commnetId) {
  94. returnElements.push(elem);
  95. }
  96. }
  97. });
  98. return returnElements;
  99. }
  100. async function reSearchElementAllByCommentId(commnetId, selector) {
  101. return await new Promise((resolve) => {
  102. let isFinding = true;
  103. const search = () => {
  104. const el = findElementAllByCommentId(commnetId, selector);
  105. if (el !== null) {
  106. resolve(el);
  107. isFinding = false;
  108. }
  109. if (isFinding) {
  110. setTimeout(() => {
  111. search();
  112. }, 100);
  113. }
  114. };
  115. search();
  116. });
  117. }
  118. async function searchTrackedParamsByObject(param, elem) {
  119. const elemObj = Object(elem);
  120. const search = (obj, history) => {
  121. Object.keys(obj).forEach((k) => {
  122. if (typeof obj[k] === "object") {
  123. search(obj[k], [...history, k]);
  124. } else if (obj[k] === param) {
  125. history.push(k);
  126. alert(
  127. `[Return YouTube Comment Username] Unknown Object format!
  128. "${history.join(
  129. ">"
  130. )}"`
  131. );
  132. }
  133. });
  134. };
  135. search(elemObj, []);
  136. }
  137.  
  138. // src/utils/escapeString.ts
  139. function escapeString(text) {
  140. return text.replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll(`"`, `&quot;`).replaceAll(`'`, `&#39;`);
  141. }
  142.  
  143. // src/utils/getUserName.ts
  144. async function getUserName(id) {
  145. debugLog("Get name");
  146. const data = await fetch(
  147. `https://www.youtube.com/feeds/videos.xml?channel_id=${id}`,
  148. {
  149. method: "GET",
  150. cache: "default",
  151. keepalive: false
  152. }
  153. ).then(async (res) => {
  154. if (res.status !== 200)
  155. throw new Error(`API Status is ${res.status}`);
  156. return await res.text();
  157. }).then((text) => {
  158. const match = text.match("<title>([^<].*)</title>");
  159. if (match !== null) {
  160. return match[1];
  161. } else {
  162. throw new Error("XML title not found");
  163. }
  164. });
  165. return data;
  166. }
  167.  
  168. // src/rewrites/rewriteOfCommentRenderer/nameRewriteOfCommentRenderer.ts
  169. function nameRewriteOfCommentRenderer(commentRenderer, isNameContainerRender, userId) {
  170. const commentRendererBody = commentRenderer.__shady_native_children[2];
  171. let nameElem = commentRendererBody.querySelector(
  172. "#main > #header > #header-author > h3 > a > span"
  173. );
  174. if (isNameContainerRender) {
  175. nameElem = commentRendererBody.__shady_native_children[1].querySelector(
  176. "#header > #header-author > #author-comment-badge > ytd-author-comment-badge-renderer > a > #channel-name > #container > #text-container > yt-formatted-string"
  177. );
  178. }
  179. void getUserName(userId).then((name) => {
  180. if (nameElem !== null) {
  181. if (isNameContainerRender) {
  182. nameElem.__shady_native_innerHTML = escapeString(name);
  183. } else {
  184. nameElem.textContent = escapeString(name);
  185. }
  186. } else {
  187. debugErr("Name element is null");
  188. }
  189. }).catch((e) => {
  190. debugErr(e);
  191. });
  192. }
  193.  
  194. // src/rewrites/rewriteOfCommentRenderer/mentionRewriteOfCommentRenderer.ts
  195. function mentionRewriteOfCommentRenderer(commentRenderer) {
  196. const commentRendererBody = commentRenderer.__shady_native_children[2];
  197. const main2 = commentRendererBody.__shady_native_children[1];
  198. const aTags = main2.querySelectorAll(
  199. "#comment-content > ytd-expander > #content > #content-text > a"
  200. );
  201. aTags.forEach((aTag) => {
  202. if (aTag.textContent?.match("@.*") !== null) {
  203. const href = aTag.getAttribute("href");
  204. if (href !== null) {
  205. void getUserName(href.split("/")[2]).then((name) => {
  206. aTag.textContent = `@${escapeString(name)} `;
  207. }).catch((e) => {
  208. debugErr(e);
  209. });
  210. } else {
  211. debugErr("Mention Atag is have not Href attr");
  212. }
  213. }
  214. });
  215. }
  216.  
  217. // src/rewrites/reply.ts
  218. function rewriteReplytNameFromContinuationItems(continuationItems) {
  219. debugLog("Reply Rewrite");
  220. continuationItems.forEach((continuationItem) => {
  221. const { commentRenderer } = continuationItem;
  222. if (commentRenderer !== void 0) {
  223. void getReplyElem(commentRenderer.trackingParams).then((replyElem) => {
  224. reWriteReplyElem(replyElem, commentRenderer);
  225. });
  226. }
  227. });
  228. }
  229. function reWriteReplyElem(replyElem, rendererData) {
  230. let isContainer = rendererData.authorIsChannelOwner;
  231. if (rendererData.authorCommentBadge !== void 0) {
  232. isContainer = true;
  233. }
  234. nameRewriteOfCommentRenderer(
  235. replyElem,
  236. isContainer,
  237. rendererData.authorEndpoint.browseEndpoint.browseId
  238. );
  239. mentionRewriteOfCommentRenderer(replyElem);
  240. }
  241. async function getReplyElem(trackedParams) {
  242. return await new Promise((resolve) => {
  243. const selector = "#replies > ytd-comment-replies-renderer > #expander > #expander-contents > #contents > ytd-comment-renderer";
  244. const commentRenderer = findElementByTrackingParams(
  245. trackedParams,
  246. selector
  247. );
  248. if (commentRenderer !== null) {
  249. resolve(commentRenderer);
  250. } else {
  251. void reSearchElement(trackedParams, selector).then((commentRenderer2) => {
  252. resolve(commentRenderer2);
  253. });
  254. }
  255. });
  256. }
  257. function rewriteTeaserReplytNameFromContinuationItems(continuationItems) {
  258. debugLog("Teaser Reply Rewrite");
  259. continuationItems.forEach((continuationItem) => {
  260. const { commentRenderer } = continuationItem;
  261. if (commentRenderer !== void 0) {
  262. void reSearchElementAllByCommentId(
  263. commentRenderer.commentId,
  264. "ytd-comment-replies-renderer > #teaser-replies > ytd-comment-renderer"
  265. ).then((replyElems) => {
  266. replyElems.forEach((replyElem) => {
  267. reWriteReplyElem(replyElem, commentRenderer);
  268. });
  269. });
  270. void reSearchElementAllByCommentId(
  271. commentRenderer.commentId,
  272. "ytd-comment-replies-renderer > #expander > #expander-contents > #contents > ytd-comment-renderer"
  273. ).then((replyElems) => {
  274. replyElems.forEach((replyElem) => {
  275. reWriteReplyElem(replyElem, commentRenderer);
  276. });
  277. });
  278. }
  279. });
  280. }
  281.  
  282. // src/rewrites/comment.ts
  283. function rewriteCommentNameFromContinuationItems(continuationItems) {
  284. debugLog("Comment Rewrite");
  285. continuationItems.forEach((continuationItem) => {
  286. const { commentThreadRenderer } = continuationItem;
  287. if (commentThreadRenderer !== void 0) {
  288. const { trackingParams } = commentThreadRenderer;
  289. void getCommentElem(trackingParams).then((commentElem) => {
  290. reWriteCommentElem(commentElem, commentThreadRenderer);
  291. });
  292. if (commentThreadRenderer.replies?.commentRepliesRenderer.teaserContents !== void 0) {
  293. rewriteTeaserReplytNameFromContinuationItems(
  294. commentThreadRenderer.replies?.commentRepliesRenderer.teaserContents
  295. );
  296. }
  297. }
  298. });
  299. }
  300. function reWriteCommentElem(commentElem, commentThreadRenderer) {
  301. const commentRenderer = commentElem.__shady_native_children[0];
  302. if (commentRenderer !== null && commentRenderer !== void 0) {
  303. let isContainer = commentThreadRenderer.comment.commentRenderer.authorIsChannelOwner;
  304. if (commentThreadRenderer.comment.commentRenderer.authorCommentBadge !== void 0) {
  305. isContainer = true;
  306. }
  307. nameRewriteOfCommentRenderer(
  308. commentRenderer,
  309. isContainer,
  310. commentThreadRenderer.comment.commentRenderer.authorEndpoint.browseEndpoint.browseId
  311. );
  312. }
  313. }
  314. async function getCommentElem(trackingParams) {
  315. return await new Promise((resolve) => {
  316. const commentElem = findElementByTrackingParams(
  317. trackingParams,
  318. "#comments > #sections > #contents > ytd-comment-thread-renderer"
  319. );
  320. if (commentElem !== null) {
  321. resolve(commentElem);
  322. } else {
  323. void reSearchElement(trackingParams, "ytd-comment-thread-renderer").then((commentElem2) => {
  324. resolve(commentElem2);
  325. }).catch((e) => {
  326. debugErr(e);
  327. });
  328. }
  329. });
  330. }
  331.  
  332. // src/handlers/handleYtAppendContinuationItemsAction.ts
  333. function handleYtAppendContinuationItemsAction(detail) {
  334. const continuationItems = detail.args[0].appendContinuationItemsAction.continuationItems;
  335. if (isCommentRenderer(continuationItems)) {
  336. const replyDetail = detail;
  337. setTimeout(() => {
  338. rewriteReplytNameFromContinuationItems(
  339. replyDetail.args[0].appendContinuationItemsAction.continuationItems
  340. );
  341. }, 1);
  342. } else {
  343. const commentDetail = detail;
  344. setTimeout(() => {
  345. rewriteCommentNameFromContinuationItems(
  346. commentDetail.args[0].appendContinuationItemsAction.continuationItems
  347. );
  348. }, 10);
  349. }
  350. }
  351.  
  352. // src/handlers/handleYtCreateCommentAction.ts
  353. function handleYtCreateCommentAction(detail) {
  354. const createCommentDetail = detail;
  355. const continuationItems = [
  356. {
  357. commentThreadRenderer: createCommentDetail.args[0].createCommentAction.contents.commentThreadRenderer
  358. }
  359. ];
  360. setTimeout(() => {
  361. rewriteCommentNameFromContinuationItems(continuationItems);
  362. }, 100);
  363. }
  364.  
  365. // src/handlers/handleYtCreateCommentReplyAction.ts
  366. function handleYtCreateCommentReplyAction(detail) {
  367. const createReplyDetail = detail;
  368. const continuationItems = [
  369. {
  370. commentRenderer: createReplyDetail.args[0].createCommentReplyAction.contents.commentRenderer
  371. }
  372. ];
  373. setTimeout(() => {
  374. rewriteTeaserReplytNameFromContinuationItems(continuationItems);
  375. }, 100);
  376. }
  377.  
  378. // src/rewrites/highlightedReply.ts
  379. function rewriteHighlightedReply(trackedParams, isContainer, userId) {
  380. const elem = findElementByTrackingParams(
  381. trackedParams,
  382. "ytd-comment-renderer"
  383. );
  384. const rewriteHighlightedReplyElem = (elem2) => {
  385. nameRewriteOfCommentRenderer(elem2, isContainer, userId);
  386. };
  387. if (elem === null) {
  388. void reSearchElement(trackedParams, "ytd-comment-renderer").then((elem2) => {
  389. rewriteHighlightedReplyElem(elem2);
  390. });
  391. } else {
  392. rewriteHighlightedReplyElem(elem);
  393. }
  394. }
  395.  
  396. // src/handlers/handleYtGetMultiPageMenuAction.ts
  397. function handleYtGetMultiPageMenuAction(detail) {
  398. const getMultiPageMenuDetail = detail;
  399. const continuationItems = getMultiPageMenuDetail.args[0].getMultiPageMenuAction.menu.multiPageMenuRenderer.sections[1].itemSectionRenderer?.contents;
  400. const highLightedTeaserContents = getMultiPageMenuDetail.args[0]?.getMultiPageMenuAction?.menu?.multiPageMenuRenderer.sections[1].itemSectionRenderer?.contents[0]?.commentThreadRenderer.replies?.commentRepliesRenderer?.teaserContents;
  401. if (continuationItems !== void 0) {
  402. setTimeout(() => {
  403. rewriteCommentNameFromContinuationItems(continuationItems);
  404. if (highLightedTeaserContents !== void 0) {
  405. const highLightedReplyRenderer = highLightedTeaserContents[0]?.commentRenderer;
  406. let isContainer = highLightedReplyRenderer.authorIsChannelOwner;
  407. if (highLightedReplyRenderer.authorCommentBadge !== void 0) {
  408. isContainer = true;
  409. }
  410. rewriteHighlightedReply(
  411. highLightedReplyRenderer.trackingParams,
  412. isContainer,
  413. highLightedReplyRenderer.authorEndpoint.browseEndpoint.browseId
  414. );
  415. }
  416. }, 100);
  417. }
  418. }
  419.  
  420. // src/handlers/handleYtHistory.ts
  421. function handleYtHistory(detail) {
  422. const historyDetail = detail;
  423. const continuationItems = historyDetail.args[1].historyEntry?.rootData.response.contents.twoColumnWatchNextResults?.results?.results?.contents[3]?.itemSectionRenderer?.contents;
  424. if (continuationItems !== void 0) {
  425. setTimeout(() => {
  426. rewriteCommentNameFromContinuationItems(continuationItems);
  427. }, 100);
  428. }
  429. }
  430.  
  431. // src/handlers/handleYtReloadContinuationItemsCommand.ts
  432. function handleYtReloadContinuationItemsCommand(detail) {
  433. const reloadDetail = detail;
  434. const { slot } = reloadDetail.args[0].reloadContinuationItemsCommand;
  435. if (slot === "RELOAD_CONTINUATION_SLOT_BODY") {
  436. const continuationItems = reloadDetail.args[0].reloadContinuationItemsCommand.continuationItems;
  437. if (continuationItems !== void 0) {
  438. setTimeout(() => {
  439. rewriteCommentNameFromContinuationItems(continuationItems);
  440. }, 100);
  441. }
  442. }
  443. }
  444.  
  445. // src/index.ts
  446. function main() {
  447. debugLog("Script start");
  448. const handleYtAction = (e) => {
  449. const { actionName } = e.detail;
  450. switch (actionName) {
  451. case "yt-append-continuation-items-action":
  452. handleYtAppendContinuationItemsAction(e.detail);
  453. break;
  454. case "yt-reload-continuation-items-command":
  455. handleYtReloadContinuationItemsCommand(e.detail);
  456. break;
  457. case "yt-history-load":
  458. handleYtHistory(e.detail);
  459. break;
  460. case "yt-get-multi-page-menu-action":
  461. handleYtGetMultiPageMenuAction(e.detail);
  462. break;
  463. case "yt-create-comment-action":
  464. handleYtCreateCommentAction(e.detail);
  465. break;
  466. case "yt-create-comment-reply-action":
  467. handleYtCreateCommentReplyAction(e.detail);
  468. break;
  469. }
  470. };
  471. document.addEventListener("yt-action", handleYtAction);
  472. document.addEventListener("yt-navigate-finish", ({ detail }) => {
  473. document.removeEventListener("yt-action", handleYtAction);
  474. document.addEventListener("yt-action", handleYtAction);
  475. });
  476. }
  477.  
  478. // node_modules/ts-extension-builder/tmp/entry.ts
  479. var args = {};
  480. if (typeof GM_info !== "undefined" && GM_info.script.grant !== void 0) {
  481. GM_info.script.grant.forEach((propatyName) => {
  482. let keyName = propatyName.split("GM_")[1];
  483. if (keyName === "xmlhttpRequest") {
  484. keyName = "xmlHttpRequest";
  485. }
  486. args[propatyName] = GM[keyName];
  487. });
  488. }
  489. main(args);
  490. }
  491. const script = document.createElement("script");
  492. script.innerHTML = `(${inject.toString()})()`
  493. unsafeWindow.document.body.appendChild(script)