恢復 YouTube 评论用户名

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

当前为 2023-06-24 提交的版本,查看 最新版本

  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.5
  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 scriptString = `// src/getUserName.ts
  21. async function getUserName(id) {
  22. const data = await fetch(
  23. \`https://www.youtube.com/youtubei/v1/browse?key=AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8&prettyPrint=false\`,
  24. {
  25. method: "POST",
  26. headers: {
  27. accept: "*/*",
  28. "accept-encoding": "gzip, deflate, br",
  29. "accept-language": "ja",
  30. "content-type": "application/json",
  31. cookie: \`GPS=1; YSC=YajuSEnP; DEVICE_INFO=DEVICE_INFO; VISITOR_INFO1_LIVE=LLIIVVEE; PREF=f6=40000000&tz=Asia.Tokyo; ST-o2eza2=itct=itct&endpoint=%7B%22clickTrackingParams%22%3A%22CBQQ8JMBGAciEwjNqtCAASAhXnm1YBHABY%3D%22%2C%22commandMetadata%22%3A%7B%22webCommandMetadata%22%3A%7B%22url%22%3A%22%2F%40FUCKYOUTUBE%2Fchannels%22%2C%22webPageType%22%3A%22WEB_PAGE_TYPE_CHANNEL%22%2C%22rootVe%22%3A3611%2C%22apiUrl%22%3A%22%2Fyoutubei%2Fv1%2Fbrowse%22%7D%7D%2C%22browseEndpoint%22%3A%7B%22browseId%22%3A%22\${id}%22%2C%22params%22%3A%22EghjaGFubmVsc_IGBAoCUgA%253D%22%2C%22canonicalBaseUrl%22%3A%22%2F%40FUCK_YOUTUBE%22%7D%7D\`,
  32. dnt: "1",
  33. referer: \`https://www.youtube.com/channel/\${id}\`,
  34. "sec-ch-ua": \`"Chromium";v="110", "Not A(Brand";v="24", "Google Chrome";v="110"\`,
  35. "sec-ch-ua-arch": "x86",
  36. "sec-ch-ua-bitness": "64",
  37. "sec-ch-ua-full-version": "110.0.5481.104",
  38. "sec-ch-ua-full-version-list": \`"Chromium";v="110.0.5481.104", "Not A(Brand";v="24.0.0.0", "Google Chrome";v="110.0.5481.104"\`,
  39. "sec-ch-ua-mobile": "?0",
  40. "sec-ch-ua-platform": "Windows",
  41. "sec-ch-ua-platform-version": "15.0.0",
  42. "sec-ch-ua-wow64": "?0",
  43. "sec-fetch-dest": "empty",
  44. "sec-fetch-mode": "same-origin",
  45. "sec-fetch-site": "same-origin",
  46. "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36",
  47. "x-client-data": "x-client-data",
  48. "x-goog-authuser": "0",
  49. "x-goog-visitor-id": "visitorData",
  50. "x-origin": "https://www.youtube.com",
  51. "x-youtube-bootstrap-logged-in": "true",
  52. "x-youtube-client-name": "1",
  53. "x-youtube-client-version": "2.20230217.01.00"
  54. },
  55. body: JSON.stringify({
  56. context: {
  57. client: {
  58. hl: "ja",
  59. gl: "JP",
  60. remoteHost: "1919:8a10:1145:1419:e1c9:b81a:09db:ff3a",
  61. deviceMake: "",
  62. deviceModel: "",
  63. visitorData: "visitorData",
  64. userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36,gzip(gfe)",
  65. clientName: "WEB",
  66. clientVersion: "2.20230217.01.00",
  67. osName: "Windows",
  68. osVersion: "10.0",
  69. originalUrl: "https://www.youtube.com/@FUCK_YOUTUBE/channels",
  70. platform: "DESKTOP",
  71. clientFormFactor: "UNKNOWN_FORM_FACTOR",
  72. configInfo: {
  73. appInstallData: "appInstallData"
  74. },
  75. userInterfaceTheme: "USER_INTERFACE_THEME_DARK",
  76. timeZone: "Asia/Tokyo",
  77. browserName: "Chrome",
  78. browserVersion: "110.0.0.0",
  79. 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",
  80. deviceExperimentId: "deviceExperimentId",
  81. screenWidthPoints: 599,
  82. screenHeightPoints: 937,
  83. screenPixelDensity: 1,
  84. screenDensityFloat: 1,
  85. utcOffsetMinutes: 540,
  86. memoryTotalKbytes: "8000000",
  87. mainAppWebInfo: {
  88. graftUrl: "/@FUCK_YOUTUBE/channels",
  89. pwaInstallabilityStatus: "PWA_INSTALLABILITY_STATUS_CAN_BE_INSTALLED",
  90. webDisplayMode: "WEB_DISPLAY_MODE_BROWSER",
  91. isWebNativeShareAvailable: true
  92. }
  93. },
  94. user: { lockedSafetyMode: false },
  95. request: {
  96. useSsl: true,
  97. internalExperimentFlags: [],
  98. consistencyTokenJars: []
  99. },
  100. clickTracking: {
  101. clickTrackingParams: "UnkoBuuriiiiiiiicuuusssaiMAJIDE="
  102. },
  103. adSignalsInfo: {
  104. params: [
  105. { key: "dt", value: "1145141919810" },
  106. { key: "flash", value: "0" },
  107. { key: "frm", value: "0" },
  108. { key: "u_tz", value: "540" },
  109. { key: "u_his", value: "1" },
  110. { key: "u_h", value: "1080" },
  111. { key: "u_w", value: "1920" },
  112. { key: "u_ah", value: "1040" },
  113. { key: "u_aw", value: "1920" },
  114. { key: "u_cd", value: "24" },
  115. { key: "bc", value: "31" },
  116. { key: "bih", value: "937" },
  117. { key: "biw", value: "582" },
  118. {
  119. key: "brdim",
  120. value: "-1920,0,-1920,0,1920,0,1920,1040,599,937"
  121. },
  122. { key: "vis", value: "1" },
  123. { key: "wgl", value: "true" },
  124. { key: "ca_type", value: "image" }
  125. ]
  126. }
  127. },
  128. browseId: id,
  129. params: "YajuSenpaiInmu1919%3D"
  130. })
  131. }
  132. ).then(async (res) => await res.text()).then((text) => {
  133. const data2 = JSON.parse(text);
  134. const name = data2.header.c4TabbedHeaderRenderer.title;
  135. return name;
  136. });
  137. return data;
  138. }
  139.  
  140. // src/index.ts
  141. function main() {
  142. const handleYtAction = (e) => {
  143. const { actionName } = e.detail;
  144. switch (actionName) {
  145. case "yt-append-continuation-items-action":
  146. handleYtAppendContinuationItemsAction(e.detail);
  147. break;
  148. case "yt-reload-continuation-items-command":
  149. handleYtReloadContinuationItemsCommand(e.detail);
  150. break;
  151. case "yt-history-load":
  152. handleYtHistory(e.detail);
  153. break;
  154. case "yt-get-multi-page-menu-action":
  155. handleYtGetMultiPageMenuAction(e.detail);
  156. break;
  157. case "yt-create-comment-action":
  158. handleYtCreateCommentAction(e.detail);
  159. break;
  160. }
  161. };
  162. document.addEventListener("yt-action", handleYtAction);
  163. document.addEventListener("yt-navigate-finish", ({ detail }) => {
  164. document.removeEventListener("yt-action", handleYtAction);
  165. document.addEventListener("yt-action", handleYtAction);
  166. });
  167. }
  168. function handleYtAppendContinuationItemsAction(detail) {
  169. const continuationItems = detail.args[0].appendContinuationItemsAction.continuationItems;
  170. if (isCommentRenderer(continuationItems)) {
  171. const replyDetail = detail;
  172. setTimeout(() => {
  173. rewriteReplytNameFromContinuationItems(
  174. replyDetail.args[0].appendContinuationItemsAction.continuationItems
  175. );
  176. }, 1);
  177. } else {
  178. const commentDetail = detail;
  179. setTimeout(() => {
  180. rewriteCommentNameFromContinuationItems(
  181. commentDetail.args[0].appendContinuationItemsAction.continuationItems
  182. );
  183. }, 100);
  184. }
  185. }
  186. function handleYtReloadContinuationItemsCommand(detail) {
  187. const reloadDetail = detail;
  188. const { slot } = reloadDetail.args[0].reloadContinuationItemsCommand;
  189. if (slot === "RELOAD_CONTINUATION_SLOT_BODY") {
  190. const continuationItems = reloadDetail.args[0].reloadContinuationItemsCommand.continuationItems;
  191. setTimeout(() => {
  192. rewriteCommentNameFromContinuationItems(continuationItems);
  193. }, 100);
  194. }
  195. }
  196. function handleYtHistory(detail) {
  197. const historyDetail = detail;
  198. const continuationItems = historyDetail.args[1].historyEntry?.rootData.response.contents.twoColumnWatchNextResults?.results?.results?.contents[3]?.itemSectionRenderer?.contents;
  199. if (continuationItems !== void 0) {
  200. setTimeout(() => {
  201. rewriteCommentNameFromContinuationItems(continuationItems);
  202. }, 100);
  203. }
  204. }
  205. function handleYtGetMultiPageMenuAction(detail) {
  206. const getMultiPageMenuDetail = detail;
  207. const continuationItems = getMultiPageMenuDetail.args[0].getMultiPageMenuAction.menu.multiPageMenuRenderer.sections[1].itemSectionRenderer?.contents;
  208. const highLightedTeaserContents = getMultiPageMenuDetail.args[0]?.getMultiPageMenuAction?.menu?.multiPageMenuRenderer.sections[1].itemSectionRenderer?.contents[0]?.commentThreadRenderer.replies?.commentRepliesRenderer?.teaserContents;
  209. if (continuationItems !== void 0) {
  210. setTimeout(() => {
  211. rewriteCommentNameFromContinuationItems(continuationItems);
  212. if (highLightedTeaserContents !== void 0) {
  213. const highLightedReplyRenderer = highLightedTeaserContents[0]?.commentRenderer;
  214. let isContainer = highLightedReplyRenderer.authorIsChannelOwner;
  215. if (highLightedReplyRenderer.authorCommentBadge !== void 0) {
  216. isContainer = true;
  217. }
  218. rewriteHighlightedReply(
  219. highLightedReplyRenderer.trackingParams,
  220. isContainer,
  221. highLightedReplyRenderer.authorEndpoint.browseEndpoint.browseId
  222. );
  223. }
  224. }, 100);
  225. }
  226. }
  227. function rewriteHighlightedReply(trackedParams, isContainer, userId) {
  228. const elem = findElementByTrackingParams(
  229. trackedParams,
  230. "ytd-comment-renderer"
  231. );
  232. const rewriteHighlightedReplyElem = (elem2) => {
  233. nameRewriteOfCommentRenderer(elem2, isContainer, userId);
  234. };
  235. if (elem === null) {
  236. void reSearchElement(trackedParams, "ytd-comment-renderer").then((elem2) => {
  237. rewriteHighlightedReplyElem(elem2);
  238. });
  239. } else {
  240. rewriteHighlightedReplyElem(elem);
  241. }
  242. }
  243. function handleYtCreateCommentAction(detail) {
  244. const createCommentDetail = detail;
  245. const continuationItems = [
  246. {
  247. commentThreadRenderer: createCommentDetail.args[0].createCommentAction.contents.commentThreadRenderer
  248. }
  249. ];
  250. setTimeout(() => {
  251. rewriteCommentNameFromContinuationItems(continuationItems);
  252. }, 100);
  253. }
  254. function rewriteReplytNameFromContinuationItems(continuationItems) {
  255. continuationItems.forEach((continuationItem) => {
  256. const { commentRenderer } = continuationItem;
  257. if (commentRenderer !== void 0) {
  258. const replyCommentRenderer = findElementByTrackingParams(
  259. commentRenderer.trackingParams,
  260. "ytd-comment-renderer"
  261. );
  262. const reWriteReplyCommentRenderer = (replyCommentRenderer2) => {
  263. let isContainer = commentRenderer.authorIsChannelOwner;
  264. if (commentRenderer.authorCommentBadge !== void 0) {
  265. isContainer = true;
  266. }
  267. nameRewriteOfCommentRenderer(
  268. replyCommentRenderer2,
  269. isContainer,
  270. commentRenderer.authorEndpoint.browseEndpoint.browseId
  271. );
  272. mentionRewriteOfCommentRenderer(replyCommentRenderer2);
  273. };
  274. if (replyCommentRenderer !== null) {
  275. reWriteReplyCommentRenderer(replyCommentRenderer);
  276. } else {
  277. void reSearchElement(
  278. commentRenderer.trackingParams,
  279. "ytd-comment-renderer"
  280. ).then((el) => {
  281. reWriteReplyCommentRenderer(el);
  282. });
  283. }
  284. }
  285. });
  286. }
  287. function rewriteCommentNameFromContinuationItems(continuationItems) {
  288. continuationItems.forEach((continuationItem) => {
  289. const { commentThreadRenderer } = continuationItem;
  290. if (commentThreadRenderer !== void 0) {
  291. const { trackingParams } = commentThreadRenderer;
  292. const commentElem = findElementByTrackingParams(
  293. trackingParams,
  294. "#comments > #sections > #contents > ytd-comment-thread-renderer"
  295. );
  296. const reWriteCommentElem = (commentElem2) => {
  297. const commentRenderer = commentElem2.__shady_native_children[0];
  298. if (commentRenderer !== null && commentRenderer !== void 0) {
  299. let isContainer = commentThreadRenderer.comment.commentRenderer.authorIsChannelOwner;
  300. if (commentThreadRenderer.comment.commentRenderer.authorCommentBadge !== void 0) {
  301. isContainer = true;
  302. }
  303. nameRewriteOfCommentRenderer(
  304. commentRenderer,
  305. isContainer,
  306. commentThreadRenderer.comment.commentRenderer.authorEndpoint.browseEndpoint.browseId
  307. );
  308. }
  309. };
  310. if (commentElem !== null) {
  311. reWriteCommentElem(commentElem);
  312. } else {
  313. void reSearchElement(
  314. trackingParams,
  315. "ytd-comment-thread-renderer"
  316. ).then((commentElem2) => {
  317. reWriteCommentElem(commentElem2);
  318. });
  319. }
  320. }
  321. });
  322. }
  323. function nameRewriteOfCommentRenderer(commentRenderer, isNameContainerRender, userId) {
  324. const commentRendererBody = commentRenderer.__shady_native_children[2];
  325. let nameElem = commentRendererBody.querySelector(
  326. "#main > #header > #header-author > h3 > a > span"
  327. );
  328. if (isNameContainerRender) {
  329. nameElem = commentRendererBody.__shady_native_children[1].querySelector(
  330. "#header > #header-author > #author-comment-badge > ytd-author-comment-badge-renderer > a > #channel-name > #container > #text-container > yt-formatted-string"
  331. );
  332. }
  333. void getUserName(userId).then((name) => {
  334. if (nameElem !== null) {
  335. if (isNameContainerRender) {
  336. nameElem.__shady_native_innerHTML = name;
  337. } else {
  338. nameElem.textContent = name;
  339. }
  340. }
  341. });
  342. }
  343. function mentionRewriteOfCommentRenderer(commentRenderer) {
  344. const commentRendererBody = commentRenderer.__shady_native_children[2];
  345. const main2 = commentRendererBody.__shady_native_children[1];
  346. const aTags = main2.querySelectorAll(
  347. "#comment-content > ytd-expander > #content > #content-text > a"
  348. );
  349. aTags.forEach((aTag) => {
  350. if (aTag.textContent?.match("@.*") !== null) {
  351. const href = aTag.getAttribute("href");
  352. if (href !== null) {
  353. void getUserName(href.split("/")[2]).then((name) => {
  354. aTag.textContent = \`@\${name} \`;
  355. });
  356. }
  357. }
  358. });
  359. }
  360. function isCommentRenderer(continuationItems) {
  361. if (continuationItems.length > 0) {
  362. if (continuationItems[0].hasOwnProperty("commentThreadRenderer")) {
  363. return false;
  364. }
  365. if (continuationItems[0].hasOwnProperty("commentRenderer")) {
  366. return true;
  367. }
  368. }
  369. return false;
  370. }
  371. function findElementByTrackingParams(trackingParams, elementSelector) {
  372. let returnElement = null;
  373. const elems = document.querySelectorAll(elementSelector);
  374. elems.forEach((elem) => {
  375. if (elem.trackedParams === trackingParams) {
  376. returnElement = elem;
  377. }
  378. });
  379. return returnElement;
  380. }
  381. async function reSearchElement(trackingParams, elementType) {
  382. return await new Promise((resolve) => {
  383. let isFinding = true;
  384. const search = () => {
  385. const el = findElementByTrackingParams(trackingParams, elementType);
  386. if (el !== null) {
  387. resolve(el);
  388. isFinding = false;
  389. }
  390. if (isFinding) {
  391. setTimeout(() => {
  392. search();
  393. }, 100);
  394. }
  395. };
  396. search();
  397. });
  398. }
  399.  
  400. // node_modules/ts-extension-builder/tmp/entry.ts
  401. var args = {};
  402. if (typeof GM_info !== "undefined" && GM_info.script.grant !== void 0) {
  403. GM_info.script.grant.forEach((propatyName) => {
  404. let keyName = propatyName.split("GM_")[1];
  405. if (keyName === "xmlhttpRequest") {
  406. keyName = "xmlHttpRequest";
  407. }
  408. args[propatyName] = GM[keyName];
  409. });
  410. }
  411. main(args);
  412. `;
  413. const script = document.createElement("script");
  414. script.innerHTML = scriptString
  415. unsafeWindow.document.body.appendChild(script)