VK Ads Fixes

Script for blocking ads in VK (VKontakte), bypassing blocking detection, etc.

  1. // ==UserScript==
  2. // @name VK Ads Fixes
  3. // @name:ru Правки рекламы ВКонтакте
  4. // @name:uk Правки реклами ВКонтакте
  5. // @namespace https://vtosters.app/
  6. // @version 2.2
  7. // @description Script for blocking ads in VK (VKontakte), bypassing blocking detection, etc.
  8. // @description:ru Скрипт для блокировки рекламы в VK (ВКонтакте), обхода обнаружения блокировки и т.д.
  9. // @description:uk Скрипт для блокування реклами у VK (ВКонтакті), обходу виявлення блокування тощо.
  10. // @author gdlbo, Vologhat
  11. // @match https://vk.com/*
  12. // @match https://vk.ru/*
  13. // @grant none
  14. // ==/UserScript==
  15.  
  16. (() => {
  17. "use strict"
  18.  
  19. class VkPeProperties
  20. {
  21. static #KEYS=[
  22. "send_user_info_stats", "force_send_user_info", "send_user_info_on_localhost",
  23. "send_navigation_stats_in_spa", "log_send_user_info_errors", "web_mytracker_collect_post_stats",
  24. "web_stats_device_id", "web_stats_reduce_debounce", "web_stats_send_beacon",
  25. "web_stats_send_on_events_limit", "web_stats_transport_story_view", "sentry_js_web_request_timeouts_feature",
  26. "sentry_js_web_request_timeouts_forwarding", "sentry_js_web_timeouts_forwarding", "sentry_js_web_verbose",
  27. "sentry_log_network_errors", "ads_app_form_link_redirect", "ads_autopromotion_web_geo",
  28. "ads_easy_promote_goods_new_create_api", "ads_light_methods_protection", "ads_market_autopromotion_bookmarks_stats",
  29. "ads_use_vk_community_video_portrait_4_5", "clips_web_my_tracker", "feed_post_track_code_client_web",
  30. "games_send_track_visitor_activity", "js_errors_no_write_uncaught_errors", "tgb_adblock_protection",
  31. "post_adblock_protection_promo", "eager_error_monitoring", "mini_apps_performance_close_app_empty_event",
  32. "mini_apps_performance_iframe_errors", "mini_apps_performance_web", "mini_apps_send_my_tracker_activity",
  33. "post_click_analytics_int_ext_link_click_web", "posting_track_event_count", "unique_adblock_users",
  34. "audio_my_tracker_web", "mini_apps_send_stat_arguments_bridge_events_sdk", "ajax_request_parse_html_error",
  35. "js_errors_no_write_uncaught_errors", "tns_track_sections", "tns_track_hosts", "geminus_counter",
  36. "ads_pixels_track_new_events_web_mvk", "web_navigation_handlers", "measure_module_navigation_stats",
  37. "group_join_track_event_count", "feed_content_events_open_post_event_web", "feed_posts_duration_stats_fix",
  38. "collect_unsupported_user_info_stats", "log_fetch_requests", "log_fetch_requests_get",
  39. "post_adguard_protection_promo", "extended_ajax_logging", "messenger_mediascope_stats_collect",
  40. "audio_player_stats_web"
  41. ];
  42.  
  43. static isValidProperty(key)
  44. { return key in this.#KEYS }
  45. }
  46.  
  47. //hook vk
  48. let actualVk=window.vk
  49. const vkHooks=new Set();
  50. Object.defineProperty(window,"vk", {
  51. get:() => actualVk,
  52. set:(value) => {
  53. actualVk=value
  54. if(actualVk)vkHooks.forEach( hook => hook(actualVk))
  55. return true
  56. },
  57. configurable:true
  58. })
  59.  
  60. //hook vk properties
  61. const createAndPerformVkPropHook=(key,hookfn) => {
  62. //hook when vk redefines
  63. vkHooks.add(vk => {
  64. if(vk&&vk[key])hookfn(vk[key])
  65. //hook when property redefines
  66. let actualProp=vk[key]
  67. Object.defineProperty(vk,key, {
  68. get:() => actualProp,
  69. set:(value) => {
  70. actualProp=value
  71. hookfn(actualProp)
  72. return true
  73. },
  74. configurable:true,
  75. enumerable:true
  76. })
  77. })
  78. }
  79.  
  80. //remove properties from vk.pe hook
  81. createAndPerformVkPropHook("pe",pe => {
  82. console.log("patch pe")
  83. Object.keys(pe)
  84. .filter(key => VkPeProperties.isValidProperty(key))
  85. .forEach(key => delete window.vk.pe[key])
  86. })
  87.  
  88. //patch vk.AudioAdsConfig hook
  89. createAndPerformVkPropHook("audioAdsConfig",audioAdsConfig => {
  90. console.log("patch audioAdsConfig")
  91. Object.defineProperties(audioAdsConfig, {
  92. enabled: {
  93. value:false
  94. },
  95. day_limit_reached: {
  96. value:false
  97. },
  98. sections: {
  99. value:[]
  100. }
  101. })
  102. })
  103.  
  104. //disable error monitor DSN hook
  105. createAndPerformVkPropHook("cfg",cfg => {
  106. console.log("disable error monitoring DSN")
  107. Object.defineProperty(cfg.error_monitoring_config,"dsn", {
  108. value:"http://127.0.0.1"
  109. })
  110. })
  111.  
  112. //patch vk.adParams hook
  113. createAndPerformVkPropHook("adParams",adParams => {
  114. console.log("patch adParams")
  115. Object.defineProperties(adParams, {
  116. ads_can_show: {
  117. value:0
  118. },
  119. leftads: {
  120. value:""
  121. },
  122. wsTransport: {
  123. value:"http://127.0.0.1"
  124. },
  125. ads_rotate_interval: {
  126. vallue:Number.MAX_SAFE_INTEGER
  127. }
  128. })
  129. })
  130.  
  131. //trigger vk and properties hooks
  132. window.vk=window.vk
  133.  
  134. setInterval(() => {
  135. //replace "away.php" url to the redirect url
  136. document.querySelectorAll("a[href*='away.php']")
  137. .forEach(a => {
  138. const url=URL.parse(a.href)
  139. if(!url.pathname.endsWith("away.php"))return
  140. //find a search parameter with valid redirect url
  141. url.searchParams.forEach((value) => {
  142. if(URL.canParse(value))
  143. {
  144. a.href=value
  145. return
  146. }
  147. })
  148. })
  149.  
  150. //remove _ads_block_data_w blocks
  151. document.querySelectorAll("div._ads_block_data_w")
  152. .forEach(div => {
  153. console.log(`Remove block with id ${div.id}]`)
  154. div.remove()
  155. })
  156.  
  157. //remove ads_left block
  158. const adsLeft=document.getElementById("ads_left")
  159. if(adsLeft)
  160. {
  161. console.log("Remove block with id: ads_left")
  162. adsLeft.remove()
  163. }
  164.  
  165. //clear all AdsLight functions
  166. if(window.AdsLight)
  167. Object.keys(window.AdsLight)
  168. .filter(key => typeof window.AdsLight[key]==="function")
  169. .forEach(key => Object.defineProperty(window.AdsLight,key, {
  170. value:() => {}
  171. }))
  172.  
  173. //patch window ads properties
  174. Object.defineProperties(window, {
  175. noAds: {
  176. value:true,
  177. configurable:true
  178. },
  179. noAdsAtAll: {
  180. value:true,
  181. configurable:true
  182. },
  183. no_left_ads: {
  184. value:true,
  185. configurable:true
  186. },
  187. no_ads: {
  188. value:true,
  189. configurable:true
  190. },
  191. isNoAdsForce: {
  192. value:true,
  193. configurable:true
  194. },
  195. hide_ad: {
  196. value:true,
  197. configurable:true
  198. },
  199. ya_direct: {
  200. value:false,
  201. configurable:true
  202. },
  203. yaDIrectAdActive: {
  204. value:false,
  205. configurable:true
  206. },
  207. __adsSet: {
  208. value:() => {},
  209. configurable:true
  210. },
  211. __adsUpdate: {
  212. value:() => {},
  213. configurable:true
  214. },
  215. AdmanHTML: {
  216. value:false,
  217. configurable:true
  218. },
  219. audioAdsConfig: {
  220. value:false,
  221. configurable:true
  222. },
  223. __adsGetAjaxParams: {
  224. value:() => {},
  225. configurable:true
  226. },
  227. __adsLoader: {
  228. value:() => {},
  229. configurable:true
  230. },
  231. })
  232. },30000/navigator.hardwareConcurrency)
  233. })();