2023-01-28 05:53:11 +00:00
import ipaddress
2023-01-19 03:29:50 +00:00
import json
import socket
2023-01-28 05:53:11 +00:00
2023-06-26 13:18:54 +00:00
from core . builtins import Bot
2023-02-05 14:33:33 +00:00
from core . utils . http import get_url
2023-06-26 13:18:54 +00:00
from core . component import module
from typing import Any , Dict
2023-06-26 15:56:00 +00:00
ip = module ( ' ip ' , desc = ' {ip.help.desc} ' ,
alias = ' whois ' , developers = [ ' Dianliang233 ' ] )
2023-06-26 13:18:54 +00:00
@ip.handle ( ' <ip> ' )
async def _ ( msg : Bot . MessageSession , ip : str ) :
try :
ipaddress . ip_address ( ip )
except BaseException :
await msg . finish ( msg . locale . t ( ' ip.message.error.unknown ' ) )
res = await check_ip ( ip )
await msg . finish ( await format_ip ( msg , res ) )
2023-01-19 03:29:50 +00:00
async def check_ip ( ip : str ) :
2023-05-25 05:04:40 +00:00
info = ipaddress . ip_address ( ip )
2023-01-19 03:29:50 +00:00
ip_property = ' '
real_ip = None
skip_geoip = False
2023-01-19 07:18:11 +00:00
if info . is_multicast :
2023-01-19 03:29:50 +00:00
ip_property = ' multicast '
2023-01-19 07:18:11 +00:00
elif info . is_global :
ip_property = ' global '
2023-01-19 03:29:50 +00:00
elif info . is_loopback :
ip_property = ' loopback '
skip_geoip = True
elif info . is_unspecified :
ip_property = ' unspecified '
skip_geoip = True
2023-01-19 07:18:11 +00:00
elif info . is_link_local :
ip_property = ' link_local '
skip_geoip = True
elif info . is_reserved :
ip_property = ' reserved '
skip_geoip = True
2023-05-25 10:35:11 +00:00
elif info . is_private :
ip_property = ' private '
skip_geoip = True
2023-01-19 03:29:50 +00:00
elif isinstance ( info , ipaddress . IPv6Address ) :
2023-01-19 07:18:11 +00:00
if info . is_site_local :
ip_property = ' site_local '
elif info . ipv4_mapped :
2023-01-19 03:29:50 +00:00
ip_property = ' ipv4_mapped '
real_ip = info . ipv4_mapped . compressed
elif info . sixtofour :
ip_property = ' sixtofour '
real_ip = info . sixtofour . compressed
elif info . teredo :
ip_property = ' teredo '
ip = str ( info . teredo )
2023-05-25 05:13:34 +00:00
else :
ip_property = ' unknown '
2023-05-25 05:04:40 +00:00
skip_geoip = True
2023-01-19 03:29:50 +00:00
res = {
' ip ' : ip ,
' version ' : info . version ,
' country_code ' : None ,
' country ' : None ,
' region_code ' : None ,
' region ' : None ,
' city ' : None ,
' postal_code ' : None ,
' contient_code ' : None ,
' latitude ' : None ,
' longitude ' : None ,
' organization ' : None ,
' asn ' : None ,
' asn_organization ' : None ,
' offset ' : None ,
2023-01-19 07:23:30 +00:00
' reverse ' : None ,
2023-01-19 03:29:50 +00:00
' ip_property ' : ip_property ,
' real_ip ' : real_ip
}
if not skip_geoip :
data = json . loads ( await get_url ( ' https://api.ip.sb/geoip/ ' + ip ) )
reverse = socket . getnameinfo ( ( ip , 0 ) , 0 )
res [ ' reverse ' ] = reverse [ 0 ]
for key in res :
if key in data :
res [ key ] = data [ key ]
return res
2023-04-30 03:30:59 +00:00
2023-01-19 03:29:50 +00:00
def parse_coordinate ( axis : str , value : float ) :
if axis == ' latitude ' :
return f ' { value } ° { " N " if value > 0 else " S " } '
elif axis == ' longitude ' :
return f ' { value } ° { " E " if value > 0 else " W " } '
2023-03-15 14:09:57 +00:00
async def format_ip ( msg , info : Dict [ str , Any ] ) :
2023-01-19 03:29:50 +00:00
ip_property = {
2023-06-26 13:18:54 +00:00
' global ' : msg . locale . t ( ' ip.message.ip_property.global ' ) ,
' private ' : msg . locale . t ( ' ip.message.ip_property.private ' ) ,
' reserved ' : msg . locale . t ( ' ip.message.ip_property.reserved ' ) ,
' multicast ' : msg . locale . t ( ' ip.message.ip_property.multicast ' ) ,
' link_local ' : msg . locale . t ( ' ip.message.ip_property.link_local ' ) ,
' loopback ' : msg . locale . t ( ' ip.message.ip_property.loopback ' ) ,
' unspecified ' : msg . locale . t ( ' ip.message.ip_property.unspecified ' ) ,
' ipv4_mapped ' : msg . locale . t ( ' ip.message.ip_property.ipv4_mapped ' ) ,
' sixtofour ' : msg . locale . t ( ' ip.message.ip_property.sixtofour ' ) ,
' teredo ' : msg . locale . t ( ' ip.message.ip_property.teredo ' ) ,
' site_local ' : msg . locale . t ( ' ip.message.ip_property.site_local ' ) ,
2023-07-11 02:32:54 +00:00
' unknown ' : msg . locale . t ( ' unknown ' )
2023-01-19 03:29:50 +00:00
}
return f ''' \
{ info [ ' ip ' ] }
2023-06-26 13:18:54 +00:00
{ msg . locale . t ( ' ip.message.type ' ) } IPv { info [ ' version ' ] } { ip_property [ info [ ' ip_property ' ] ] } { msg . locale . t ( ' ip.message.ip_property ' ) } { f """
{ msg . locale . t ( ' ip.message.real_ip ' ) } { info [ ' real_ip ' ] } """ if info[ ' real_ip ' ] is not None else ' ' } { f """
{ msg . locale . t ( ' ip.message.location ' ) } { f " { info [ ' city ' ] } , " if info [ ' city ' ] is not None else ' ' } { f " { info [ ' region ' ] } , " if info [ ' region ' ] is not None else ' ' } { info [ ' country ' ] } """ if info[ ' country ' ] is not None else ' ' } { f " ( { parse_coordinate( ' longitude ' , info[ ' longitude ' ])}, { parse_coordinate( ' latitude ' , info[ ' latitude ' ])}) " if info[ ' longitude ' ] is not None and info[ ' latitude ' ] is not None else ' ' } { f """
{ msg . locale . t ( ' ip.message.postal_code ' ) } { info [ ' postal_code ' ] } """ if info[ ' postal_code ' ] is not None else ' ' } { f """
{ msg . locale . t ( ' ip.message.organization ' ) } { info [ ' organization ' ] } """ if info[ ' organization ' ] is not None else ' ' } { f """
{ msg . locale . t ( ' ip.message.asn ' ) } { info [ ' asn ' ] } """ if info[ ' asn ' ] is not None else ' ' } { f " ( {info['asn_organization']} ) " if info[ ' asn_organization ' ] is not None else ' ' } { f """
{ msg . locale . t ( ' ip.message.utc ' ) } UTC { ( info [ ' offset ' ] / 3600 ) : + g } """ if info[ ' offset ' ] is not None else ' ' } { f """
{ msg . locale . t ( ' ip.message.reverse ' ) } { info [ ' reverse ' ] } """ if info[ ' reverse ' ] is not None and info[ ' reverse ' ] != info[ ' ip ' ] else ' ' } ' ' '