adam4adam remove ads

removes annoying ads from adam4adam*.com sites, tested in MS Edge and Firefox

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name        adam4adam remove ads
// @namespace   electronsf
// @icon
// @version     0.1.3
// @license     MIT
// @include     https://www.adam4adam.com/*
// @include     https://www.adam4adamsfw.com/*
// @grant       none
//
// @author      [email protected]
// @description removes annoying ads from adam4adam*.com sites, tested in MS Edge and Firefox
// ==/UserScript==

/* jshint esversion: 8 */

// toggle to see debug output in the javascript console
var DEBUG = false

// each line is a regex anchored to start of class name via '^'
// and to the end of class name via $
var classRegexTargetSelfStr = `
promo-bar-ads
(banner-)?vip.*
ads-.+
header-banner
mys-wrapper
adsbygoogle.*
stories-feed-container
google-anno.*
`
// special case:  easier to identify the child of an elt we need
// to remove than the elt itself
var classRegexTargetParentStr = `
sticky-block
`

const LOG_TAG = 'a4a de-ad-ifier :: '
var logRule = '===============================================\n'
var iframesRemoved = false
var classToCountInitMap = new Map()
var classToRemovalCountMap = new Map()

function constructRegex (multilineStr) {
  return new RegExp(
    '^(' +
      multilineStr.split(`\n`).join(`|`).replace(/^\|/, ``).replace(/\|$/, ``) +
      ')$'
  )
}
const classRegexTargetSelf = constructRegex(classRegexTargetSelfStr)
const classRegexTargetParent = constructRegex(classRegexTargetParentStr)

function debugAllClassNames () {
  var classNamesArr = []
  var cn
  Array.from(document.querySelectorAll('*')).forEach(e => {
    cn = e.className
    if (cn != '') {
      if (classToCountInitMap.has(cn)) {
        classToCountInitMap.set(cn, classToCountInitMap.get(cn) + 1)
      } else {
        classNamesArr.push(cn)
        classToCountInitMap.set(cn, 1)
      }
    }
  })

  var classNamesStr, count
  classNamesArr.toSorted().forEach(cn => {
    classNamesStr += cn
    count = classToCountInitMap.get(cn)
    if (classToCountInitMap.get(cn) > 1) {
      classNamesStr += ' (' + count + ')'
    }
    classNamesStr += '\n'
  })

  console.log(
    logRule +
      LOG_TAG +
      'DEBUG Class Names\n' +
      logRule +
      classNamesStr +
      logRule
  )
}

function debugPostReport () {
  var removalsArr = []
  var count = 0
  // classToRemovalCountMap.keys().forEach(cn => {
  classToRemovalCountMap.entries().forEach(entry => {
    removalsArr.push(entry[1] + '\t' + entry[0])
  })
  console.log(
    logRule + LOG_TAG + 'DEBUG Removal Report\n' + logRule +
    removalsArr.toSorted().join('\n') + '\n' + logRule
  )
}

function doRemoval (elt) {
  if (classToRemovalCountMap.has(elt.className)) {
    classToRemovalCountMap.set(
      elt.className,
      classToRemovalCountMap.get(elt.className) + 1
    )
  } else {
    classToRemovalCountMap.set(elt.className, 1)
  }
  elt.remove()
}

function removeByClassRegex (classRegex, removeParent) {
  var pendingRemoval = []
  Array.from(document.querySelectorAll('*')).forEach(e => {
    if (classRegex.test(e.className)) {
      pendingRemoval.push(e)
    }
  })

  pendingRemoval.forEach(e => {
    console.log(LOG_TAG + "REMOVING element with class='" + e.className + "'")
    try {
      if (removeParent) {
        doRemoval(e.parentNode)
      } else {
        doRemoval(e)
      }
    } catch (error) {
      console.log(LOG_TAG + 'Error encountered:  ' + error)
    }
  })

  return pendingRemoval.length
}

var totalItn = 0

const wait = ms => new Promise(resolve => setTimeout(resolve, ms))

// itn: num iterations
// ms:  milliseconds between each iteration
async function runIterations (itn, ms) {
  for (var i = 0; i < itn; i++) {
    totalItn++
    console.log(
      LOG_TAG + 'run #' + totalItn + ':  a4a removing ad-related elements'
    )

    var removedCount = 0
    removedCount += removeByClassRegex(classRegexTargetParent, true)
    removedCount += removeByClassRegex(classRegexTargetSelf, false)

    if (!iframesRemoved) {
      var numIframesRemoved = 0
      Array.from(document.getElementsByTagName('iframe')).map(e => {
        iframesRemoved = true
        e.remove()
      })
    }
    console.log(
      LOG_TAG + 'sleeping for ' + ms / 1000 + 'sec before running again'
    )
    await wait(ms)
  }
}

async function doStart () {
  !DEBUG || debugAllClassNames()

  var phase1Itn = 3
  var phase1Interval = 1000
  var phase2Itn = 3
  var phase2Interval = 3000
  var startDelay = 0

  runIterations(phase1Itn, phase1Interval)
  startDelay += phase1Itn * phase1Interval

  await wait(startDelay)
  runIterations(phase2Itn, phase2Interval)
  startDelay += phase2Itn * phase2Interval

  await wait(startDelay)
  !DEBUG || debugPostReport()

  console.log(LOG_TAG + 'finished!')

  return 0
}

doStart()