4
0
mirror of https://github.com/darkclip/netlist.git synced 2026-11-11 21:14:09 +08:00
netlist/raydata.py
2023-07-19 21:50:46 +08:00

137 lines
4.2 KiB
Python
Executable File

#!/usr/bin/env python3
from __future__ import annotations
import typing
import sys
import os
from pathlib import Path
from ipaddress import IPv4Network, IPv6Network, AddressValueError
import ray_pb2
def load_networks(
dat_files: typing.List[str], country_code: str
) -> typing.List[IPv4Network | IPv6Network]:
networks = []
for file in dat_files:
file_path = Path(file).resolve()
if not file_path.exists() or not file_path.is_file():
continue
data = ray_pb2.GeoIPList()
with open(file_path, 'rb') as fp:
data.ParseFromString(fp.read())
for entry in data.entry:
if entry.country_code.lower() != country_code.lower():
continue
for cidr in entry.cidr:
try:
networks.append(IPv4Network((cidr.ip, cidr.prefix)))
except AddressValueError:
pass
try:
networks.append(IPv6Network((cidr.ip, cidr.prefix)))
except AddressValueError:
pass
return networks
def load_domains(
dat_files: typing.List[str], country_code: str, domain_type: int | None = None
) -> typing.List[str]:
domains = []
for file in dat_files:
file_path = Path(file).resolve()
if not file_path.exists() or not file_path.is_file():
continue
data = ray_pb2.GeoSiteList()
with open(file_path, 'rb') as fp:
data.ParseFromString(fp.read())
for entry in data.entry:
if entry.country_code.lower() != country_code.lower():
continue
for domain in entry.domain:
if domain_type is None:
domains.append(domain.value)
elif domain.type == domain_type:
domains.append(domain.value)
return domains
def main(args):
input = getattr(args, 'input', None)
output = getattr(args, 'output', None)
data_list = []
if getattr(args, 'data_type', None) == 'geoip':
data_list = load_networks(input, getattr(args, 'country', None))
if getattr(args, 'data_type', None) == 'geosite':
data_list = load_domains(
input, getattr(args, 'country', None), getattr(args, 'domain_type', None)
)
if len(data_list) == 0:
print('No legal data.')
sys.exit(1)
output_lines = [
f"{getattr(args,'prefix','')}{str(entry)}{getattr(args,'suffix','')}"
for entry in data_list
]
if output is None:
for line in output_lines:
print(line, end='')
else:
output: Path
output_file = output.resolve()
if not output_file.parent.exists():
os.makedirs(output_file.parent)
with output_file.open('w', encoding='utf-8') as wfp:
wfp.writelines(output_lines)
print(f'Output: {len(output_lines)}')
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument(
'input',
nargs='+',
type=str,
default=[],
help='input ray data files (separated by space)',
)
parser.add_argument('-c', '--country', type=str, default='', help='country code')
parser.add_argument('-o', '--output', type=Path, help='output file to write')
parser.add_argument(
'-p', '--prefix', type=str, default='', help='write line prefix'
)
parser.add_argument(
'-s', '--suffix', type=str, default='\n', help='write line suffix'
)
parser.set_defaults(func=main)
subparser = parser.add_subparsers(dest='data_type', required=True)
parser_geoip = subparser.add_parser(
'geoip',
help='use geoip as input',
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser_geosite = subparser.add_parser(
'geosite',
help='use geosite as input',
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser_geosite.add_argument(
'-t',
'--domain-type',
type=int,
help='geosite domain type',
)
args = parser.parse_args()
args.func(args)