Smart AD blocker for: Yandex, Mail.ru

Smart AD blocker with dynamic blocking protection, for: Yandex, Mail.ru

目前为 2024-06-30 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Smart AD blocker for: Yandex, Mail.ru
  3. // @name:ru Умный блокировщик рекламы для: Yandex, Mail.ru
  4. // @namespace http://tampermonkey.net/
  5. // @version 2024-07-01_04-16
  6. // @description Smart AD blocker with dynamic blocking protection, for: Yandex, Mail.ru
  7. // @description:ru Умный блокировщик рекламы при динамической защите от блокировки, для: Yandex, Mail.ru
  8. // @author Igor Lebedev
  9. // @license GPL-3.0-or-later
  10. // @match http://*.mail.ru/*
  11. // @match https://*.mail.ru/*
  12. // @match https://*.ya.ru/*
  13. // @match https://*.yandex.ru/*
  14. // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
  15. // @grant none
  16. // @run-at document-end
  17. // ==/UserScript==
  18.  
  19. (function() {
  20. 'use strict';
  21.  
  22. // получаем текущий адрес страницы
  23. const currentURL = window.location.href
  24. const config = {
  25. SettingsOnOff: true,
  26. isRunningAsExtension: false,
  27. nodes: {
  28. mail_ru_email_GeneralBlock: 'div.application-mail__layout.application-mail__layout_main',
  29. mail_ru_suggestions: 'div.themes-widget.themes-widget_full',
  30. mail_ru_banner_top_parent: 'div[slot="main-column"]',
  31. mail_ru_banner_top_parent_bannerClassList: ['span', 'article', 'p', 'section'], // все возможные типы нод, используемые в качестве контекнера рекламного баннера
  32. ya_ru_banner_under_search: 'div.banner.i-mini-bem', // все возможные типы нод, используемые в качестве контекнера рекламного баннера
  33. ya_ru_search_suggestions: 'div.Modal.Modal_visible.Modal_hasAnimation.Distribution-SplashScreenModal.Distribution-SplashScreenModal_outerCross.SplashscreenDefault', // все возможные типы нод, используемые в качестве контекнера рекламного баннера
  34.  
  35.  
  36. }
  37. };
  38. let intervalId
  39.  
  40. // Функция для проверки наличия целевой ноды
  41. function checkForTargetNode() {
  42. const observer_config = { childList: true, subtree: true };
  43.  
  44. if (currentURL.startsWith('https://e.mail.ru/')) {
  45.  
  46.  
  47.  
  48. function checkFor_GeneralBlock() {
  49. const targetNode = document.querySelector(config.nodes.mail_ru_email_GeneralBlock);
  50.  
  51. if (targetNode) {
  52. clearInterval(interval_GeneralBlock)
  53. checkAndRemoveRightBlock(targetNode)
  54. checkAndRemoveTopBlock(targetNode)
  55. checkAndRemoveMailruSuggestions(null)
  56.  
  57. // Настраиваем наблюдение за изменениями в документе
  58. const observer = new MutationObserver((mutationsList, observer) => {
  59. for (let mutation of mutationsList) {
  60. if (mutation.type === 'childList') {
  61. // checkAndRemoveRightBlock(mutation);
  62. // checkAndRemoveTopBlock(mutation);
  63.  
  64. mutation.removedNodes.forEach(node => {
  65. if (node.nodeType === Node.ELEMENT_NODE && node.matches('div.portal-menu-element.portal-menu-element_select.portal-menu-element_expanded.portal-menu-element_not-touch.portal-menu-element_pony-mode')) {
  66. checkAndRemoveRightBlock(mutation);
  67. checkAndRemoveTopBlock(mutation);
  68. }
  69. });
  70. mutation.addedNodes.forEach(node => {
  71. if (node.nodeType === Node.ELEMENT_NODE && node.nodeName === 'A') {
  72. checkAndRemoveMailruSuggestions(mutation)
  73.  
  74. }
  75. });
  76.  
  77. }
  78. }
  79. });
  80. observer.observe(targetNode, observer_config);
  81.  
  82. }
  83. }
  84. // Функция для проверки наличия и удаления блока рекламного банера Майлру в нижнем левом углу
  85. function checkAndRemoveMailruSuggestions(mutation) {
  86. const targetNode = document.querySelector(config.nodes.mail_ru_suggestions);
  87. if (targetNode) {
  88. // clearInterval(interval_MailruSuggestions); // Останавливаем интервал, так как элемент уже найден
  89. targetNode.remove()
  90. }
  91. }
  92. const interval_GeneralBlock = setInterval(checkFor_GeneralBlock, 200);
  93.  
  94. }
  95.  
  96. else if (currentURL.startsWith('https://mail.ru/')) {
  97. mail_ru_checkAndRemoveTopBlock()
  98.  
  99. const observer = new MutationObserver((mutationsList, observer) => {
  100. for (let mutation of mutationsList) {
  101. if (mutation.type === 'childList') {
  102. // console.log('Новые узлы добавлены:', mutation.addedNodes);
  103. // для всех возможных типов нод-контейнеров баннера
  104. config.nodes.mail_ru_banner_top_parent_bannerClassList.forEach(item => {
  105. // mail_ru_checkAndRemoveTopBlock()
  106. mutation.addedNodes.forEach(node => {
  107. if (node.nodeName === item.toUpperCase()) {
  108. mail_ru_checkAndRemoveTopBlock_classList(node,mutation)
  109. }
  110. });
  111. });
  112.  
  113. }
  114. }
  115. });
  116. observer.observe(document.querySelector(config.nodes.mail_ru_banner_top_parent), observer_config);
  117.  
  118. }
  119. else if (currentURL.startsWith('https://ya.ru/search/')) {
  120. const targetNode = document.querySelector(config.nodes.ya_ru_search_suggestions)
  121. targetNode?.remove()
  122. }
  123. else if (currentURL.startsWith('https://ya.ru/')) {
  124. const targetNode = document.querySelector(config.nodes.ya_ru_banner_under_search)
  125. targetNode?.remove()
  126. const dist_stripe = document.querySelector("div.dist-stripe")
  127. dist_stripe?.parentNode.remove()
  128.  
  129. }
  130. // каталог игр
  131. else if (currentURL.startsWith('https://yandex.ru/games/') && !currentURL.startsWith('https://yandex.ru/games/app/')) {
  132. // реклама в каталоге игр
  133. function AD_remove_node(node, mutation_test) {
  134. const nodeDiv = node.querySelector('div')
  135. // Проверяем, является ли элемент div и не содержит ли он указанные классы
  136. if (nodeDiv &&
  137. !nodeDiv.classList.contains('feed_block_suggested') &&
  138. !nodeDiv.classList.contains('feed_block_categorized')) {
  139. clearInterval(interval_AD_remove)
  140. node.remove()
  141. }
  142. }
  143. function AD_remove() {
  144. const targetNodes = document.querySelectorAll('div.page__page.main-page > div#feeds > div.adaptive-width')
  145. targetNodes?.forEach(node => {
  146. AD_remove_node(node)
  147. });
  148. }
  149. const interval_AD_remove = setInterval(AD_remove, 500);
  150.  
  151. const observer = new MutationObserver((mutationsList, observer) => {
  152. for (let mutation of mutationsList) {
  153. if (mutation.type === 'childList') {
  154. // console.log('Новые узлы добавлены:', mutation.addedNodes);
  155. mutation.addedNodes.forEach(node => {
  156. if (node.nodeName === 'DIV' &&
  157. node.className === 'adaptive-width') {
  158. AD_remove_node(node, mutation)
  159. }
  160. });
  161.  
  162. }
  163. }
  164. });
  165. observer.observe(document.querySelector('div.page__right'), observer_config);
  166. }
  167. // на странице игры
  168. else if (currentURL.startsWith('https://yandex.ru/games/app/')) {
  169. // центральный баннер
  170. function AD_center_remove() {
  171. const targetNodes = document.querySelectorAll('div.play-modal_with-blur')
  172. if (targetNodes.length > 0) {
  173. clearInterval(interval_AD_center_remove)
  174. targetNodes.forEach(node => {
  175. // Проверяем, является ли элемент div и не содержит ли он указанные классы
  176.  
  177. // node.parentNode.remove()
  178. node.parentNode.style.display = 'none'
  179. // node.querySelector('span.Icon')?.click()
  180.  
  181. });
  182. }
  183. // const targetNode = document.querySelector('div.prowo-container_with-blur > div.prowo__wrapper > div.prowo > span.Icon.Icon_size_m.close-button') || document.querySelector('div.play-modal__inner > div > span.Icon.Icon_size_m.close-button')
  184. // if (targetNode) {
  185. // // clearInterval(interval_AD_center_remove)
  186. // targetNode.click()
  187. // }
  188. }
  189. const interval_AD_center_remove = setInterval(AD_center_remove, 500);
  190. // правый блок рекламы
  191. function RiggtBlock_remove() {
  192. const targetNode_RiggtBlock = document.querySelector('div.stack > div')
  193. if (targetNode_RiggtBlock) {
  194. clearInterval(interval_RiggtBlock_remove)
  195. targetNode_RiggtBlock.remove()
  196. }
  197. }
  198. const interval_RiggtBlock_remove = setInterval(RiggtBlock_remove, 500);
  199. // кнопка "Отключить рекламу"
  200. const targetStackDivs = document.querySelectorAll('div.stack > div')
  201. targetStackDivs?.forEach(node => {
  202. // Проверяем, заканчивается ли класс на __desktop-disable-ad-button-wrapper
  203. node.classList.forEach(className => {
  204. if (className.endsWith('__desktop-disable-ad-button-wrapper')) {
  205. node.parentNode.remove();
  206. }
  207. });
  208. });
  209.  
  210.  
  211. }
  212. // почтовый ящик
  213. else if (currentURL.startsWith('https://mail.yandex.ru/')) {
  214. // реклама внизу слева
  215.  
  216. function AD_remove_node(node, mutation_test) {
  217. // Проверяем, не содержит ли node он указанные классы
  218. if (!node.classList.contains('ns-view-react-left-column') &&
  219. !node.classList.contains('ns-view-fill-height-placeholder-box') &&
  220. !node.classList.contains('ns-view-skin-saver-box') &&
  221. !node.classList.contains('ns-view-copyright-box')) {
  222. node.remove()
  223. }
  224. }
  225. function AD_remove() {
  226. const targetNode = document.querySelector('div.ns-view-left-box.mail-Layout-Aside-Inner-Box.js-layout-aside-inner-box[data-key="box=left-box"]')
  227. if (targetNode) {
  228. clearInterval(interval_AD_remove)
  229. const observer = new MutationObserver((mutationsList, observer) => {
  230. for (let mutation of mutationsList) {
  231. if (mutation.type === 'childList') {
  232. // console.log('Новые узлы добавлены:', mutation.addedNodes);
  233. mutation.addedNodes.forEach(node => {
  234. if (node.nodeName === 'DIV' &&
  235. node.parentNode === targetNode) {
  236. AD_remove_node(node, mutation)
  237. }
  238. });
  239.  
  240. }
  241. }
  242. });
  243. observer.observe(targetNode, observer_config);
  244.  
  245. const targetNodes = targetNode.querySelectorAll('div')
  246. targetNodes?.forEach(node => {
  247. AD_remove_node(node)
  248. });
  249. }
  250.  
  251. }
  252. const interval_AD_remove = setInterval(AD_remove, 500);
  253. }
  254. }
  255.  
  256.  
  257. // https://e.mail.ru/inbox/
  258. // Функция для проверки наличия и удаления правого блока
  259. function checkAndRemoveRightBlock(mutation_test) {
  260. // блок опрделяется непосредственно перед анализом так как иначе теряется
  261. const targetNode = document.querySelector(config.nodes.mail_ru_email_GeneralBlock);
  262. const span = targetNode.querySelector('span');
  263. if (span) {
  264. const RightBlock = span.querySelector('div.layout__column.layout__column_right.layout__column_right-indented');
  265. if (RightBlock) {
  266. RightBlock.remove();
  267. }
  268. else {
  269. // const divs = span.querySelectorAll('div');
  270. // Получаем непосредственные дочерние элементы
  271. const divs = span.children;
  272.  
  273. // Перебираем дочерние элементы
  274. if (divs.length === 3) {
  275. for (let div of divs) {
  276. const classList = Array.from(div.classList);
  277. if (classList.length === 3 &&
  278. classList.some(className => className.length === 7) &&
  279. classList.some(className => className.length === 15) &&
  280. classList.some(className => className.length === 15)) {
  281. // console.log('Найден и удален div:', div);
  282. div.remove();
  283. break;
  284. }
  285. }
  286. }
  287. }
  288. }
  289. }
  290. // https://e.mail.ru/inbox/
  291. // Функция для проверки наличия и удаления верхнего блока
  292. function checkAndRemoveTopBlock(mutation_test) {
  293. // блок опрделяется непосредственно перед анализом так как иначе теряется
  294. const targetNode = document.querySelector(config.nodes.mail_ru_email_GeneralBlock);
  295. const span = targetNode.querySelector('span');
  296. if (span) {
  297. // const divs = span.querySelectorAll('div');
  298. // Получаем непосредственные дочерние элементы
  299. const divs = span.children;
  300.  
  301. // Перебираем дочерние элементы
  302. for (let div of divs) {
  303. const classList = Array.from(div.classList);
  304. if (classList.length === 1 &&
  305. classList.some(className => className.length === 7) ) {
  306.  
  307. const DivBlock = div.querySelector('div > div > div > div > div > div > div')
  308. const DivBlockclassList = Array.from(DivBlock.classList);
  309. if (DivBlockclassList.length === 3 &&
  310. DivBlockclassList.some(className => className.length === 7) &&
  311. DivBlockclassList.some(className => className.length === 15) &&
  312. DivBlockclassList.some(className => className.length === 15)) {
  313. // console.log('Найден и удален div:', div);
  314. DivBlock.remove();
  315. break;
  316. }
  317. }
  318. }
  319. }
  320. }
  321.  
  322. // https://mail.ru/
  323. // Функция для проверки наличия и удаления верхнего рекламного блока
  324. function mail_ru_checkAndRemoveTopBlock() {
  325. const targetNode = document.querySelector(config.nodes.mail_ru_banner_top_parent);
  326. if (targetNode) {
  327. // тип ноды меняется через каждые несколько секунд
  328. let targetNode_banner
  329.  
  330. targetNode_banner = targetNode.querySelector('div.tgb-wrapper')
  331.  
  332. if (targetNode_banner) {
  333. targetNode_banner.remove()
  334. }
  335. // });
  336.  
  337. }
  338. }
  339.  
  340. function mail_ru_checkAndRemoveTopBlock_classList(Node,mutation_test) {
  341. const classList = Array.from(Node.classList);
  342. if (classList.length === 3 &&
  343. classList.some(className => className.length === 7) &&
  344. classList.some(className => className.length === 7) &&
  345. classList.some(className => className.length === 15)) {
  346. Node.remove();
  347. // Node.style.display = 'none';
  348.  
  349. }
  350. }
  351.  
  352. checkForTargetNode()
  353.  
  354.  
  355. })();

QingJ © 2025

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