From e63e939d7714cade8de978f07cb91d1c46c7dcbf Mon Sep 17 00:00:00 2001 From: Romain J Date: Wed, 21 Apr 2021 17:59:43 +0200 Subject: [PATCH] feat(commands:cloudflare|Network): add workaround to iplocalise for cloudflare --- .idea/dictionaries/romain.xml | 1 + tuxbot/cogs/Network/functions/utils.py | 42 +++++++++++++++++--------- tuxbot/cogs/Network/network.py | 41 +++++++++++++++++++------ 3 files changed, 60 insertions(+), 24 deletions(-) diff --git a/.idea/dictionaries/romain.xml b/.idea/dictionaries/romain.xml index 573134c..9778327 100644 --- a/.idea/dictionaries/romain.xml +++ b/.idea/dictionaries/romain.xml @@ -9,6 +9,7 @@ apres asctime commandstats + crimeflare ctype debian dnskey diff --git a/tuxbot/cogs/Network/functions/utils.py b/tuxbot/cogs/Network/functions/utils.py index a3c75b4..4e9de08 100644 --- a/tuxbot/cogs/Network/functions/utils.py +++ b/tuxbot/cogs/Network/functions/utils.py @@ -1,10 +1,13 @@ import socket -from typing import Union, NoReturn +from typing import Union, NoReturn, Optional -import discord +import asyncio +import re import ipinfo import ipwhois import pydig +import aiohttp + from ipinfo.exceptions import RequestQuotaExceededError from ipwhois import Net @@ -22,7 +25,7 @@ def _(x): return x -async def get_ip(ip: str, inet: str = "", tmp: discord.Message = None) -> str: +async def get_ip(ip: str, inet: str = "") -> str: _inet: Union[socket.AddressFamily, int] = 0 # pylint: disable=no-member if inet == "6": @@ -33,9 +36,6 @@ async def get_ip(ip: str, inet: str = "", tmp: discord.Message = None) -> str: try: return socket.getaddrinfo(str(ip), None, _inet)[1][4][0] except socket.gaierror as e: - if tmp: - await tmp.delete() - raise VersionNotFound( _( "Unable to collect information on this in the given " @@ -51,9 +51,7 @@ async def get_hostname(ip: str) -> str: return "N/A" -async def get_ipwhois_result( - ip_address: str, tmp: discord.Message = None -) -> Union[NoReturn, dict]: +async def get_ipwhois_result(ip_address: str) -> Union[NoReturn, dict]: try: net = Net(ip_address) obj = IPASN(net) @@ -61,9 +59,6 @@ async def get_ipwhois_result( except ipwhois.exceptions.ASNRegistryError: return {} except ipwhois.exceptions.IPDefinedError as e: - if tmp: - await tmp.delete() - raise RFC18( _( "IP address {ip_address} is already defined as Private-Use" @@ -72,9 +67,7 @@ async def get_ipwhois_result( ) from e -async def get_ipinfo_result( - apikey: str, ip_address: str -) -> Union[NoReturn, dict]: +async def get_ipinfo_result(apikey: str, ip_address: str) -> dict: try: handler = ipinfo.getHandlerAsync( apikey, request_options={"timeout": 7} @@ -84,6 +77,25 @@ async def get_ipinfo_result( return {} +async def get_crimeflare_result( + session: aiohttp.ClientSession, ip_address: str +) -> Optional[str]: + try: + async with session.post( + "http://www.crimeflare.org:82/cgi-bin/cfsearch.cgi", + data=f"cfS={ip_address}", + timeout=aiohttp.ClientTimeout(total=15), + ) as s: + ip = re.search(r"(\d*\.\d*\.\d*\.\d*)", await s.text()) + + if ip: + return ip.group() + except (aiohttp.ClientError, asyncio.exceptions.TimeoutError): + pass + + return None + + def merge_ipinfo_ipwhois(ipinfo_result: dict, ipwhois_result: dict) -> dict: output = {"belongs": "N/A", "rir": "N/A", "region": "N/A", "flag": "N/A"} diff --git a/tuxbot/cogs/Network/network.py b/tuxbot/cogs/Network/network.py index 145b7cf..1b40805 100644 --- a/tuxbot/cogs/Network/network.py +++ b/tuxbot/cogs/Network/network.py @@ -6,6 +6,7 @@ from typing import Union, Optional import aiohttp import discord from aiohttp import ClientConnectorError +from jishaku.models import copy_context_with from discord.ext import commands from ipinfo.exceptions import RequestQuotaExceededError from structured_config import ConfigFile @@ -42,6 +43,7 @@ from .functions.utils import ( get_pydig_result, check_query_type_or_raise, check_ip_version_or_raise, + get_crimeflare_result, ) log = logging.getLogger("tuxbot.cogs.Network") @@ -56,7 +58,7 @@ class Network(commands.Cog): NetworkConfig, ).config - async def cog_command_error(self, ctx, error): + async def cog_command_error(self, ctx: ContextPlus, error): if isinstance( error, ( @@ -70,6 +72,9 @@ class Network(commands.Cog): ): await ctx.send(_(str(error), ctx, self.bot.config)) + async def cog_before_invoke(self, ctx: ContextPlus): + await ctx.trigger_typing() + # ========================================================================= # ========================================================================= @@ -82,18 +87,13 @@ class Network(commands.Cog): ): check_ip_version_or_raise(str(version)) - tmp = await ctx.send( - _("*Retrieving information...*", ctx, self.bot.config), - deletable=False, - ) - - ip_address = await get_ip(str(ip), str(version), tmp) + ip_address = await get_ip(str(ip), str(version)) ip_hostname = await get_hostname(ip_address) ipinfo_result = await get_ipinfo_result( self.__config.ipinfoKey, ip_address ) - ipwhois_result = await get_ipwhois_result(ip_address, tmp) + ipwhois_result = await get_ipwhois_result(ip_address) merged_results = merge_ipinfo_ipwhois(ipinfo_result, ipwhois_result) @@ -128,9 +128,32 @@ class Network(commands.Cog): ), ) - await tmp.delete() await ctx.send(embed=e) + @command_extra(name="cloudflare", deletable=True) + async def _cloudflare( + self, + ctx: ContextPlus, + ip: DomainConverter, + ): + crimeflare_result = await get_crimeflare_result( + self.bot.session, str(ip) + ) + + if crimeflare_result: + alt_ctx = await copy_context_with( + ctx, content=f"{ctx.prefix}iplocalise {crimeflare_result}" + ) + return await alt_ctx.command.reinvoke(alt_ctx) + + await ctx.send( + _( + "Unable to collect information through CloudFlare", + ctx, + self.bot.config, + ).format() + ) + @command_extra(name="getheaders", aliases=["headers"], deletable=True) async def _getheaders( self, ctx: ContextPlus, ip: DomainConverter, *, user_agent: str = ""