├── .gitattributes ├── .github ├── CODEOWNERS ├── workflows │ ├── delete_old_workflows.yml │ ├── dependency-review.yml │ └── codeql-analysis.yml └── FUNDING.yml ├── images ├── ytn128.png └── ytn48.png ├── background.js ├── manifest.json ├── LICENSE ├── popup.js ├── popup.html ├── README.md └── script.js /.gitattributes: -------------------------------------------------------------------------------- 1 | * linguist-detectable 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Fallback to project maintainer 2 | * @Nomes77 3 | -------------------------------------------------------------------------------- /images/ytn128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nomes77/YT-Nonstop/HEAD/images/ytn128.png -------------------------------------------------------------------------------- /images/ytn48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nomes77/YT-Nonstop/HEAD/images/ytn48.png -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | chrome.runtime.onInstalled.addListener(() => { 4 | Reload(); 5 | }); 6 | 7 | function Reload() { 8 | chrome.tabs.query({ 9 | url: [ 10 | "https://www.youtube.com/*", 11 | "https://music.youtube.com/*" 12 | ] 13 | }, (tabs) => { 14 | for(let tab of tabs) { 15 | chrome.tabs.reload(tab.id) 16 | } 17 | }); 18 | }; 19 | -------------------------------------------------------------------------------- /.github/workflows/delete_old_workflows.yml: -------------------------------------------------------------------------------- 1 | name: Delete old workflow runs 2 | on: 3 | workflow_dispatch: 4 | schedule: 5 | - cron: '00 15 1 1,3,5,7,9,11 *' 6 | 7 | jobs: 8 | del_runs: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Delete workflow runs 12 | uses: Mattraks/delete-workflow-runs@main 13 | with: 14 | token: ${{ github.token }} 15 | repository: ${{ github.repository }} 16 | retain_days: 30 17 | keep_minimum_runs: 3 18 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ["https://www.paypal.com/donate/?hosted_button_id=NRARDMBBMV3LC"] 13 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "YT-Nonstop", 3 | "version": "1.5.3", 4 | "description": "Deletes the annoying \"Video paused. Continue watching?\" confirmation on YouTube and keeps YouTube running nonstop without autoplay message!", 5 | "permissions": [ "storage", "https://www.youtube.com/*", "https://music.youtube.com/*" ], 6 | "background": { 7 | "scripts": [ "background.js" ] 8 | }, 9 | "content_scripts": [ 10 | { 11 | "matches": [ "https://www.youtube.com/*", "https://music.youtube.com/*" ], 12 | "js": [ "script.js" ], 13 | "run_at": "document_end" 14 | } 15 | ], 16 | "page_action": { 17 | "default_icon": "images/ytn128.png", 18 | "default_popup": "popup.html", 19 | "show_matches": [ "https://www.youtube.com/*", "https://music.youtube.com/*" ] 20 | }, 21 | "icons": { 22 | "48": "images/ytn48.png", 23 | "128": "images/ytn128.png" 24 | }, 25 | "manifest_version": 2 26 | } 27 | -------------------------------------------------------------------------------- /.github/workflows/dependency-review.yml: -------------------------------------------------------------------------------- 1 | # Dependency Review Action 2 | # 3 | # This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. 4 | # 5 | # Source repository: https://github.com/actions/dependency-review-action 6 | # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement 7 | name: 'Dependency Review' 8 | on: [pull_request] 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | dependency-review: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: 'Checkout Repository' 18 | uses: actions/checkout@v3 19 | - name: 'Dependency Review' 20 | uses: actions/dependency-review-action@v3.0.2 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 BvdP 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /popup.js: -------------------------------------------------------------------------------- 1 | window.onload = () => { 2 | document.getElementById('autoskip-toggle').addEventListener("click", function(event) { 3 | //native html input element toggles on click 4 | setAutoTubeListeners('autoSkip'); 5 | }); 6 | setSettings([ 7 | {key: 'autoSkip', cb: setAutoSkip}, 8 | ]); 9 | }; // end window.onload 10 | 11 | // helpers 12 | function setSettings(items){ 13 | chrome.storage.sync.get(null, function(data) { 14 | const setItems = {}; 15 | items.forEach( ({key, cb}) => { 16 | if (data === undefined || data[key] === undefined || data[key] === null) { 17 | setItems.key = cb(true); 18 | } else if(!data[key]) { 19 | cb(false); 20 | } else { 21 | cb(true); 22 | } 23 | }); 24 | // update items if they were undefined or null 25 | Object.keys(setItems).length > 0 && chrome.storage.sync.set(setItems, function() {}); 26 | }); 27 | } 28 | 29 | function setAutoTubeListeners(key) { 30 | const value = { 31 | autoSkip: document.getElementById('autoskip-toggle').checked, 32 | }[key]; 33 | chrome.tabs.query({ 34 | url: [ 35 | "https://www.youtube.com/*", 36 | "https://music.youtube.com/*" 37 | ] 38 | }, 39 | (tabs) => { 40 | for (let tab of tabs) { 41 | chrome.tabs.sendMessage(tab.id, {[key]: value}); 42 | } 43 | }); 44 | chrome.storage.sync.set({[key]: value}); 45 | } 46 | 47 | function setAutoSkip(status) { 48 | return document.getElementById('autoskip-toggle').toggleAttribute('checked', status); 49 | } 50 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main; manifest_3 ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main; manifest_3 ] 20 | schedule: 21 | - cron: '00 12 1 * *' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] 37 | # Learn more: 38 | # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed 39 | 40 | steps: 41 | - name: Checkout repository 42 | uses: actions/checkout@v2 43 | 44 | # Initializes the CodeQL tools for scanning. 45 | - name: Initialize CodeQL 46 | uses: github/codeql-action/init@v1 47 | with: 48 | languages: ${{ matrix.language }} 49 | # If you wish to specify custom queries, you can do so here or in a config file. 50 | # By default, queries listed here will override any specified in a config file. 51 | # Prefix the list here with "+" to use these queries and those in the config file. 52 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 53 | 54 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 55 | # If this step fails, then you should remove it and run the build manually (see below) 56 | - name: Autobuild 57 | uses: github/codeql-action/autobuild@v1 58 | 59 | # ℹ️ Command-line programs to run using the OS shell. 60 | # 📚 https://git.io/JvXDl 61 | 62 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 63 | # and modify them (or add more) to build your code if your project 64 | # uses a compiled language 65 | 66 | #- run: | 67 | # make bootstrap 68 | # make release 69 | 70 | - name: Perform CodeQL Analysis 71 | uses: github/codeql-action/analyze@v1 72 | -------------------------------------------------------------------------------- /popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 116 | 117 | 118 |
119 |

