224 lines
5.7 KiB
Bash
224 lines
5.7 KiB
Bash
#!/bin/sh
|
|
set -eu
|
|
|
|
OUT="/root/AllowDomainsList.mtrickle"
|
|
WORK="/tmp/mihomo_groups.$$"
|
|
mkdir -p "$WORK"
|
|
trap 'rm -rf "$WORK"' EXIT
|
|
|
|
REPO_TGZ="$WORK/repo.tgz"
|
|
REPO_DIR="$WORK/repo"
|
|
|
|
RED="$(printf '\033[31m')"
|
|
GRN="$(printf '\033[32m')"
|
|
YEL="$(printf '\033[33m')"
|
|
CYN="$(printf '\033[36m')"
|
|
MAG="$(printf '\033[35m')"
|
|
RST="$(printf '\033[0m')"
|
|
|
|
say() { color="$1"; shift; echo -e "${color}$*${RST}"; }
|
|
|
|
fetch() {
|
|
u="$1"; d="$2"
|
|
if command -v uclient-fetch >/dev/null 2>&1; then
|
|
uclient-fetch -q -O "$d" "$u"
|
|
elif command -v wget >/dev/null 2>&1; then
|
|
wget -q -O "$d" "$u"
|
|
elif command -v curl >/dev/null 2>&1; then
|
|
curl -fsSL -o "$d" "$u"
|
|
else
|
|
say "$RED" "ОШИБКА: нет uclient-fetch/wget/curl"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
count_lines_human() {
|
|
f="$1"
|
|
bytes="$(wc -c < "$f" 2>/dev/null || echo 0)"
|
|
nl="$(wc -l < "$f" 2>/dev/null || echo 0)"
|
|
if [ "$bytes" -gt 0 ] && [ "$nl" -eq 0 ]; then echo 1; else echo "$nl"; fi
|
|
}
|
|
|
|
merge_lst_dir() {
|
|
src="$1"
|
|
[ -d "$src" ] || return 0
|
|
find "$src" -maxdepth 1 -type f -name '*.lst' -print | while IFS= read -r f; do
|
|
base="$(basename "$f")"
|
|
out="$WORK/$base"
|
|
awk '{ sub(/\r$/,""); print }' "$f" >> "$out"
|
|
done
|
|
}
|
|
|
|
clear
|
|
say "$MAG" "Создаём список ItDog Allow Domains для MagiTrickle"
|
|
|
|
fetch "https://api.github.com/repos/itdoginfo/allow-domains/tarball/main" "$REPO_TGZ"
|
|
|
|
mkdir -p "$REPO_DIR"
|
|
tar -xzf "$REPO_TGZ" -C "$REPO_DIR"
|
|
|
|
ROOTDIR="$(find "$REPO_DIR" -mindepth 1 -maxdepth 1 -type d | head -n 1)"
|
|
[ -n "${ROOTDIR:-}" ] || { say "$RED" "ОШИБКА: не нашёл корневую папку в архиве"; exit 1; }
|
|
|
|
say "$YEL" "Вытаскивем списки Categories / Services / Subnets/IPv4/IPv6"
|
|
merge_lst_dir "$ROOTDIR/Categories"
|
|
merge_lst_dir "$ROOTDIR/Services"
|
|
merge_lst_dir "$ROOTDIR/Subnets/IPv4"
|
|
merge_lst_dir "$ROOTDIR/Subnets/IPv6"
|
|
|
|
LIST_COUNT="$(find "$WORK" -maxdepth 1 -name '*.lst' | wc -l | tr -d ' ')"
|
|
say "$MAG" "Всего файлов в работе: $YEL$LIST_COUNT"
|
|
|
|
awk '
|
|
function trim(s){ sub(/^[ \t\r\n]+/,"",s); sub(/[ \t\r\n]+$/,"",s); return s }
|
|
function tolower_ascii(s, i,c,r,up,lo){
|
|
up="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; lo="abcdefghijklmnopqrstuvwxyz"; r=""
|
|
for(i=1;i<=length(s);i++){ c=substr(s,i,1); p=index(up,c); if(p) c=substr(lo,p,1); r=r c }
|
|
return r
|
|
}
|
|
function titlecase(s){ return (s==""?s:toupper(substr(s,1,1)) substr(s,2)) }
|
|
FNR==1{
|
|
fn=FILENAME
|
|
sub(/^.*\//,"",fn); sub(/\.lst$/,"",fn)
|
|
grp=titlecase(tolower_ascii(fn))
|
|
}
|
|
{
|
|
line=$0
|
|
sub(/\r$/,"",line)
|
|
sub(/#.*/,"",line); sub(/;.*/,"",line)
|
|
line=trim(line)
|
|
if(line=="") next
|
|
|
|
if (line ~ /^[a-zA-Z]+:\/\//) {
|
|
gsub(/^([a-zA-Z]+:\/\/)/,"",line)
|
|
sub(/\/.*$/,"",line)
|
|
}
|
|
|
|
if(line ~ /^\*\./) line=substr(line,2)
|
|
if(line ~ /^\./) line=substr(line,2)
|
|
|
|
line=trim(line)
|
|
if(line=="") next
|
|
|
|
print grp "\t" line
|
|
}
|
|
' "$WORK"/*.lst > "$WORK/tagged.tsv"
|
|
|
|
TAGGED_TOTAL="$(wc -l < "$WORK/tagged.tsv" 2>/dev/null || echo 0)"
|
|
say "$MAG" "Всего строк: $YEL$TAGGED_TOTAL"
|
|
say "$CYN" "Создаём общий список. Ждите..."
|
|
|
|
awk -F '\t' '
|
|
function is_ipv4(s){ return (s ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}$/) }
|
|
function is_ipv4_cidr(s){ return (s ~ /^([0-9]{1,3}\.){3}[0-9]{1,3}\/[0-9]{1,2}$/) }
|
|
function is_ipv6(s){ return (s ~ /^[0-9a-fA-F:]+$/) }
|
|
function is_ipv6_cidr(s){ return (s ~ /^[0-9a-fA-F:]+\/[0-9]{1,3}$/) }
|
|
function is_domainish(s){ return (s ~ /^[A-Za-z0-9][A-Za-z0-9.-]*\.[A-Za-z0-9.-]+$/) }
|
|
function dotcount(s, i,c,n){ n=0; for(i=1;i<=length(s);i++){ c=substr(s,i,1); if(c==".") n++ } return n }
|
|
|
|
function json_escape(s, i,c,o){
|
|
o=""
|
|
for(i=1;i<=length(s);i++){
|
|
c=substr(s,i,1)
|
|
if(c=="\\") o=o "\\\\"
|
|
else if(c=="\"") o=o "\\\""
|
|
else if(c=="\r" || c=="\n") o=o ""
|
|
else o=o c
|
|
}
|
|
return o
|
|
}
|
|
|
|
function rid( x){
|
|
"hexdump -n 4 -e \x27/1 \"%02x\"\x27 /dev/urandom 2>/dev/null" | getline x
|
|
close("hexdump -n 4 -e \x27/1 \"%02x\"\x27 /dev/urandom 2>/dev/null")
|
|
if(x=="") x="00000000"
|
|
return x
|
|
}
|
|
|
|
function hsv_to_hex(h, s, v, c,x,m,r,g,b,hh){
|
|
c=v*s
|
|
hh=h/60
|
|
x=c*(1-((hh%2)-1<0?-(hh%2-1):(hh%2-1)))
|
|
|
|
if(hh<1){r=c;g=x;b=0}
|
|
else if(hh<2){r=x;g=c;b=0}
|
|
else if(hh<3){r=0;g=c;b=x}
|
|
else if(hh<4){r=0;g=x;b=c}
|
|
else if(hh<5){r=x;g=0;b=c}
|
|
else {r=c;g=0;b=x}
|
|
|
|
m=v-c
|
|
r=int((r+m)*255)
|
|
g=int((g+m)*255)
|
|
b=int((b+m)*255)
|
|
|
|
return sprintf("#%02x%02x%02x",r,g,b)
|
|
}
|
|
|
|
BEGIN{
|
|
OFS=""
|
|
print "{\"groups\":["
|
|
first_group=1
|
|
}
|
|
|
|
{
|
|
g=$1; v=$2
|
|
key=g SUBSEP v
|
|
if(seen[key]++) next
|
|
groups[g]=1
|
|
vals[g, ++cnt[g]] = v
|
|
}
|
|
|
|
END{
|
|
golden=137.508
|
|
|
|
n=0
|
|
for(g in groups){ glist[++n]=g }
|
|
|
|
for(i=1;i<=n;i++) for(j=i+1;j<=n;j++) if(glist[i] > glist[j]){ t=glist[i]; glist[i]=glist[j]; glist[j]=t }
|
|
|
|
for(gi=1; gi<=n; gi++){
|
|
g=glist[gi]
|
|
|
|
if(!first_group) printf(",\n")
|
|
first_group=0
|
|
|
|
gid=rid()
|
|
|
|
hue=(gi*golden)%360
|
|
color=hsv_to_hex(hue,0.65,0.95)
|
|
|
|
print "{\"id\":\"",gid,"\",\"name\":\"",json_escape(g),"\",\"color\":\"",color,"\",\"interface\":\"Mihomo\",\"enable\":true,\"rules\":["
|
|
first_rule=1
|
|
|
|
m=cnt[g]
|
|
for(i=1;i<=m;i++) vlist[i]=vals[g,i]
|
|
for(i=1;i<=m;i++) for(j=i+1;j<=m;j++) if(vlist[i] > vlist[j]){ t=vlist[i]; vlist[i]=vlist[j]; vlist[j]=t }
|
|
|
|
for(i=1;i<=m;i++){
|
|
v=vlist[i]
|
|
if(v=="") continue
|
|
|
|
if(is_ipv6_cidr(v) || is_ipv6(v)) typ="subnet6"
|
|
else if(is_ipv4_cidr(v) || is_ipv4(v)) typ="subnet"
|
|
else if(is_domainish(v)){
|
|
if(dotcount(v)>=2) typ="domain"; else typ="namespace"
|
|
} else typ="namespace"
|
|
|
|
if(!first_rule) printf(",\n")
|
|
first_rule=0
|
|
|
|
printf("{\"enable\":true,\"id\":\"%s\",\"name\":\"\",\"rule\":\"%s\",\"type\":\"%s\"}",rid(),json_escape(v),typ)
|
|
}
|
|
|
|
print "]}"
|
|
delete vlist
|
|
}
|
|
|
|
print "]}"
|
|
}
|
|
' "$WORK/tagged.tsv" > "$OUT"
|
|
|
|
say "$GRN" "Готово!"
|
|
say "$YEL" "Файл сохранён:" "$RST""$OUT"
|