Merge pull request #41 from deoxykev/refactor_rulesets
refactor rulesets into separate files and add a ruleset compiler cli …
This commit is contained in:
27
cmd/main.go
27
cmd/main.go
@@ -8,6 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"ladder/handlers"
|
"ladder/handlers"
|
||||||
|
"ladder/handlers/cli"
|
||||||
|
|
||||||
"github.com/akamensky/argparse"
|
"github.com/akamensky/argparse"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
@@ -17,6 +18,7 @@ import (
|
|||||||
|
|
||||||
//go:embed favicon.ico
|
//go:embed favicon.ico
|
||||||
var faviconData string
|
var faviconData string
|
||||||
|
|
||||||
//go:embed styles.css
|
//go:embed styles.css
|
||||||
var cssData embed.FS
|
var cssData embed.FS
|
||||||
|
|
||||||
@@ -40,7 +42,20 @@ func main() {
|
|||||||
|
|
||||||
ruleset := parser.String("r", "ruleset", &argparse.Options{
|
ruleset := parser.String("r", "ruleset", &argparse.Options{
|
||||||
Required: false,
|
Required: false,
|
||||||
Help: "File, Directory or URL to a ruleset.yml. Overrides RULESET environment variable.",
|
Help: "File, Directory or URL to a ruleset.yaml. Overrides RULESET environment variable.",
|
||||||
|
})
|
||||||
|
|
||||||
|
mergeRulesets := parser.Flag("", "merge-rulesets", &argparse.Options{
|
||||||
|
Required: false,
|
||||||
|
Help: "Compiles a directory of yaml files into a single ruleset.yaml. Requires --ruleset arg.",
|
||||||
|
})
|
||||||
|
mergeRulesetsGzip := parser.Flag("", "merge-rulesets-gzip", &argparse.Options{
|
||||||
|
Required: false,
|
||||||
|
Help: "Compiles a directory of yaml files into a single ruleset.gz Requires --ruleset arg.",
|
||||||
|
})
|
||||||
|
mergeRulesetsOutput := parser.String("", "merge-rulesets-output", &argparse.Options{
|
||||||
|
Required: false,
|
||||||
|
Help: "Specify output file for --merge-rulesets and --merge-rulesets-gzip. Requires --ruleset and --merge-rulesets args.",
|
||||||
})
|
})
|
||||||
|
|
||||||
err := parser.Parse(os.Args)
|
err := parser.Parse(os.Args)
|
||||||
@@ -48,6 +63,16 @@ func main() {
|
|||||||
fmt.Print(parser.Usage(err))
|
fmt.Print(parser.Usage(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// utility cli flag to compile ruleset directory into single ruleset.yaml
|
||||||
|
if *mergeRulesets || *mergeRulesetsGzip {
|
||||||
|
err = cli.HandleRulesetMerge(ruleset, mergeRulesets, mergeRulesetsGzip, mergeRulesetsOutput)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
if os.Getenv("PREFORK") == "true" {
|
if os.Getenv("PREFORK") == "true" {
|
||||||
*prefork = true
|
*prefork = true
|
||||||
}
|
}
|
||||||
|
|||||||
1
go.mod
1
go.mod
@@ -26,4 +26,5 @@ require (
|
|||||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||||
golang.org/x/net v0.18.0 // indirect
|
golang.org/x/net v0.18.0 // indirect
|
||||||
golang.org/x/sys v0.14.0 // indirect
|
golang.org/x/sys v0.14.0 // indirect
|
||||||
|
golang.org/x/term v0.14.0
|
||||||
)
|
)
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -68,6 +68,8 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
|
|||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||||
|
golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8=
|
||||||
|
golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
|||||||
105
handlers/cli/cli.go
Normal file
105
handlers/cli/cli.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
|
"ladder/pkg/ruleset"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"golang.org/x/term"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HandleRulesetMerge merges a set of ruleset files, specified by the rulesetPath or RULESET env variable, into either YAML or Gzip format.
|
||||||
|
// Exits the program with an error message if the ruleset path is not provided or if loading the ruleset fails.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - rulesetPath: A pointer to a string specifying the path to the ruleset file.
|
||||||
|
// - mergeRulesets: A pointer to a boolean indicating if a merge operation should be performed.
|
||||||
|
// - mergeRulesetsGzip: A pointer to a boolean indicating if the merge should be in Gzip format.
|
||||||
|
// - mergeRulesetsOutput: A pointer to a string specifying the output file path. If empty, the output is printed to stdout.
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// - An error if the ruleset loading or merging process fails, otherwise nil.
|
||||||
|
func HandleRulesetMerge(rulesetPath *string, mergeRulesets *bool, mergeRulesetsGzip *bool, mergeRulesetsOutput *string) error {
|
||||||
|
if *rulesetPath == "" {
|
||||||
|
*rulesetPath = os.Getenv("RULESET")
|
||||||
|
}
|
||||||
|
if *rulesetPath == "" {
|
||||||
|
fmt.Println("ERROR: no ruleset provided. Try again with --ruleset <ruleset.yaml>")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
rs, err := ruleset.NewRuleset(*rulesetPath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *mergeRulesetsGzip {
|
||||||
|
return gzipMerge(rs, mergeRulesetsOutput)
|
||||||
|
}
|
||||||
|
return yamlMerge(rs, mergeRulesetsOutput)
|
||||||
|
}
|
||||||
|
|
||||||
|
// gzipMerge takes a RuleSet and an optional output file path pointer. It compresses the RuleSet into Gzip format.
|
||||||
|
// If the output file path is provided, the compressed data is written to this file. Otherwise, it prints a warning
|
||||||
|
// and outputs the binary data to stdout
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - rs: The ruleset.RuleSet to be compressed.
|
||||||
|
// - mergeRulesetsOutput: A pointer to a string specifying the output file path. If empty, the output is directed to stdout.
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// - An error if compression or file writing fails, otherwise nil.
|
||||||
|
func gzipMerge(rs ruleset.RuleSet, mergeRulesetsOutput *string) error {
|
||||||
|
gzip, err := rs.GzipYaml()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if *mergeRulesetsOutput != "" {
|
||||||
|
out, err := os.Create(*mergeRulesetsOutput)
|
||||||
|
defer out.Close()
|
||||||
|
_, err = io.Copy(out, gzip)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if term.IsTerminal(int(os.Stdout.Fd())) {
|
||||||
|
println("WARNING: binary output can mess up your terminal. Use '--merge-rulesets-output <ruleset.gz>' or pipe it to a file.")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
_, err = io.Copy(os.Stdout, gzip)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// yamlMerge takes a RuleSet and an optional output file path pointer. It converts the RuleSet into YAML format.
|
||||||
|
// If the output file path is provided, the YAML data is written to this file. If not, the YAML data is printed to stdout.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - rs: The ruleset.RuleSet to be converted to YAML.
|
||||||
|
// - mergeRulesetsOutput: A pointer to a string specifying the output file path. If empty, the output is printed to stdout.
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// - An error if YAML conversion or file writing fails, otherwise nil.
|
||||||
|
func yamlMerge(rs ruleset.RuleSet, mergeRulesetsOutput *string) error {
|
||||||
|
yaml, err := rs.Yaml()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if *mergeRulesetsOutput == "" {
|
||||||
|
fmt.Printf(yaml)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(*mergeRulesetsOutput, []byte(yaml), fs.FileMode(os.O_RDWR))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("ERROR: failed to write merged YAML ruleset to '%s'\n", *mergeRulesetsOutput)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -39,20 +39,20 @@ type Rule struct {
|
|||||||
CSP string `yaml:"content-security-policy,omitempty"`
|
CSP string `yaml:"content-security-policy,omitempty"`
|
||||||
} `yaml:"headers,omitempty"`
|
} `yaml:"headers,omitempty"`
|
||||||
GoogleCache bool `yaml:"googleCache,omitempty"`
|
GoogleCache bool `yaml:"googleCache,omitempty"`
|
||||||
RegexRules []Regex `yaml:"regexRules"`
|
RegexRules []Regex `yaml:"regexRules,omitempty"`
|
||||||
|
|
||||||
UrlMods struct {
|
UrlMods struct {
|
||||||
Domain []Regex `yaml:"domain"`
|
Domain []Regex `yaml:"domain,omitempty"`
|
||||||
Path []Regex `yaml:"path"`
|
Path []Regex `yaml:"path,omitempty"`
|
||||||
Query []KV `yaml:"query"`
|
Query []KV `yaml:"queryomitempty"`
|
||||||
} `yaml:"urlMods"`
|
} `yaml:"urlMods,omitempty"`
|
||||||
|
|
||||||
Injections []struct {
|
Injections []struct {
|
||||||
Position string `yaml:"position"`
|
Position string `yaml:"position,omitempty"`
|
||||||
Append string `yaml:"append"`
|
Append string `yaml:"append,omitempty"`
|
||||||
Prepend string `yaml:"prepend"`
|
Prepend string `yaml:"prepend,omitempty"`
|
||||||
Replace string `yaml:"replace"`
|
Replace string `yaml:"replace,omitempty"`
|
||||||
} `yaml:"injections"`
|
} `yaml:"injections,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRulesetFromEnv creates a new RuleSet based on the RULESET environment variable.
|
// NewRulesetFromEnv creates a new RuleSet based on the RULESET environment variable.
|
||||||
|
|||||||
194
ruleset.yaml
194
ruleset.yaml
@@ -1,194 +0,0 @@
|
|||||||
- domain: example.com
|
|
||||||
domains:
|
|
||||||
- www.beispiel.de
|
|
||||||
googleCache: true
|
|
||||||
headers:
|
|
||||||
x-forwarded-for: none
|
|
||||||
referer: none
|
|
||||||
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
|
|
||||||
cookie: privacy=1
|
|
||||||
regexRules:
|
|
||||||
- match: <script\s+([^>]*\s+)?src="(/)([^"]*)"
|
|
||||||
replace: <script $1 script="/https://www.example.com/$3"
|
|
||||||
injections:
|
|
||||||
- position: head # Position where to inject the code
|
|
||||||
append: |
|
|
||||||
<script>
|
|
||||||
window.localStorage.clear();
|
|
||||||
console.log("test");
|
|
||||||
alert("Hello!");
|
|
||||||
</script>
|
|
||||||
- position: h1
|
|
||||||
replace: |
|
|
||||||
<h1>An example with a ladder ;-)</h1>
|
|
||||||
- domain: www.americanbanker.com
|
|
||||||
paths:
|
|
||||||
- /news
|
|
||||||
injections:
|
|
||||||
- position: head
|
|
||||||
append: |
|
|
||||||
<script>
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
const inlineGate = document.querySelector('.inline-gate');
|
|
||||||
if (inlineGate) {
|
|
||||||
inlineGate.classList.remove('inline-gate');
|
|
||||||
const inlineGated = document.querySelectorAll('.inline-gated');
|
|
||||||
for (const elem of inlineGated) { elem.classList.remove('inline-gated'); }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
- domain: www.nzz.ch
|
|
||||||
paths:
|
|
||||||
- /international
|
|
||||||
- /sport
|
|
||||||
- /wirtschaft
|
|
||||||
- /technologie
|
|
||||||
- /feuilleton
|
|
||||||
- /zuerich
|
|
||||||
- /wissenschaft
|
|
||||||
- /gesellschaft
|
|
||||||
- /panorama
|
|
||||||
- /mobilitaet
|
|
||||||
- /reisen
|
|
||||||
- /meinung
|
|
||||||
- /finanze
|
|
||||||
injections:
|
|
||||||
- position: head
|
|
||||||
append: |
|
|
||||||
<script>
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
const paywall = document.querySelector('.dynamic-regwall');
|
|
||||||
removeDOMElement(paywall)
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
- domains:
|
|
||||||
- www.architecturaldigest.com
|
|
||||||
- www.bonappetit.com
|
|
||||||
- www.cntraveler.com
|
|
||||||
- www.epicurious.com
|
|
||||||
- www.gq.com
|
|
||||||
- www.newyorker.com
|
|
||||||
- www.vanityfair.com
|
|
||||||
- www.vogue.com
|
|
||||||
- www.wired.com
|
|
||||||
injections:
|
|
||||||
- position: head
|
|
||||||
append: |
|
|
||||||
<script>
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
const banners = document.querySelectorAll('.paywall-bar, div[class^="MessageBannerWrapper-"');
|
|
||||||
banners.forEach(el => { el.remove(); });
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
- domains:
|
|
||||||
- www.nytimes.com
|
|
||||||
- www.time.com
|
|
||||||
headers:
|
|
||||||
ueser-agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
|
|
||||||
cookie: nyt-a=; nyt-gdpr=0; nyt-geo=DE; nyt-privacy=1
|
|
||||||
referer: https://www.google.com/
|
|
||||||
injections:
|
|
||||||
- position: head
|
|
||||||
append: |
|
|
||||||
<script>
|
|
||||||
window.localStorage.clear();
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
const banners = document.querySelectorAll('div[data-testid="inline-message"], div[id^="ad-"], div[id^="leaderboard-"], div.expanded-dock, div.pz-ad-box, div[id="top-wrapper"], div[id="bottom-wrapper"]');
|
|
||||||
banners.forEach(el => { el.remove(); });
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
- domains:
|
|
||||||
- www.thestar.com
|
|
||||||
- www.niagarafallsreview.ca
|
|
||||||
- www.stcatharinesstandard.ca
|
|
||||||
- www.thepeterboroughexaminer.com
|
|
||||||
- www.therecord.com
|
|
||||||
- www.thespec.com
|
|
||||||
- www.wellandtribune.ca
|
|
||||||
injections:
|
|
||||||
- position: head
|
|
||||||
append: |
|
|
||||||
<script>
|
|
||||||
window.localStorage.clear();
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
const paywall = document.querySelectorAll('div.subscriber-offers');
|
|
||||||
paywall.forEach(el => { el.remove(); });
|
|
||||||
const subscriber_only = document.querySelectorAll('div.subscriber-only');
|
|
||||||
for (const elem of subscriber_only) {
|
|
||||||
if (elem.classList.contains('encrypted-content') && dompurify_loaded) {
|
|
||||||
const parser = new DOMParser();
|
|
||||||
const doc = parser.parseFromString('<div>' + DOMPurify.sanitize(unscramble(elem.innerText)) + '</div>', 'text/html');
|
|
||||||
const content_new = doc.querySelector('div');
|
|
||||||
elem.parentNode.replaceChild(content_new, elem);
|
|
||||||
}
|
|
||||||
elem.removeAttribute('style');
|
|
||||||
elem.removeAttribute('class');
|
|
||||||
}
|
|
||||||
const banners = document.querySelectorAll('div.subscription-required, div.redacted-overlay, div.subscriber-hide, div.tnt-ads-container');
|
|
||||||
banners.forEach(el => { el.remove(); });
|
|
||||||
const ads = document.querySelectorAll('div.tnt-ads-container, div[class*="adLabelWrapper"]');
|
|
||||||
ads.forEach(el => { el.remove(); });
|
|
||||||
const recommendations = document.querySelectorAll('div[id^="tncms-region-article"]');
|
|
||||||
recommendations.forEach(el => { el.remove(); });
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
- domain: www.usatoday.com
|
|
||||||
injections:
|
|
||||||
- position: head
|
|
||||||
append: |
|
|
||||||
<script>
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
const banners = document.querySelectorAll('div.roadblock-container, .gnt_nb, [aria-label="advertisement"], div[id="main-frame-error"]');
|
|
||||||
banners.forEach(el => { el.remove(); });
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
- domain: www.washingtonpost.com
|
|
||||||
injections:
|
|
||||||
- position: head
|
|
||||||
append: |
|
|
||||||
<script>
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
let paywall = document.querySelectorAll('div[data-qa$="-ad"], div[id="leaderboard-wrapper"], div[data-qa="subscribe-promo"]');
|
|
||||||
paywall.forEach(el => { el.remove(); });
|
|
||||||
const images = document.querySelectorAll('img');
|
|
||||||
images.forEach(image => { image.parentElement.style.filter = ''; });
|
|
||||||
const headimage = document.querySelectorAll('div .aspect-custom');
|
|
||||||
headimage.forEach(image => { image.style.filter = ''; });
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
- domain: medium.com
|
|
||||||
headers:
|
|
||||||
referer: https://t.co/x?amp=1
|
|
||||||
x-forwarded-for: none
|
|
||||||
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
|
|
||||||
content-security-policy: script-src 'self';
|
|
||||||
cookie:
|
|
||||||
- domain: tagesspiegel.de
|
|
||||||
headers:
|
|
||||||
content-security-policy: script-src 'self';
|
|
||||||
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
|
|
||||||
urlMods:
|
|
||||||
query:
|
|
||||||
- key: amp
|
|
||||||
value: 1
|
|
||||||
- domain: www.ft.com
|
|
||||||
headers:
|
|
||||||
referer: https://t.co/x?amp=1
|
|
||||||
injections:
|
|
||||||
- position: head
|
|
||||||
append: |
|
|
||||||
<script>
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
|
||||||
const styleTags = document.querySelectorAll('link[rel="stylesheet"]');
|
|
||||||
styleTags.forEach(el => {
|
|
||||||
const href = el.getAttribute('href').substring(1);
|
|
||||||
const updatedHref = href.replace(/(https?:\/\/.+?)\/{2,}/, '$1/');
|
|
||||||
el.setAttribute('href', updatedHref);
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
const cookie = document.querySelectorAll('.o-cookie-message, .js-article-ribbon, .o-ads, .o-banner, .o-message, .article__content-sign-up');
|
|
||||||
cookie.forEach(el => { el.remove(); });
|
|
||||||
}, 1000);
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
35
rulesets/ca/_multi-metroland-media-group.yaml
Normal file
35
rulesets/ca/_multi-metroland-media-group.yaml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
- domains:
|
||||||
|
- www.thestar.com
|
||||||
|
- www.niagarafallsreview.ca
|
||||||
|
- www.stcatharinesstandard.ca
|
||||||
|
- www.thepeterboroughexaminer.com
|
||||||
|
- www.therecord.com
|
||||||
|
- www.thespec.com
|
||||||
|
- www.wellandtribune.ca
|
||||||
|
injections:
|
||||||
|
- position: head
|
||||||
|
append: |
|
||||||
|
<script>
|
||||||
|
window.localStorage.clear();
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const paywall = document.querySelectorAll('div.subscriber-offers');
|
||||||
|
paywall.forEach(el => { el.remove(); });
|
||||||
|
const subscriber_only = document.querySelectorAll('div.subscriber-only');
|
||||||
|
for (const elem of subscriber_only) {
|
||||||
|
if (elem.classList.contains('encrypted-content') && dompurify_loaded) {
|
||||||
|
const parser = new DOMParser();
|
||||||
|
const doc = parser.parseFromString('<div>' + DOMPurify.sanitize(unscramble(elem.innerText)) + '</div>', 'text/html');
|
||||||
|
const content_new = doc.querySelector('div');
|
||||||
|
elem.parentNode.replaceChild(content_new, elem);
|
||||||
|
}
|
||||||
|
elem.removeAttribute('style');
|
||||||
|
elem.removeAttribute('class');
|
||||||
|
}
|
||||||
|
const banners = document.querySelectorAll('div.subscription-required, div.redacted-overlay, div.subscriber-hide, div.tnt-ads-container');
|
||||||
|
banners.forEach(el => { el.remove(); });
|
||||||
|
const ads = document.querySelectorAll('div.tnt-ads-container, div[class*="adLabelWrapper"]');
|
||||||
|
ads.forEach(el => { el.remove(); });
|
||||||
|
const recommendations = document.querySelectorAll('div[id^="tncms-region-article"]');
|
||||||
|
recommendations.forEach(el => { el.remove(); });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
24
rulesets/ch/nzz-ch.yaml
Normal file
24
rulesets/ch/nzz-ch.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
- domain: www.nzz.ch
|
||||||
|
paths:
|
||||||
|
- /international
|
||||||
|
- /sport
|
||||||
|
- /wirtschaft
|
||||||
|
- /technologie
|
||||||
|
- /feuilleton
|
||||||
|
- /zuerich
|
||||||
|
- /wissenschaft
|
||||||
|
- /gesellschaft
|
||||||
|
- /panorama
|
||||||
|
- /mobilitaet
|
||||||
|
- /reisen
|
||||||
|
- /meinung
|
||||||
|
- /finanze
|
||||||
|
injections:
|
||||||
|
- position: head
|
||||||
|
append: |
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const paywall = document.querySelector('.dynamic-regwall');
|
||||||
|
removeDOMElement(paywall)
|
||||||
|
});
|
||||||
|
</script>
|
||||||
9
rulesets/de/tagesspiegel-de.yaml
Normal file
9
rulesets/de/tagesspiegel-de.yaml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# loads amp version of page
|
||||||
|
- domain: tagesspiegel.de
|
||||||
|
headers:
|
||||||
|
content-security-policy: script-src 'self';
|
||||||
|
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
|
||||||
|
urlMods:
|
||||||
|
query:
|
||||||
|
- key: amp
|
||||||
|
value: 1
|
||||||
20
rulesets/gb/ft-com.yaml
Normal file
20
rulesets/gb/ft-com.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
- domain: www.ft.com
|
||||||
|
headers:
|
||||||
|
referer: https://t.co/x?amp=1
|
||||||
|
injections:
|
||||||
|
- position: head
|
||||||
|
append: |
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const styleTags = document.querySelectorAll('link[rel="stylesheet"]');
|
||||||
|
styleTags.forEach(el => {
|
||||||
|
const href = el.getAttribute('href').substring(1);
|
||||||
|
const updatedHref = href.replace(/(https?:\/\/.+?)\/{2,}/, '$1/');
|
||||||
|
el.setAttribute('href', updatedHref);
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
const cookie = document.querySelectorAll('.o-cookie-message, .js-article-ribbon, .o-ads, .o-banner, .o-message, .article__content-sign-up');
|
||||||
|
cookie.forEach(el => { el.remove(); });
|
||||||
|
}, 1000);
|
||||||
|
})
|
||||||
|
</script>
|
||||||
19
rulesets/us/_multi-conde-nast.yaml
Normal file
19
rulesets/us/_multi-conde-nast.yaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
- domains:
|
||||||
|
- www.architecturaldigest.com
|
||||||
|
- www.bonappetit.com
|
||||||
|
- www.cntraveler.com
|
||||||
|
- www.epicurious.com
|
||||||
|
- www.gq.com
|
||||||
|
- www.newyorker.com
|
||||||
|
- www.vanityfair.com
|
||||||
|
- www.vogue.com
|
||||||
|
- www.wired.com
|
||||||
|
injections:
|
||||||
|
- position: head
|
||||||
|
append: |
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const banners = document.querySelectorAll('.paywall-bar, div[class^="MessageBannerWrapper-"');
|
||||||
|
banners.forEach(el => { el.remove(); });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
16
rulesets/us/americanbanker-com.yaml
Normal file
16
rulesets/us/americanbanker-com.yaml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
- domain: americanbanker.com
|
||||||
|
paths:
|
||||||
|
- /news
|
||||||
|
injections:
|
||||||
|
- position: head
|
||||||
|
append: |
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const inlineGate = document.querySelector('.inline-gate');
|
||||||
|
if (inlineGate) {
|
||||||
|
inlineGate.classList.remove('inline-gate');
|
||||||
|
const inlineGated = document.querySelectorAll('.inline-gated');
|
||||||
|
for (const elem of inlineGated) { elem.classList.remove('inline-gated'); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
7
rulesets/us/medium-com.yaml
Normal file
7
rulesets/us/medium-com.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
- domain: medium.com
|
||||||
|
headers:
|
||||||
|
referer: https://t.co/x?amp=1
|
||||||
|
x-forwarded-for: none
|
||||||
|
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
|
||||||
|
content-security-policy: script-src 'self';
|
||||||
|
cookie:
|
||||||
17
rulesets/us/nytimes-com.yaml
Normal file
17
rulesets/us/nytimes-com.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
- domains:
|
||||||
|
- www.nytimes.com
|
||||||
|
- www.time.com
|
||||||
|
headers:
|
||||||
|
ueser-agent: Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)
|
||||||
|
cookie: nyt-a=; nyt-gdpr=0; nyt-geo=DE; nyt-privacy=1
|
||||||
|
referer: https://www.google.com/
|
||||||
|
injections:
|
||||||
|
- position: head
|
||||||
|
append: |
|
||||||
|
<script>
|
||||||
|
window.localStorage.clear();
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const banners = document.querySelectorAll('div[data-testid="inline-message"], div[id^="ad-"], div[id^="leaderboard-"], div.expanded-dock, div.pz-ad-box, div[id="top-wrapper"], div[id="bottom-wrapper"]');
|
||||||
|
banners.forEach(el => { el.remove(); });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
10
rulesets/us/usatoday-com.yaml
Normal file
10
rulesets/us/usatoday-com.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
- domain: www.usatoday.com
|
||||||
|
injections:
|
||||||
|
- position: head
|
||||||
|
append: |
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const banners = document.querySelectorAll('div.roadblock-container, .gnt_nb, [aria-label="advertisement"], div[id="main-frame-error"]');
|
||||||
|
banners.forEach(el => { el.remove(); });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
14
rulesets/us/washingtonpost-com.yaml
Normal file
14
rulesets/us/washingtonpost-com.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
- domain: www.washingtonpost.com
|
||||||
|
injections:
|
||||||
|
- position: head
|
||||||
|
append: |
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
let paywall = document.querySelectorAll('div[data-qa$="-ad"], div[id="leaderboard-wrapper"], div[data-qa="subscribe-promo"]');
|
||||||
|
paywall.forEach(el => { el.remove(); });
|
||||||
|
const images = document.querySelectorAll('img');
|
||||||
|
images.forEach(image => { image.parentElement.style.filter = ''; });
|
||||||
|
const headimage = document.querySelectorAll('div .aspect-custom');
|
||||||
|
headimage.forEach(image => { image.style.filter = ''; });
|
||||||
|
});
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user