Skip to content

Commit 53bb560

Browse files
committed
feat: update build script and add dns_converter.py for enhanced DNS format conversion
1 parent 9af2395 commit 53bb560

File tree

2 files changed

+137
-42
lines changed

2 files changed

+137
-42
lines changed

build.sh

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,43 @@
11
#!/bin/bash
2-
3-
# FOP - Filter Orderer and Preener (Phyton Edition)
4-
#python tools/FOP.py
5-
# FOP - Filter Orderer and Preener (Rust Edition)
6-
fop -n src/
7-
8-
# render it and save it into
9-
flrender -i abpindo=. abpindo.template subscriptions/abpindo.txt
10-
flrender -i abpindo=. abpindo_extended.template subscriptions/abpindo_extended.txt
11-
flrender -i abpindo=. abpindo_annoyances.template subscriptions/abpindo_annoyances.txt
12-
flrender -i abpindo=. abpindo_hosts.template subscriptions/abpindo_hosts.txt
13-
flrender -i abpindo=. abpindo_hosts_adult.template subscriptions/abpindo_hosts_adult.txt
14-
flrender -i abpindo=. abpindo_noadult.template subscriptions/abpindo_noadult.txt
15-
flrender -i abpindo=. abpindo_noelemhide.template subscriptions/abpindo_noelemhide.txt
16-
17-
adblock2hosts --ip 0.0.0.0 -o subscriptions/hosts.txt subscriptions/abpindo_hosts.txt
18-
adblock2hosts --ip 0.0.0.0 -o subscriptions/hosts_adult.txt subscriptions/abpindo_hosts_adult.txt
19-
20-
adblock2plain -o subscriptions/domain.txt subscriptions/abpindo_hosts.txt
21-
adblock2plain -o subscriptions/domain_adult.txt subscriptions/abpindo_hosts_adult.txt
22-
23-
adblock2plain -o tools/domain_plain.txt subscriptions/abpindo.txt
24-
adblock2plain --aggressive -o tools/domain_plain_aggressive.txt subscriptions/abpindo.txt
25-
26-
python tools/hosts_to_dnsmasq_address.py subscriptions/hosts.txt subscriptions/dnsmasq.txt
27-
python tools/hosts_to_dnsmasq_address.py subscriptions/hosts_adult.txt subscriptions/dnsmasq_adult.txt
28-
python tools/hosts_to_dnsmasq_server.py subscriptions/hosts.txt subscriptions/dnsmasq_server.txt
29-
python tools/hosts_to_dnsmasq_server.py subscriptions/hosts_adult.txt subscriptions/dnsmasq_adult_server.txt
30-
31-
python tools/hosts_to_rpz.py subscriptions/hosts.txt subscriptions/rpz.txt
32-
python tools/hosts_to_rpz.py subscriptions/hosts_adult.txt subscriptions/rpz_adult.txt
33-
34-
python tools/hosts_to_aghome.py subscriptions/hosts.txt subscriptions/aghome.txt
35-
python tools/hosts_to_aghome.py subscriptions/hosts_adult.txt subscriptions/aghome_adult.txt
36-
37-
python tools/hosts_to_unbound.py subscriptions/hosts.txt subscriptions/unbound.txt
38-
python tools/hosts_to_unbound.py subscriptions/hosts_adult.txt subscriptions/unbound_adult.txt
39-
40-
#adblock2hosts -o subscriptions/domain.txt subscriptions/abpindo_hosts.txt
41-
#adblock2hosts -o subscriptions/domain_adult.txt subscriptions/abpindo_hosts_adult.txt
42-
43-
read -p "Press any key to resume ..."
2+
# build.sh — Local development build script.
3+
# For CI/CD, use .github/workflows/autobuild.yml instead.
4+
5+
set -euo pipefail
6+
7+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8+
SUBSCRIPTIONS="$REPO_ROOT/subscriptions"
9+
TOOLS="$REPO_ROOT/tools"
10+
11+
mkdir -p "$SUBSCRIPTIONS"
12+
13+
echo "==> Running FOP..."
14+
fop -n "$REPO_ROOT/src/"
15+
16+
echo "==> Building ABP subscriptions..."
17+
flrender -i abpindo="$REPO_ROOT" "$REPO_ROOT/abpindo.template" "$SUBSCRIPTIONS/abpindo.txt"
18+
flrender -i abpindo="$REPO_ROOT" "$REPO_ROOT/abpindo_noadult.template" "$SUBSCRIPTIONS/abpindo_noadult.txt"
19+
flrender -i abpindo="$REPO_ROOT" "$REPO_ROOT/abpindo_noelemhide.template" "$SUBSCRIPTIONS/abpindo_noelemhide.txt"
20+
flrender -i abpindo="$REPO_ROOT" "$REPO_ROOT/abpindo_annoyances.template" "$SUBSCRIPTIONS/abpindo_annoyances.txt"
21+
flrender -i abpindo="$REPO_ROOT" "$REPO_ROOT/abpindo_extended.template" "$SUBSCRIPTIONS/abpindo_extended.txt"
22+
flrender -i abpindo="$REPO_ROOT" "$REPO_ROOT/abpindo_hosts.template" "$SUBSCRIPTIONS/abpindo_hosts.txt"
23+
flrender -i abpindo="$REPO_ROOT" "$REPO_ROOT/abpindo_hosts_adult.template" "$SUBSCRIPTIONS/abpindo_hosts_adult.txt"
24+
25+
echo "==> Building DNS filters..."
26+
adblock2hosts --ip 0.0.0.0 -o "$SUBSCRIPTIONS/hosts.txt" "$SUBSCRIPTIONS/abpindo_hosts.txt"
27+
adblock2hosts --ip 0.0.0.0 -o "$SUBSCRIPTIONS/hosts_adult.txt" "$SUBSCRIPTIONS/abpindo_hosts_adult.txt"
28+
29+
adblock2plain -o "$SUBSCRIPTIONS/domain.txt" "$SUBSCRIPTIONS/abpindo_hosts.txt"
30+
adblock2plain -o "$SUBSCRIPTIONS/domain_adult.txt" "$SUBSCRIPTIONS/abpindo_hosts_adult.txt"
31+
32+
python3 "$TOOLS/dns_converter.py" --format dnsmasq_address "$SUBSCRIPTIONS/hosts.txt" "$SUBSCRIPTIONS/dnsmasq.txt"
33+
python3 "$TOOLS/dns_converter.py" --format dnsmasq_address "$SUBSCRIPTIONS/hosts_adult.txt" "$SUBSCRIPTIONS/dnsmasq_adult.txt"
34+
python3 "$TOOLS/dns_converter.py" --format dnsmasq_server "$SUBSCRIPTIONS/hosts.txt" "$SUBSCRIPTIONS/dnsmasq_server.txt"
35+
python3 "$TOOLS/dns_converter.py" --format dnsmasq_server "$SUBSCRIPTIONS/hosts_adult.txt" "$SUBSCRIPTIONS/dnsmasq_adult_server.txt"
36+
python3 "$TOOLS/dns_converter.py" --format rpz "$SUBSCRIPTIONS/hosts.txt" "$SUBSCRIPTIONS/rpz.txt"
37+
python3 "$TOOLS/dns_converter.py" --format rpz "$SUBSCRIPTIONS/hosts_adult.txt" "$SUBSCRIPTIONS/rpz_adult.txt"
38+
python3 "$TOOLS/dns_converter.py" --format aghome "$SUBSCRIPTIONS/hosts.txt" "$SUBSCRIPTIONS/aghome.txt"
39+
python3 "$TOOLS/dns_converter.py" --format aghome "$SUBSCRIPTIONS/hosts_adult.txt" "$SUBSCRIPTIONS/aghome_adult.txt"
40+
python3 "$TOOLS/dns_converter.py" --format unbound "$SUBSCRIPTIONS/hosts.txt" "$SUBSCRIPTIONS/unbound.txt"
41+
python3 "$TOOLS/dns_converter.py" --format unbound "$SUBSCRIPTIONS/hosts_adult.txt" "$SUBSCRIPTIONS/unbound_adult.txt"
42+
43+
echo "==> Done. Output: $SUBSCRIPTIONS/"

