ddys_ad.js

广告隐藏

  1. // ==UserScript==
  2. // @name ddys_ad.js
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.11
  5. // @description 广告隐藏
  6. // @author wuuconix
  7. // @match *://*/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=ddys.tv
  9. // @grant none
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. /* 存储在本地的云端规则,用于提高过滤速度 */
  14. let adListCloud = localStorage.getItem("ddys_ad_cloud")
  15. if (adListCloud) {
  16. adListCloud = JSON.parse(adListCloud)
  17. filter(adListCloud)
  18. }
  19.  
  20. /* 云端的过滤规则,存储于 https://gist.github.com/wuuconix/82b6b724694d773f455eac38202fcca8 */
  21. fetch(`https://mirror.ghproxy.com/https://gist.githubusercontent.com/wuuconix/82b6b724694d773f455eac38202fcca8/raw/ad.json?ts=${Date.now()}`).then(res => res.json()).then(res => {
  22. filter(res[location.hostname])
  23. localStorage.setItem("ddys_ad_cloud", JSON.stringify(res[location.hostname] ?? []))
  24. })
  25.  
  26. /* 本地的过滤规则,存储于 localStorage 由用户通过ctrl+shift+鼠标左键 增加 */
  27. let adList = localStorage.getItem("ddys_ad")
  28. if (adList) {
  29. adList = JSON.parse(adList)
  30. filter(adList)
  31. }
  32.  
  33. function filter(adList) {
  34. if (!Array.isArray(adList) || adList.length == 0) {
  35. return
  36. }
  37.  
  38. const style = document.createElement("style")
  39. style.innerHTML = `${adList.join(",")} {
  40. width: 0px !important;
  41. height: 0px !important;
  42. opacity: 0 !important;
  43. pointer-events: none !important;
  44. }`
  45.  
  46. document.head.appendChild(style)
  47. }
  48.  
  49. /* 支持 ctrl+shift+鼠标左键 选中某元素加入本地过滤规则中 */
  50. document.addEventListener("click", (e) => {
  51. if (!e.ctrlKey || !e.shiftKey) {
  52. return
  53. }
  54.  
  55. e.preventDefault()
  56. e.stopPropagation()
  57.  
  58. const target = e.target
  59. target.style.width="0px"
  60. target.style.height="0px"
  61.  
  62. const jsPath = getDomPath(target)
  63. let adList = localStorage.getItem("ddys_ad")
  64.  
  65. if (adList) {
  66. adList = JSON.parse(adList)
  67. adList.push(jsPath)
  68. localStorage.setItem("ddys_ad", JSON.stringify(adList))
  69. } else {
  70. localStorage.setItem("ddys_ad", JSON.stringify([jsPath]))
  71. }
  72. })
  73.  
  74. /* 获取选中的某个元素的css路径 https://gist.github.com/karlgroves/7544592 */
  75. function getDomPath(el, noVerify) {
  76. // store the original element if verify is enabled. If it isn't, then don't even bother
  77. // taking up any memory for it.
  78.  
  79. const origElem = el;
  80.  
  81. if ( ! el ) {
  82. console.error('No element provided');
  83. return;
  84. }
  85.  
  86. const stack = [];
  87. let levelCount = 0;
  88. let nearestElemWithId = null;
  89.  
  90. let sibParent;
  91. let sibSiblings;
  92.  
  93. do {
  94. levelCount++;
  95.  
  96. let sibCount = 0;
  97. let sibIndex = 0;
  98. sibParent = el?.parentNode;
  99. sibSiblings = sibParent?.children;
  100.  
  101. if ( sibSiblings ){
  102. sibSiblings = Array.from(sibSiblings).filter( sibElem => el.nodeName == sibElem.nodeName );
  103. }
  104.  
  105. // Iterate over the childNodes of the elements parentNode to get the
  106. // index to use
  107. if ( sibSiblings ){
  108. for ( let i = 0; i < sibSiblings.length; i++ ) {
  109. let sib = sibSiblings[i];
  110.  
  111. //if ( sib.nodeName != el.nodeName ) continue;
  112. sibCount++;
  113.  
  114. if ( sib === el ) {
  115. // If this is the correct element, then save the sibIndex
  116. // and stop looping
  117. sibIndex = sibCount;
  118. break;
  119. }
  120. }
  121. }
  122.  
  123. if ( el && el.hasAttribute('id') && el.id != '' ) {
  124. nearestElemWithId = el.id;
  125.  
  126. // Turns out, if you have an id that starts with a numerical value, then you can't
  127. // use it in querySelector[All] unless you either escape it or add [id=] to it.
  128. if ( /^[0-9]/.test(el.id) ){
  129. stack.unshift(`[id="${el.id}"]`);
  130. }
  131. else {
  132. stack.unshift(`#${el.id}`);
  133. }
  134. }
  135. else if ( sibCount > 1 ) {
  136. stack.unshift(el.nodeName.toLowerCase() + ':nth-of-type(' + parseInt(sibIndex) + ')');
  137. }
  138. else {
  139. stack.unshift(el.nodeName.toLowerCase());
  140. }
  141.  
  142. el = sibParent;
  143. }
  144. while( sibParent?.nodeType === Node.ELEMENT_NODE && nearestElemWithId === null );
  145.  
  146.  
  147. if ( stack[0] === 'html' )
  148. stack.shift();
  149.  
  150. const result = stack.join(' > ');
  151.  
  152. if ( noVerify ) return result;
  153.  
  154. let selectionFromResult;
  155.  
  156. try {
  157. selectionFromResult = document.querySelector(result);
  158. }
  159. catch(err){
  160. console.error(`Encountered an exception when trying to verify querySelector(${result})\n\tError:`, err);
  161. }
  162.  
  163. // If there's no matches when using querySelector() with the result string, then
  164. // return false;
  165. if ( ! selectionFromResult ){
  166. console.error(`Failed to find any document using querySelector(${result})`);
  167. return false;
  168. }
  169.  
  170. // If there is a result, but its not the same element, then return false;
  171. else if ( ! origElem.isSameNode(selectionFromResult) ){
  172. console.error(`Element returned from querySelector(${result}) is not the same as the element provided`);
  173. }
  174.  
  175. // If we got here, then the matched element is the same element, then it's been verified.
  176. return result;
  177. }

QingJ © 2025

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