#!/usr/bin/env -S runvenv .venv # # (c) 2025, Ryan A. Colyer # Made available under the GPLv3 license # import maxminddb import datetime import pytz import sys import os script_dir = os.path.dirname(os.path.realpath(__file__)) db = maxminddb.open_database(os.path.join(script_dir, 'GeoLite2-City.mmdb')) if len(sys.argv) < 2: sys.exit(-1) ipaddr = sys.argv[1] try: geo = db.get(ipaddr) except ValueError: # raised if maxminddb thinks this is not an ip address import socket try: # Fall back to treating it like a hostname. hostname = ipaddr ipaddr = socket.gethostbyname(hostname) geo = db.get(ipaddr) except Exception: sys.exit(-1) reslist = [] tzoffset = '' # Check for all the useful entries, failing gracefully on every missing one. try: reslist.append(geo['city']['names']['en']) except Exception: pass try: reslist.extend([e['names']['en'] for e in geo['subdivisions']]) except Exception: pass try: reslist.append(geo['country']['names']['en']) except Exception: try: reslist.append(geo['registered_country']['names']['en']) except Exception: pass try: offset = pytz.timezone(geo['location']['time_zone']).utcoffset(datetime.datetime.now()).total_seconds()/3600 tzoffset = f'UTC{"+" if offset>0 else ""}{offset:g}' #latlong = f'{geo["location"]["latitude"]}, {geo["location"]["longitude"]}' except Exception: pass resstr = ', '.join({k:0 for k in reslist}.keys()) resstr = ': '.join([s for s in [resstr, tzoffset] if s]) if resstr: print(resstr, end='')