Tradingview Skip Ads (desktop and mobile)

Trying to skip Cyber Monday sale, Black Friday sale, Easter sale and ads with a "Decline offer", "Competition started" or "The Leap is on" in them

  1. // ==UserScript==
  2. // @name Tradingview Skip Ads (desktop and mobile)
  3. // @description Trying to skip Cyber Monday sale, Black Friday sale, Easter sale and ads with a "Decline offer", "Competition started" or "The Leap is on" in them
  4. // @author Konf
  5. // @namespace https://greasyfork.org/users/424058
  6. // @icon https://www.google.com/s2/favicons?sz=64&domain=tradingview.com
  7. // @version 5.1.0
  8. // @match https://www.tradingview.com/*
  9. // @require https://cdnjs.cloudflare.com/ajax/libs/arrive/2.4.1/arrive.min.js#sha512-wkU3qYWjenbM+t2cmvw2ADRRh4opbOYBjkhrPGHV7M6dcE/TR0oKpoDkWXfUs3HrulI2JFuTQyqPLRih1V54EQ==
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM_registerMenuCommand
  13. // @grant GM_unregisterMenuCommand
  14. // @run-at document-start
  15. // @noframes
  16. // ==/UserScript==
  17.  
  18. /* jshint esversion: 11 */
  19.  
  20. (function() {
  21. 'use strict';
  22.  
  23. (function main() {
  24. if (!document.documentElement) return setTimeout(main);
  25.  
  26. const stats = GM_getValue('adSkipStats', {});
  27. let menuCommandId = null;
  28.  
  29. updateMenuCommand();
  30.  
  31. document.arrive('div.tv-dialog__modal-body',
  32. { existing: true },
  33. (modal) => {
  34. for (const span of modal.querySelectorAll('span')) {
  35. if (span.textContent.toLowerCase() === 'cyber monday') {
  36. modal.querySelector('div.tv-dialog__close').click();
  37. incrementStat('Cyber Monday');
  38. break;
  39. }
  40.  
  41. if (
  42. span.textContent.toLowerCase().includes('black friday')
  43. ) {
  44. modal.querySelector('div.tv-dialog__close').click();
  45. incrementStat('Black Friday');
  46. break;
  47. }
  48. }
  49. }
  50. );
  51.  
  52. document.arrive('div[data-dialog-name="gopro"]',
  53. { existing: true },
  54. (modal) => {
  55. if (findAndDeclineOffer(modal)) incrementStat('Go pro offer');
  56. }
  57. );
  58.  
  59. document.arrive('div[data-dialog-name="gopro-mobile"]',
  60. { existing: true },
  61. (modal) => {
  62. if (findAndDeclineOffer(modal)) incrementStat('Go pro mobile offer');
  63.  
  64. for (const p of modal.querySelectorAll('p')) {
  65. if (p.textContent.toLowerCase() === 'competition started') {
  66. modal.querySelector('button[aria-label="Close"]').click();
  67. incrementStat('Competition started');
  68. break;
  69. } else if (p.textContent.toLowerCase() === 'the leap is on') {
  70. modal.querySelector('button[class*=closeButton-]').click();
  71. incrementStat('The Leap is on');
  72. break;
  73. }
  74. }
  75. }
  76. );
  77.  
  78. document.arrive('div.banner-WnHzIH9Q',
  79. { existing: true },
  80. (popup) => {
  81. popup
  82. .closest('div.tv-dialog__modal-container')
  83. .querySelector('.tv-dialog__close')
  84. .click();
  85.  
  86. incrementStat('Black Friday №2');
  87. }
  88. );
  89.  
  90. document.arrive('p[class*=title-] > span[class*=gradient-]',
  91. { existing: true },
  92. (titlePart) => {
  93. if (titlePart.textContent.toLowerCase() !== 'easter sale') return;
  94.  
  95. titlePart
  96. .closest('div[class*=modal-]')
  97. .querySelector('button[class*=closeButton-]')
  98. .click();
  99.  
  100. incrementStat('Full page Easter Sale');
  101. }
  102. );
  103.  
  104. document.arrive('div[class*=header-] > p[class*=title-]',
  105. { existing: true },
  106. (title) => {
  107. if (!title.textContent.toLowerCase().startsWith('easter sale')) return;
  108.  
  109. const popupContainer = title.closest('div[class*=toastGroup-]');
  110.  
  111. popupContainer.style.display = 'none';
  112. popupContainer.querySelector('div[class*=closeButton-] > button').click();
  113.  
  114. incrementStat('Small Easter Sale popup');
  115. }
  116. );
  117.  
  118. // utils ----------------------------------------------------------
  119.  
  120. function findAndDeclineOffer(goProModal) {
  121. for (const span of goProModal.querySelectorAll('span')) {
  122. if (span.textContent.toLowerCase() === 'decline offer') {
  123. span.parentElement.click();
  124.  
  125. return true;
  126. }
  127. }
  128. }
  129.  
  130. function incrementStat(adType) {
  131. stats[adType] = (stats[adType] || 0) + 1;
  132. GM_setValue('adSkipStats', stats);
  133. updateMenuCommand();
  134. }
  135.  
  136. function showStats() {
  137. alert(
  138. 'Total skipped ads history:\n' +
  139. JSON.stringify(GM_getValue('adSkipStats', {}), null, 2)
  140. );
  141. }
  142.  
  143. function updateMenuCommand() {
  144. if (menuCommandId !== null) GM_unregisterMenuCommand(menuCommandId);
  145.  
  146. menuCommandId = GM_registerMenuCommand(
  147. `Show skipped ads (${Object.values(stats).reduce((a, b) => a + b, 0)})`, showStats
  148. );
  149. }
  150.  
  151. // ---------------------------------------------------------- utils
  152. })();
  153. })();