Youtube全画面

Execute UserScript

  1. // ==UserScript==
  2. // @name Youtube全画面
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.5
  5. // @description Execute UserScript
  6. // @author Your Name
  7. // @match https://m.youtube.com
  8. // @grant none
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14. document.addEventListener('keydown', (e) => {
  15. if (e.key === 'c') {
  16. javascript:(function(){
  17. const DEBUG_MODE = false;
  18. const MAX_RETRY = 3;
  19. const DELAY = 500;
  20.  
  21. const youtubeClicker = {
  22. init: function(x, y) {
  23. this.retryCount = 0;
  24. this.targetX = x;
  25. this.targetY = y;
  26. this.attemptClick();
  27. },
  28.  
  29. attemptClick: function() {
  30. try {
  31. const element = this.findDeepElement(this.targetX, this.targetY);
  32. if (!element) {
  33. if (this.retryCount < MAX_RETRY) {
  34. this.retryCount++;
  35. setTimeout(() => this.attemptClick(), DELAY);
  36. return;
  37. }
  38. throw new Error('要素が見つかりません');
  39. }
  40.  
  41. this.simulateFullClickSequence(element);
  42. DEBUG_MODE && console.log('YouTubeクリック成功');
  43. } catch (error) {
  44. console.error('YouTubeクリックエラー:', error);
  45. }
  46. },
  47.  
  48. findDeepElement: function(x, y) {
  49. const traverseShadowDOM = (element) => {
  50. if (element.shadowRoot) {
  51. const shadowElement = document.elementFromPoint(x, y);
  52. return shadowElement ? traverseShadowDOM(shadowElement) : element;
  53. }
  54. return element;
  55. };
  56.  
  57. let element = document.elementFromPoint(x, y);
  58. return element ? traverseShadowDOM(element) : null;
  59. },
  60.  
  61. simulateFullClickSequence: function(element) {
  62. const rect = element.getBoundingClientRect();
  63. const clientX = this.targetX;
  64. const clientY = this.targetY;
  65.  
  66. const events = [
  67. 'mousedown', 'mouseup', 'click', 'dblclick'
  68. ];
  69.  
  70. events.forEach(type => {
  71. const event = new MouseEvent(type, {
  72. view: window,
  73. bubbles: true,
  74. cancelable: true,
  75. clientX,
  76. clientY,
  77. relatedTarget: element
  78. });
  79. element.dispatchEvent(event);
  80. });
  81.  
  82. DEBUG_MODE && console.log('イベント発火シーケンス完了', {
  83. element,
  84. clientX,
  85. clientY
  86. });
  87. }
  88. };
  89.  
  90. /* 実行位置調整(YouTubeのサイドバーを考慮) */
  91. const adjustForYouTubeUI = () => {
  92. const sidebarWidth = document.querySelector('ytd-app')?.offsetWidth > 1400 ? 240 : 72;
  93. return { x: 320 + sidebarWidth, y: 200 };
  94. };
  95.  
  96. /* メイン実行 */
  97. const { x, y } = adjustForYouTubeUI();
  98. youtubeClicker.init(x, y);
  99. })();
  100. }
  101. });
  102. })();

QingJ © 2025

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