|
| 1 | +function injectScript(YTNonstop, tag) { |
| 2 | + var node = document.getElementsByTagName(tag)[0]; |
| 3 | + var init_inject_script = document.createElement('script'); |
| 4 | + var run_inject_script = document.createElement('script'); |
| 5 | + |
| 6 | + init_inject_script.setAttribute('type', 'text/javascript'); |
| 7 | + run_inject_script.setAttribute('type', 'text/javascript'); |
| 8 | + |
| 9 | + init_inject_script.append(`YTNonstop = ${YTNonstop}()`); |
| 10 | + node.appendChild(init_inject_script); |
| 11 | + |
| 12 | + run_inject_script.append("autotube = YTNonstop = new YTNonstop();"); |
| 13 | + node.appendChild(run_inject_script); |
| 14 | + |
| 15 | + init_inject_script.remove(); |
| 16 | +} |
| 17 | + |
| 18 | +let YTNonstop = (function YTNonstop(options) { |
| 19 | + const MutationObserver = window.MutationObserver || window.WebKitMutationObserver; |
| 20 | + const autotube = { |
| 21 | + _autoSkip: null, |
| 22 | + //getters |
| 23 | + getIsAutoSkip: function() { return autotube._autoSkip}, |
| 24 | + // setters |
| 25 | + setAutoSkip: function(value) { return autotube._autoSkip = value}, |
| 26 | + } |
| 27 | + const YTMusic = window.location.hostname === 'music.youtube.com'; |
| 28 | + const videoPlayer = document.getElementById('movie_player'); |
| 29 | + |
| 30 | + function getTimestamp() { |
| 31 | + return new Date().toLocaleTimeString(); |
| 32 | + } |
| 33 | + function log(message) { |
| 34 | + console.log(`[YT-Nonstop | ${getTimestamp()}] ${message}`); |
| 35 | + } |
| 36 | + |
| 37 | + // .getPlayerState(): -1 = unstarted, 0 = ended, 1 = playing, 2 = paused, 3 = buffering, 5 = video cued |
| 38 | + // if video paused ---> play video |
| 39 | + const play = () => { |
| 40 | + const popupEventNodename = YTMusic ? document.querySelector('YTMUSIC-YOU-THERE-RENDERER') : |
| 41 | + document.querySelector('YT-CONFIRM-DIALOG-RENDERER'); |
| 42 | + const popupContainer = YTMusic ? document.getElementsByTagName('ytmusic-popup-container')[0] : |
| 43 | + document.getElementsByTagName('ytd-popup-container')[0]; |
| 44 | + |
| 45 | + if (videoPlayer.getPlayerState() === 2 && popupEventNodename) { |
| 46 | + videoPlayer.playVideo(); |
| 47 | + popupContainer.remove(); |
| 48 | + log('Popup hidden and video played again'); |
| 49 | + } |
| 50 | + } |
| 51 | + |
| 52 | + // if video ended ---> skip to next video |
| 53 | + const skip = () => { |
| 54 | + if (videoPlayer.getPlayerState() === 0 && !YTMusic) { |
| 55 | + const overlay = document.querySelector('.ytp-autonav-endscreen-countdown-overlay[style="display: none;"]'); |
| 56 | + const overlay_v = document.getElementsByClassName('ytp-autonav-endscreen-countdown-overlay')[0]; |
| 57 | + const next = document.getElementsByClassName('ytp-autonav-endscreen-upnext-play-button')[0]; |
| 58 | + const cancel = document.getElementsByClassName('ytp-autonav-endscreen-upnext-cancel-button')[0]; |
| 59 | + const autonav_off = document.querySelector('.ytp-autonav-toggle-button-container > .ytp-autonav-toggle-button[aria-checked="false"]'); |
| 60 | + |
| 61 | + if (autotube.getIsAutoSkip() == true && (!overlay || autonav_off)) { |
| 62 | + // videoPlayer.setAutonav(true); |
| 63 | + // videoPlayer.nextVideo(); |
| 64 | + overlay_v.remove(); |
| 65 | + next.click(); |
| 66 | + log('Skipped to next video'); |
| 67 | + } else |
| 68 | + if (autotube.getIsAutoSkip() == false && !overlay) { |
| 69 | + // videoPlayer.setAutonav(false); |
| 70 | + overlay_v.remove(); |
| 71 | + cancel.click(); |
| 72 | + log('Canceled next video'); |
| 73 | + } |
| 74 | + } |
| 75 | + } |
| 76 | + |
| 77 | + const autonav_button = () => { |
| 78 | + const autonav_on = YTMusic ? document.querySelector('#automix[role="button"][aria-pressed="true"]') : |
| 79 | + document.querySelector('.ytp-autonav-toggle-button-container > .ytp-autonav-toggle-button[aria-checked="true"]'); |
| 80 | + const autonav_off = YTMusic ? document.querySelector('#automix[role="button"][aria-pressed="false"]') : |
| 81 | + document.querySelector('.ytp-autonav-toggle-button-container > .ytp-autonav-toggle-button[aria-checked="false"]'); |
| 82 | + |
| 83 | + if (autotube.getIsAutoSkip() == true && autonav_off) { |
| 84 | + autonav_off.click(); |
| 85 | + log('Enabled autoplay/autonav'); |
| 86 | + } else |
| 87 | + if (autotube.getIsAutoSkip() == false && autonav_on) { |
| 88 | + autonav_on.click(); |
| 89 | + log('Disabled autoplay/autonav'); |
| 90 | + } |
| 91 | + } |
| 92 | + |
| 93 | + const autonav_button_style = () => { |
| 94 | + const autonav = YTMusic ? document.getElementsByClassName('autoplay')[1] : |
| 95 | + document.querySelector('.ytp-button[data-tooltip-target-id="ytp-autonav-toggle-button"]'); |
| 96 | + |
| 97 | + autonav.setAttribute("style", "height:0px; width:0px; opacity:0"); |
| 98 | + log('Hide autoplay/autonav, since the button is overriden'); |
| 99 | + } |
| 100 | + |
| 101 | + function run() { |
| 102 | + const play_button = { |
| 103 | + getButton: window.document.getElementsByClassName('ytp-play-button ytp-button')[0] |
| 104 | + || window.document.getElementById('play-pause-button'), |
| 105 | + config: { attributes: true, childList: true, subtree: true }, |
| 106 | + callback: (mutationsList, observer) => { |
| 107 | + play(); |
| 108 | + skip(); |
| 109 | + } |
| 110 | + } |
| 111 | + |
| 112 | + const loadSettings = { |
| 113 | + setSettings: setInterval(() => { |
| 114 | + if (window.location.href.indexOf("/watch") == -1 ) return; |
| 115 | + |
| 116 | + // set play button observer |
| 117 | + try { |
| 118 | + const play_button_observer = new MutationObserver(play_button.callback); |
| 119 | + play_button_observer.observe(play_button.getButton, play_button.config); |
| 120 | + } catch(e) { |
| 121 | + log('Play button does not exist; reload page'); |
| 122 | + window.location.reload(); |
| 123 | + } |
| 124 | + |
| 125 | + // set autonav button |
| 126 | + autonav_button(); |
| 127 | + autonav_button_style(); |
| 128 | + |
| 129 | + clearInterval(loadSettings.setSettings); |
| 130 | + }, 1000), |
| 131 | + |
| 132 | + setAutonavButton: setInterval(() => { |
| 133 | + if (window.location.href.indexOf("/watch") == -1 ) return; |
| 134 | + autonav_button(); |
| 135 | + }, 5000), |
| 136 | + |
| 137 | + // Autoplay Method 1: Set last time active all 20 minutes to now |
| 138 | + // Autoplay Method 2: If video paused and popup visible ---> play video |
| 139 | + // Autoplay Method 3: Pause and UnPause after 20 minutes |
| 140 | + setOtherMethods: setInterval(() => { |
| 141 | + if (window.location.href.indexOf("/watch") == -1 ) return; |
| 142 | + window._lact = Date.now(); |
| 143 | + log('Reset last time active'); |
| 144 | + play(); |
| 145 | + // if (videoPlayer.getPlayerState() === 1) { |
| 146 | + // videoPlayer.pauseVideo(); |
| 147 | + // videoPlayer.playVideo(); |
| 148 | + // log('Paused and unpaused video'); |
| 149 | + // } |
| 150 | + }, 600000) |
| 151 | + } |
| 152 | + |
| 153 | + return autotube; |
| 154 | + }; |
| 155 | + |
| 156 | + // exposing functions |
| 157 | + function _getIsAutoSkip() { return autotube.getIsAutoSkip() }; |
| 158 | + function YTNonstop () { |
| 159 | + this.isAutoSkip = _getIsAutoSkip; |
| 160 | + run(); |
| 161 | + }; |
| 162 | + |
| 163 | + const eventHandler = (key, value) => { |
| 164 | + switch(key) { |
| 165 | + case "autoSkip": |
| 166 | + autotube.setAutoSkip(value); |
| 167 | + break; |
| 168 | + } |
| 169 | + } |
| 170 | + addEventListener('message', function(data) { |
| 171 | + for (key in data.data){ |
| 172 | + eventHandler(key, data.data[key]); |
| 173 | + } |
| 174 | + }); |
| 175 | + |
| 176 | + // Return YTNonstop object |
| 177 | + return YTNonstop; |
| 178 | +}); |
| 179 | + |
| 180 | +injectScript(YTNonstop, 'html'); |
0 commit comments