134 lines
4.0 KiB
Python
134 lines
4.0 KiB
Python
""" модуль запуска """
|
|
|
|
import httpx
|
|
import asyncio
|
|
import toml
|
|
from .base import BaseFilterProvider, BaseSourceProvider, BaseOutputProvider, IPAddreses
|
|
from .plugins import use_plugins
|
|
from typing import Optional
|
|
|
|
|
|
def is_valid_addreses(addrs: IPAddreses, config) -> bool:
|
|
result = addrs.ipv4 or addrs.ipv6
|
|
if config.get("require_ipv4"):
|
|
result = result and addrs.ipv4
|
|
if config.get("require_ipv6"):
|
|
result = result and addrs.ipv6
|
|
return result
|
|
|
|
|
|
async def get_ip_addresses(config) -> Optional[IPAddreses]:
|
|
providers = BaseSourceProvider.registred.values()
|
|
ip_addresses = None
|
|
is_done = False
|
|
pending = [asyncio.create_task(p.fetch_all(), name=p.name) for p in providers]
|
|
while not is_done and pending:
|
|
done, pending = await asyncio.wait(pending, return_when=asyncio.FIRST_COMPLETED)
|
|
for x in done:
|
|
ip_addresses = x.result()
|
|
if is_valid_addreses(ip_addresses, config):
|
|
is_done = True
|
|
break
|
|
ip_addresses = None
|
|
|
|
if pending:
|
|
gather = asyncio.gather(*pending)
|
|
gather.cancel()
|
|
try:
|
|
await gather
|
|
except asyncio.CancelledError:
|
|
pass
|
|
return ip_addresses
|
|
|
|
|
|
async def check_ip_addresses(ip_addresses):
|
|
providers = BaseFilterProvider.registred.values()
|
|
result = True
|
|
failed = ""
|
|
pending = [
|
|
asyncio.create_task(p.check(*ip_addresses), name=p.name) for p in providers
|
|
]
|
|
while result and pending:
|
|
done, pending = await asyncio.wait(pending, return_when=asyncio.FIRST_COMPLETED)
|
|
for x in done:
|
|
result = x.result()
|
|
if not result:
|
|
failed = x.get_name()
|
|
|
|
if pending:
|
|
gather = asyncio.gather(*pending)
|
|
gather.cancel()
|
|
try:
|
|
await gather
|
|
except asyncio.CancelledError:
|
|
pass
|
|
|
|
if not result:
|
|
print("failed filter:", failed)
|
|
|
|
return result
|
|
|
|
|
|
async def send_ip_addreses(ip_addresses):
|
|
providers = BaseOutputProvider.registred.values()
|
|
await asyncio.gather(
|
|
*(
|
|
asyncio.create_task(p.set_addrs(*ip_addresses), name=p.name)
|
|
for p in providers
|
|
)
|
|
)
|
|
|
|
|
|
def print_debug_info(config):
|
|
debug = config.get("debug", False)
|
|
if debug:
|
|
print("DEBUG info:")
|
|
print(
|
|
f"source classes: {[*BaseSourceProvider._childs]}, {[*map(str, BaseSourceProvider._childs.values())]}"
|
|
)
|
|
print(
|
|
f"filter classes: {[*BaseFilterProvider._childs]}, {[*map(str, BaseFilterProvider._childs.values())]}"
|
|
)
|
|
print(
|
|
f"output classes: {[*BaseOutputProvider._childs]}, {[*map(str, BaseOutputProvider._childs.values())]}"
|
|
)
|
|
print(
|
|
f"source providers: {[*BaseSourceProvider.registred]}, {[*map(str, BaseSourceProvider.registred.values())]}"
|
|
)
|
|
print(
|
|
f"filter providers: {[*BaseFilterProvider.registred]}, {[*map(str, BaseFilterProvider.registred.values())]}"
|
|
)
|
|
print(
|
|
f"output providers: {[*BaseOutputProvider.registred]}, {[*map(str, BaseOutputProvider.registred.values())]}"
|
|
)
|
|
|
|
|
|
async def app(config, ipv4t, ipv6t):
|
|
use_plugins(config, ipv4t, ipv6t)
|
|
|
|
print_debug_info(config)
|
|
|
|
ip_addreses = await get_ip_addresses(config)
|
|
if ip_addreses is None:
|
|
print("no IP addresses")
|
|
return
|
|
if not await check_ip_addresses(ip_addreses):
|
|
print("stop by filters")
|
|
return
|
|
await send_ip_addreses(ip_addreses)
|
|
print("done")
|
|
|
|
|
|
async def main():
|
|
config = toml.load("settings/config.toml")
|
|
async with httpx.AsyncHTTPTransport(
|
|
local_address="0.0.0.0", proxy=config.get("proxy_v4")
|
|
) as ipv4t, httpx.AsyncHTTPTransport(
|
|
local_address="::", proxy=config.get("proxy_v6")
|
|
) as ipv6t:
|
|
await app(config, ipv4t, ipv6t)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
asyncio.run(main())
|