tools/dns_converter.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/usr/bin/env python3
2+
"""
3+
dns_converter.py — Convert a hosts file to various DNS blocker formats.
4+
5+
Replaces: hosts_to_aghome.py, hosts_to_dnsmasq_address.py,
6+
hosts_to_dnsmasq_server.py, hosts_to_rpz.py, hosts_to_unbound.py
7+
8+
Source: https://gist.github.com/iam-py-test/ba35ce681e195c690ea3590f79479a3b
9+
10+
Usage:
11+
python3 dns_converter.py --format FORMAT input.txt output.txt
12+
13+
Formats:
14+
aghome ||example.com^
15+
dnsmasq_address address=/example.com/0.0.0.0
16+
dnsmasq_server server=/example.com/
17+
rpz example.com CNAME .
18+
unbound local-zone: "example.com" always_nxdomain
19+
"""
20+
21+
import sys
22+
import argparse
23+
24+
FORMATS = {
25+
"aghome": lambda d: f"||{d}^",
26+
"dnsmasq_address": lambda d: f"address=/{d}/0.0.0.0",
27+
"dnsmasq_server": lambda d: f"server=/{d}/",
28+
"rpz": lambda d: f"{d} CNAME .",
29+
"unbound": lambda d: f'local-zone: "{d}" always_nxdomain',
30+
}
31+
32+
# Lines starting with these prefixes are not valid hosts entries
33+
_SKIP_PREFIXES = ("#", "!", "[", "|")
34+
35+
36+
def extract_domain(line: str) -> str | None:
37+
"""Return the domain from a hosts-format line, or None if not applicable."""
38+
line = line.strip()
39+
if not line or line.startswith(_SKIP_PREFIXES):
40+
return None
41+
if line.startswith(("0.0.0.0", "127.0.0.1")):
42+
parts = line.split()
43+
return parts[1] if len(parts) >= 2 else None
44+
return line
45+
46+
47+
def convert(input_path: str, output_path: str, fmt: str) -> None:
48+
formatter = FORMATS[fmt]
49+
print(f"Converting {input_path} -> {output_path} (format: {fmt})")
50+
51+
with open(input_path, "r", encoding="utf-8") as infile, \
52+
open(output_path, "w", encoding="utf-8") as outfile:
53+
54+
for line in infile:
55+
stripped = line.strip()
56+
57+
if not stripped:
58+
continue
59+
60+
if stripped.startswith("#"):
61+
outfile.write(stripped + "\n")
62+
continue
63+
64+
domain = extract_domain(stripped)
65+
if domain:
66+
outfile.write(formatter(domain) + "\n")
67+
68+
69+
def main() -> None:
70+
parser = argparse.ArgumentParser(
71+
description="Convert hosts file to DNS blocker formats."
72+
)
73+
parser.add_argument(
74+
"--format",
75+
required=True,
76+
choices=FORMATS.keys(),
77+
metavar="FORMAT",
78+
help=f"Output format: {', '.join(FORMATS.keys())}",
79+
)
80+
parser.add_argument("input", help="Input hosts file")
81+
parser.add_argument("output", help="Output file")
82+
args = parser.parse_args()
83+
84+
try:
85+
convert(args.input, args.output, args.format)
86+
except FileNotFoundError as e:
87+
print(f"Error: {e}", file=sys.stderr)
88+
sys.exit(1)
89+
except OSError as e:
90+
print(f"Error: {e}", file=sys.stderr)
91+
sys.exit(1)
92+
93+
94+
if __name__ == "__main__":
95+
main()

0 commit comments

Comments
 (0)