YT-Nonstop

120 |
121 | 122 |
123 | Auto-skip to next video: 124 |
125 | 130 |
131 |
132 |
133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Commit rate `main`](https://img.shields.io/github/commit-activity/m/Nomes77/YT-Nonstop?label=Commits%20%60main%60&color=succes)](https://github.com/Nomes77/YT-Nonstop/commits/) 2 | [![Last commit `main`](https://img.shields.io/github/last-commit/Nomes77/YT-Nonstop?label=Last%20commit%20%60main%60&color=informational)](https://github.com/Nomes77/YT-Nonstop/commits/main) 3 | [![Commit rate `manifest_3`](https://img.shields.io/github/commit-activity/m/Nomes77/YT-Nonstop/manifest_3?label=Commits%20%60manifest_3%60&color=succes)](https://github.com/Nomes77/YT-Nonstop/commits/manifest_3) 4 | [![Last commit `manifest_3`](https://img.shields.io/github/last-commit/Nomes77/YT-Nonstop/manifest_3?label=Last%20commit%20%60manifest_3%60&color=informational)](https://github.com/Nomes77/YT-Nonstop/commits/manifest_3)
5 | [![Issues](https://img.shields.io/github/issues/Nomes77/YT-Nonstop?label=Issues&color=red)](https://github.com/Nomes77/YT-Nonstop/issues) 6 | [![Issues](https://img.shields.io/github/issues-closed/Nomes77/YT-Nonstop?color=green&label=Issues)](https://github.com/Nomes77/YT-Nonstop/issues?q=is%3Aissue+is%3Aclosed) 7 | [![GitHub Release Date](https://img.shields.io/github/release-date/Nomes77/YT-Nonstop?color=white&label=Latest%20Release)](https://github.com/Nomes77/YT-Nonstop/releases/) 8 | [![License](https://img.shields.io/badge/License-MIT-blue.svg?label=License&color=lightgrey)](https://github.com/Nomes77/YT-Nonstop/blob/main/LICENSE)
9 | [![](https://img.shields.io/badge/dynamic/json?label=Edge&color=important&prefix=v&query=%24.version&url=https%3A%2F%2Fmicrosoftedge.microsoft.com%2Faddons%2Fgetproductdetailsbycrxid%2Fddobgngkifgapahlheghhckckkcgpikf)](https://microsoftedge.microsoft.com/addons/detail/ytnonstop/ddobgngkifgapahlheghhckckkcgpikf) 10 | [![](https://img.shields.io/badge/dynamic/json?label=Rating&color=yellow&suffix=/5&query=%24.averageRating&url=https%3A%2F%2Fmicrosoftedge.microsoft.com%2Faddons%2Fgetproductdetailsbycrxid%2Fddobgngkifgapahlheghhckckkcgpikf)](https://microsoftedge.microsoft.com/addons/detail/ytnonstop/ddobgngkifgapahlheghhckckkcgpikf) 11 | [![](https://img.shields.io/badge/dynamic/json?label=Users&color=blueviolet&query=%24.activeInstallCount&url=https%3A%2F%2Fmicrosoftedge.microsoft.com%2Faddons%2Fgetproductdetailsbycrxid%2Fddobgngkifgapahlheghhckckkcgpikf)](https://microsoftedge.microsoft.com/addons/detail/ytnonstop/ddobgngkifgapahlheghhckckkcgpikf)
12 | [![](https://img.shields.io/amo/v/yt-nonstop?label=FireFox&color=important)](https://addons.mozilla.org/en-US/firefox/addon/yt-nonstop/) 13 | [![](https://img.shields.io/amo/rating/yt-nonstop?label=Rating&color=yellow)](https://addons.mozilla.org/en-US/firefox/addon/yt-nonstop/) 14 | [![](https://img.shields.io/amo/users/yt-nonstop?label=Users&color=blueviolet)](https://addons.mozilla.org/en-US/firefox/addon/yt-nonstop/) 15 | *** 16 | # YT-Nonstop 17 | 18 | Autoclicker for Youtube's latest "feature" - Video paused. Continue watching?
19 | Furthermore it keeps YouTube running and auto-skip to the next video on the list 🔥 20 | 21 |

22 | Get YT-Nonstop for Firefox 23 | Get YT-Nonstop for Microsoft Edge 24 |

25 | 26 | *** 27 | #### If you want to load the extension by yourself in your browser without installing it from store or Microsoft suddenly decides to take action against it, follow the instructions below: 28 | 29 | 1. Clone or download this repository 30 | - If you download it, make sure to extract it first 31 | 3. Open the Extension Management page by navigating to `edge://extensions` 32 | - The Extension Management page can also be opened by clicking on the Edge menu, hovering over More Tools then selecting Extensions. 33 | 6. Enable Developer Mode by clicking the toggle switch next to Developer mode. 34 | 7. Click the Load unpacked button and select the extension directory. 35 | 8. Ta-da! The extension has been successfully installed! 36 | 37 | -------------------------------------------------------------------------------- /script.js: -------------------------------------------------------------------------------- 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 = { 29 | player: () => document.getElementById('movie_player'), 30 | }; 31 | 32 | function getTimestamp() { 33 | return new Date().toLocaleTimeString(); 34 | } 35 | function log(message) { 36 | console.log(`[YT-Nonstop | ${getTimestamp()}] ${message}`); 37 | } 38 | 39 | // .getPlayerState(): -1 = unstarted, 0 = ended, 1 = playing, 2 = paused, 3 = buffering, 5 = video cued 40 | // if video paused ---> play video 41 | const play = () => { 42 | const popupEventNodename = YTMusic ? document.querySelector('YTMUSIC-YOU-THERE-RENDERER') : 43 | document.querySelector('YT-CONFIRM-DIALOG-RENDERER'); 44 | const popupContainer = YTMusic ? document.getElementsByTagName('ytmusic-popup-container')[0] : 45 | document.getElementsByTagName('ytd-popup-container')[0]; 46 | // Make sure that the right popup is shown 47 | const wrongPopup = document.querySelector('YT-CONFIRM-DIALOG-RENDERER #cancel-button:not([hidden])'); 48 | 49 | if (videoPlayer.player().getPlayerState() === 2 && popupEventNodename && !wrongPopup) { 50 | videoPlayer.player().playVideo(); 51 | popupContainer.handleClosePopupAction_(); 52 | log('Popup hidden and video played again'); 53 | } 54 | } 55 | 56 | // if video ended ---> skip to next video 57 | const skip = () => { 58 | if (videoPlayer.player().getPlayerState() === 0 && !YTMusic) { 59 | const overlay = document.querySelector('.ytp-autonav-endscreen-countdown-overlay[style="display: none;"]'); 60 | const overlay_v = document.getElementsByClassName('ytp-autonav-endscreen-countdown-overlay')[0]; 61 | const next = document.getElementsByClassName('ytp-autonav-endscreen-upnext-play-button')[0]; 62 | const cancel = document.getElementsByClassName('ytp-autonav-endscreen-upnext-cancel-button')[0]; 63 | const autonav_off = document.querySelector('.ytp-autonav-toggle-button-container > .ytp-autonav-toggle-button[aria-checked="false"]'); 64 | 65 | if (autotube.getIsAutoSkip() == true && (!overlay || autonav_off)) { 66 | // videoPlayer.player().setAutonav(true); 67 | // videoPlayer.player().nextVideo(); 68 | overlay_v.remove(); 69 | next.click(); 70 | log('Skipped to next video'); 71 | } else 72 | if (autotube.getIsAutoSkip() == false && !overlay) { 73 | // videoPlayer.player().setAutonav(false); 74 | overlay_v.remove(); 75 | cancel.click(); 76 | log('Canceled next video'); 77 | } 78 | } 79 | } 80 | 81 | const autonav_button = () => { 82 | const autonav_on = YTMusic ? document.querySelector('#automix[role="button"][aria-pressed="true"]') : 83 | document.querySelector('.ytp-autonav-toggle-button-container > .ytp-autonav-toggle-button[aria-checked="true"]'); 84 | const autonav_off = YTMusic ? document.querySelector('#automix[role="button"][aria-pressed="false"]') : 85 | document.querySelector('.ytp-autonav-toggle-button-container > .ytp-autonav-toggle-button[aria-checked="false"]'); 86 | 87 | if (autotube.getIsAutoSkip() == true && autonav_off) { 88 | autonav_off.click(); 89 | log('Enabled autoplay/autonav'); 90 | } else 91 | if (autotube.getIsAutoSkip() == false && autonav_on) { 92 | autonav_on.click(); 93 | log('Disabled autoplay/autonav'); 94 | } 95 | } 96 | 97 | const autonav_button_style = () => { 98 | const autonav = YTMusic ? document.getElementsByClassName('autoplay')[1] : 99 | document.querySelector('.ytp-button[data-tooltip-target-id="ytp-autonav-toggle-button"]'); 100 | 101 | autonav.setAttribute("style", "height:0px; width:0px; opacity:0"); 102 | log('Hide autoplay/autonav, since the button is overriden'); 103 | } 104 | 105 | function run() { 106 | const play_button = { 107 | getButton: window.document.getElementsByClassName('ytp-play-button ytp-button')[0] 108 | || window.document.getElementById('play-pause-button'), 109 | config: { attributes: true, childList: true, subtree: true }, 110 | callback: (mutationsList, observer) => { 111 | play(); 112 | skip(); 113 | } 114 | } 115 | 116 | const loadSettings = { 117 | setSettings: setInterval(() => { 118 | if (window.location.href.indexOf("/watch") == -1) return; 119 | 120 | // set play button observer 121 | try { 122 | const play_button_observer = new MutationObserver(play_button.callback); 123 | play_button_observer.observe(play_button.getButton, play_button.config); 124 | } catch(e) { 125 | log('Play button does not exist; reload page'); 126 | window.location.reload(); 127 | } 128 | 129 | // set autonav button 130 | autonav_button(); 131 | autonav_button_style(); 132 | 133 | clearInterval(loadSettings.setSettings); 134 | }, 1000), 135 | 136 | setAutonavButton: setInterval(() => { 137 | if (window.location.href.indexOf("/watch") == -1) { 138 | if (document.querySelector('ytd-app[miniplayer-is-active]') || document.querySelector('ytmusic-player-bar:not([player-page-open_])')) { 139 | autonav_button(); 140 | } else { 141 | return; 142 | } 143 | } 144 | autonav_button(); 145 | }, 5000), 146 | 147 | // Autoplay Method 1: Set last time active all 20 minutes to now 148 | // Autoplay Method 2: If video paused and popup visible ---> play video 149 | // Autoplay Method 3: Pause and UnPause after 20 minutes 150 | setOtherMethods: setInterval(() => { 151 | if (window.location.href.indexOf("/watch") == -1) { 152 | if (document.querySelector('ytd-app[miniplayer-is-active]') || document.querySelector('ytmusic-player-bar:not([player-page-open_])')) { 153 | window._lact = Date.now(); 154 | log('Reset last time active'); 155 | play(); 156 | } else { 157 | return; 158 | } 159 | } 160 | window._lact = Date.now(); 161 | log('Reset last time active'); 162 | play(); 163 | }, 600000) 164 | } 165 | 166 | return autotube; 167 | }; 168 | 169 | // exposing functions 170 | function _getIsAutoSkip() { return autotube.getIsAutoSkip() }; 171 | function YTNonstop () { 172 | this.isAutoSkip = _getIsAutoSkip; 173 | run(); 174 | }; 175 | 176 | const eventHandler = (key, value) => { 177 | switch(key) { 178 | case "autoSkip": 179 | autotube.setAutoSkip(value); 180 | break; 181 | } 182 | } 183 | addEventListener('message', function(data) { 184 | for (key in data.data){ 185 | eventHandler(key, data.data[key]); 186 | } 187 | }); 188 | 189 | // Return YTNonstop object 190 | return YTNonstop; 191 | }); 192 | 193 | window.onload = (event) => { 194 | chrome.runtime.onMessage.addListener( (data) => { 195 | postMessage(data, '*'); 196 | }); 197 | chrome.storage.sync.get(null, function(data) { 198 | data = { 199 | autoSkip: data.autoSkip === undefined || data.autoSkip === null ? true : JSON.parse(data.autoSkip), 200 | } 201 | postMessage(data, '*'); 202 | // injectScript(YTNonstop, 'html'); 203 | }); 204 | }; 205 | 206 | injectScript(YTNonstop, 'html'); 207 | --------------------------------------------------------------------------------