We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
ip: MaxMind GeoLite2 Changes
### Description
MaxMind appears to now require an account to download the GeoLite2 databases, which Sopel currently uses. The geolite.maxmind.com domain, where Sopel downloads the databases, no longer exists, which is causing tests to fail.

### Reproduction steps
1. Clone master
2. Run `./pytest_run.py -v sopel/modules/ip.py`
3. Observe `sopel/modules/ip.py::test_example_ip_0 FAILED`

### Expected behavior
Test passes

### Notes
There seems to be an API with a [python library](https://pypi.org/project/geoip2/), but that also requires an account.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sopel/modules/ip.py`
Content:
```
1 # coding=utf-8
2 """
3 ip.py - Sopel GeoIP Lookup Module
4 Copyright 2011, Dimitri Molenaars, TyRope.nl,
5 Copyright © 2013, Elad Alfassa <elad@fedoraproject.org>
6 Licensed under the Eiffel Forum License 2.
7 
8 https://sopel.chat
9 """
10 
11 from __future__ import unicode_literals, absolute_import, print_function, division
12 
13 import logging
14 import os
15 import socket
16 import tarfile
17 
18 import geoip2.database
19 
20 from sopel.config.types import FilenameAttribute, StaticSection
21 from sopel.module import commands, example
22 
23 urlretrieve = None
24 try:
25     from urllib import urlretrieve
26 except ImportError:
27     try:
28         # urlretrieve has been put under urllib.request in Python 3.
29         # It's also deprecated so this should probably be replaced with
30         # urllib2.
31         from urllib.request import urlretrieve
32     except ImportError:
33         pass
34 
35 
36 LOGGER = logging.getLogger(__name__)
37 
38 
39 class GeoipSection(StaticSection):
40     GeoIP_db_path = FilenameAttribute('GeoIP_db_path', directory=True)
41     """Path of the directory containing the GeoIP database files."""
42 
43 
44 def configure(config):
45     """
46     | name | example | purpose |
47     | ---- | ------- | ------- |
48     | GeoIP\\_db\\_path | /home/sopel/GeoIP/ | Path to the GeoIP database files |
49     """
50     config.define_section('ip', GeoipSection)
51     config.ip.configure_setting('GeoIP_db_path',
52                                 'Path of the GeoIP db files')
53 
54 
55 def setup(bot):
56     bot.config.define_section('ip', GeoipSection)
57 
58 
59 def _decompress(source, target, delete_after_decompression=True):
60     """Decompress just the database from the archive"""
61     # https://stackoverflow.com/a/16452962
62     tar = tarfile.open(source)
63     for member in tar.getmembers():
64         if ".mmdb" in member.name:
65             member.name = os.path.basename(member.name)
66             tar.extract(member, target)
67     if delete_after_decompression:
68         os.remove(source)
69 
70 
71 def _find_geoip_db(bot):
72     """Find the GeoIP database"""
73     config = bot.config
74     if config.ip.GeoIP_db_path:
75         cities_db = os.path.join(config.ip.GeoIP_db_path, 'GeoLite2-City.mmdb')
76         ipasnum_db = os.path.join(config.ip.GeoIP_db_path, 'GeoLite2-ASN.mmdb')
77         if (os.path.isfile(cities_db) and os.path.isfile(ipasnum_db)):
78             return config.ip.GeoIP_db_path
79         else:
80             LOGGER.warning(
81                 'GeoIP path configured but DB not found in configured path')
82 
83     if (os.path.isfile(os.path.join(config.core.homedir, 'GeoLite2-City.mmdb')) and
84             os.path.isfile(os.path.join(config.core.homedir, 'GeoLite2-ASN.mmdb'))):
85         return config.core.homedir
86     elif (os.path.isfile(os.path.join('/usr/share/GeoIP', 'GeoLite2-City.mmdb')) and
87             os.path.isfile(os.path.join('/usr/share/GeoIP', 'GeoLite2-ASN.mmdb'))):
88         return '/usr/share/GeoIP'
89     elif urlretrieve:
90         LOGGER.info('Downloading GeoIP database')
91         bot.say('Downloading GeoIP database, please wait...')
92         geolite_urls = [
93             'https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz',
94             'https://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz'
95         ]
96         for url in geolite_urls:
97             LOGGER.debug('GeoIP Source URL: %s', url)
98             full_path = os.path.join(config.core.homedir, url.split("/")[-1])
99             urlretrieve(url, full_path)
100             _decompress(full_path, config.core.homedir)
101         return bot.config.core.homedir
102     else:
103         return False
104 
105 
106 @commands('iplookup', 'ip')
107 @example('.ip 8.8.8.8',
108          r'\[IP\/Host Lookup\] Hostname: \S*dns\S*\.google\S* \| Location: United States \| ISP: AS15169 Google LLC',
109          re=True,
110          ignore='Downloading GeoIP database, please wait...',
111          online=True)
112 def ip(bot, trigger):
113     """IP Lookup tool"""
114     # Check if there is input at all
115     if not trigger.group(2):
116         return bot.reply("No search term.")
117     # Check whether the input is an IP or hostmask or a nickname
118     decide = ['.', ':']
119     if any(x in trigger.group(2) for x in decide):
120         # It's an IP/hostname!
121         query = trigger.group(2).strip()
122     else:
123         # Need to get the host for the username
124         username = trigger.group(2).strip()
125         user_in_botdb = bot.users.get(username)
126         if user_in_botdb is not None:
127             query = user_in_botdb.host
128 
129             # Sanity check - sometimes user information isn't populated yet
130             if query is None:
131                 return bot.say("I don't know that user's host.")
132         else:
133             return bot.say("I\'m not aware of this user.")
134 
135     db_path = _find_geoip_db(bot)
136     if db_path is False:
137         LOGGER.error('Can\'t find (or download) usable GeoIP database.')
138         bot.say('Sorry, I don\'t have a GeoIP database to use for this lookup.')
139         return False
140 
141     if ':' in query:
142         try:
143             socket.inet_pton(socket.AF_INET6, query)
144         except (OSError, socket.error):  # Python 2/3 compatibility
145             return bot.say("[IP/Host Lookup] Unable to resolve IP/Hostname")
146     elif '.' in query:
147         try:
148             socket.inet_pton(socket.AF_INET, query)
149         except (socket.error, socket.herror):
150             try:
151                 query = socket.getaddrinfo(query, None)[0][4][0]
152             except socket.gaierror:
153                 return bot.say("[IP/Host Lookup] Unable to resolve IP/Hostname")
154     else:
155         return bot.say("[IP/Host Lookup] Unable to resolve IP/Hostname")
156 
157     city = geoip2.database.Reader(os.path.join(db_path, 'GeoLite2-City.mmdb'))
158     asn = geoip2.database.Reader(os.path.join(db_path, 'GeoLite2-ASN.mmdb'))
159     host = socket.getfqdn(query)
160     try:
161         city_response = city.city(query)
162         asn_response = asn.asn(query)
163     except geoip2.errors.AddressNotFoundError:
164         return bot.say("[IP/Host Lookup] The address is not in the database.")
165 
166     response = "[IP/Host Lookup] Hostname: %s" % host
167     try:
168         response += " | Location: %s" % city_response.country.name
169     except AttributeError:
170         response += ' | Location: Unknown'
171 
172     region = city_response.subdivisions.most_specific.name
173     response += " | Region: %s" % region if region else ""
174     city = city_response.city.name
175     response += " | City: %s" % city if city else ""
176     isp = "AS" + str(asn_response.autonomous_system_number) + \
177           " " + asn_response.autonomous_system_organization
178     response += " | ISP: %s" % isp if isp else ""
179     bot.say(response)
180 
181 
182 if __name__ == "__main__":
183     from sopel.test_tools import run_example_tests
184     run_example_tests(__file__)
185
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/sopel/modules/ip.py b/sopel/modules/ip.py
--- a/sopel/modules/ip.py
+++ b/sopel/modules/ip.py
@@ -19,6 +19,7 @@
 
 from sopel.config.types import FilenameAttribute, StaticSection
 from sopel.module import commands, example
+from sopel.tools import web
 
 urlretrieve = None
 try:
@@ -89,10 +90,19 @@
     elif urlretrieve:
         LOGGER.info('Downloading GeoIP database')
         bot.say('Downloading GeoIP database, please wait...')
-        geolite_urls = [
-            'https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz',
-            'https://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz'
-        ]
+
+        common_params = {'license_key': 'JXBEmLjOzislFnh4', 'suffix': 'tar.gz'}
+        base_url = 'https://download.maxmind.com/app/geoip_download'
+        geolite_urls = []
+
+        for edition in ['ASN', 'City']:
+            geolite_urls.append(
+                '{base}?{params}'.format(
+                    base=base_url,
+                    params=web.urlencode(dict(common_params, **{'edition_id': 'GeoLite2-%s' % edition})),
+                )
+            )
+
         for url in geolite_urls:
             LOGGER.debug('GeoIP Source URL: %s', url)
             full_path = os.path.join(config.core.homedir, url.split("/")[-1])

{"golden_diff": "diff --git a/sopel/modules/ip.py b/sopel/modules/ip.py\n--- a/sopel/modules/ip.py\n+++ b/sopel/modules/ip.py\n@@ -19,6 +19,7 @@\n \n from sopel.config.types import FilenameAttribute, StaticSection\n from sopel.module import commands, example\n+from sopel.tools import web\n \n urlretrieve = None\n try:\n@@ -89,10 +90,19 @@\n     elif urlretrieve:\n         LOGGER.info('Downloading GeoIP database')\n         bot.say('Downloading GeoIP database, please wait...')\n-        geolite_urls = [\n-            'https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz',\n-            'https://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz'\n-        ]\n+\n+        common_params = {'license_key': 'JXBEmLjOzislFnh4', 'suffix': 'tar.gz'}\n+        base_url = 'https://download.maxmind.com/app/geoip_download'\n+        geolite_urls = []\n+\n+        for edition in ['ASN', 'City']:\n+            geolite_urls.append(\n+                '{base}?{params}'.format(\n+                    base=base_url,\n+                    params=web.urlencode(dict(common_params, **{'edition_id': 'GeoLite2-%s' % edition})),\n+                )\n+            )\n+\n         for url in geolite_urls:\n             LOGGER.debug('GeoIP Source URL: %s', url)\n             full_path = os.path.join(config.core.homedir, url.split(\"/\")[-1])\n", "issue": "ip: MaxMind GeoLite2 Changes\n### Description\r\nMaxMind appears to now require an account to download the GeoLite2 databases, which Sopel currently uses. The geolite.maxmind.com domain, where Sopel downloads the databases, no longer exists, which is causing tests to fail.\r\n\r\n### Reproduction steps\r\n1. Clone master\r\n2. Run `./pytest_run.py -v sopel/modules/ip.py`\r\n3. Observe `sopel/modules/ip.py::test_example_ip_0 FAILED`\r\n\r\n### Expected behavior\r\nTest passes\r\n\r\n### Notes\r\nThere seems to be an API with a [python library](https://pypi.org/project/geoip2/), but that also requires an account.\n", "before_files": [{"content": "# coding=utf-8\n\"\"\"\nip.py - Sopel GeoIP Lookup Module\nCopyright 2011, Dimitri Molenaars, TyRope.nl,\nCopyright \u00a9 2013, Elad Alfassa <elad@fedoraproject.org>\nLicensed under the Eiffel Forum License 2.\n\nhttps://sopel.chat\n\"\"\"\n\nfrom __future__ import unicode_literals, absolute_import, print_function, division\n\nimport logging\nimport os\nimport socket\nimport tarfile\n\nimport geoip2.database\n\nfrom sopel.config.types import FilenameAttribute, StaticSection\nfrom sopel.module import commands, example\n\nurlretrieve = None\ntry:\n    from urllib import urlretrieve\nexcept ImportError:\n    try:\n        # urlretrieve has been put under urllib.request in Python 3.\n        # It's also deprecated so this should probably be replaced with\n        # urllib2.\n        from urllib.request import urlretrieve\n    except ImportError:\n        pass\n\n\nLOGGER = logging.getLogger(__name__)\n\n\nclass GeoipSection(StaticSection):\n    GeoIP_db_path = FilenameAttribute('GeoIP_db_path', directory=True)\n    \"\"\"Path of the directory containing the GeoIP database files.\"\"\"\n\n\ndef configure(config):\n    \"\"\"\n    | name | example | purpose |\n    | ---- | ------- | ------- |\n    | GeoIP\\\\_db\\\\_path | /home/sopel/GeoIP/ | Path to the GeoIP database files |\n    \"\"\"\n    config.define_section('ip', GeoipSection)\n    config.ip.configure_setting('GeoIP_db_path',\n                                'Path of the GeoIP db files')\n\n\ndef setup(bot):\n    bot.config.define_section('ip', GeoipSection)\n\n\ndef _decompress(source, target, delete_after_decompression=True):\n    \"\"\"Decompress just the database from the archive\"\"\"\n    # https://stackoverflow.com/a/16452962\n    tar = tarfile.open(source)\n    for member in tar.getmembers():\n        if \".mmdb\" in member.name:\n            member.name = os.path.basename(member.name)\n            tar.extract(member, target)\n    if delete_after_decompression:\n        os.remove(source)\n\n\ndef _find_geoip_db(bot):\n    \"\"\"Find the GeoIP database\"\"\"\n    config = bot.config\n    if config.ip.GeoIP_db_path:\n        cities_db = os.path.join(config.ip.GeoIP_db_path, 'GeoLite2-City.mmdb')\n        ipasnum_db = os.path.join(config.ip.GeoIP_db_path, 'GeoLite2-ASN.mmdb')\n        if (os.path.isfile(cities_db) and os.path.isfile(ipasnum_db)):\n            return config.ip.GeoIP_db_path\n        else:\n            LOGGER.warning(\n                'GeoIP path configured but DB not found in configured path')\n\n    if (os.path.isfile(os.path.join(config.core.homedir, 'GeoLite2-City.mmdb')) and\n            os.path.isfile(os.path.join(config.core.homedir, 'GeoLite2-ASN.mmdb'))):\n        return config.core.homedir\n    elif (os.path.isfile(os.path.join('/usr/share/GeoIP', 'GeoLite2-City.mmdb')) and\n            os.path.isfile(os.path.join('/usr/share/GeoIP', 'GeoLite2-ASN.mmdb'))):\n        return '/usr/share/GeoIP'\n    elif urlretrieve:\n        LOGGER.info('Downloading GeoIP database')\n        bot.say('Downloading GeoIP database, please wait...')\n        geolite_urls = [\n            'https://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz',\n            'https://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz'\n        ]\n        for url in geolite_urls:\n            LOGGER.debug('GeoIP Source URL: %s', url)\n            full_path = os.path.join(config.core.homedir, url.split(\"/\")[-1])\n            urlretrieve(url, full_path)\n            _decompress(full_path, config.core.homedir)\n        return bot.config.core.homedir\n    else:\n        return False\n\n\n@commands('iplookup', 'ip')\n@example('.ip 8.8.8.8',\n         r'\\[IP\\/Host Lookup\\] Hostname: \\S*dns\\S*\\.google\\S* \\| Location: United States \\| ISP: AS15169 Google LLC',\n         re=True,\n         ignore='Downloading GeoIP database, please wait...',\n         online=True)\ndef ip(bot, trigger):\n    \"\"\"IP Lookup tool\"\"\"\n    # Check if there is input at all\n    if not trigger.group(2):\n        return bot.reply(\"No search term.\")\n    # Check whether the input is an IP or hostmask or a nickname\n    decide = ['.', ':']\n    if any(x in trigger.group(2) for x in decide):\n        # It's an IP/hostname!\n        query = trigger.group(2).strip()\n    else:\n        # Need to get the host for the username\n        username = trigger.group(2).strip()\n        user_in_botdb = bot.users.get(username)\n        if user_in_botdb is not None:\n            query = user_in_botdb.host\n\n            # Sanity check - sometimes user information isn't populated yet\n            if query is None:\n                return bot.say(\"I don't know that user's host.\")\n        else:\n            return bot.say(\"I\\'m not aware of this user.\")\n\n    db_path = _find_geoip_db(bot)\n    if db_path is False:\n        LOGGER.error('Can\\'t find (or download) usable GeoIP database.')\n        bot.say('Sorry, I don\\'t have a GeoIP database to use for this lookup.')\n        return False\n\n    if ':' in query:\n        try:\n            socket.inet_pton(socket.AF_INET6, query)\n        except (OSError, socket.error):  # Python 2/3 compatibility\n            return bot.say(\"[IP/Host Lookup] Unable to resolve IP/Hostname\")\n    elif '.' in query:\n        try:\n            socket.inet_pton(socket.AF_INET, query)\n        except (socket.error, socket.herror):\n            try:\n                query = socket.getaddrinfo(query, None)[0][4][0]\n            except socket.gaierror:\n                return bot.say(\"[IP/Host Lookup] Unable to resolve IP/Hostname\")\n    else:\n        return bot.say(\"[IP/Host Lookup] Unable to resolve IP/Hostname\")\n\n    city = geoip2.database.Reader(os.path.join(db_path, 'GeoLite2-City.mmdb'))\n    asn = geoip2.database.Reader(os.path.join(db_path, 'GeoLite2-ASN.mmdb'))\n    host = socket.getfqdn(query)\n    try:\n        city_response = city.city(query)\n        asn_response = asn.asn(query)\n    except geoip2.errors.AddressNotFoundError:\n        return bot.say(\"[IP/Host Lookup] The address is not in the database.\")\n\n    response = \"[IP/Host Lookup] Hostname: %s\" % host\n    try:\n        response += \" | Location: %s\" % city_response.country.name\n    except AttributeError:\n        response += ' | Location: Unknown'\n\n    region = city_response.subdivisions.most_specific.name\n    response += \" | Region: %s\" % region if region else \"\"\n    city = city_response.city.name\n    response += \" | City: %s\" % city if city else \"\"\n    isp = \"AS\" + str(asn_response.autonomous_system_number) + \\\n          \" \" + asn_response.autonomous_system_organization\n    response += \" | ISP: %s\" % isp if isp else \"\"\n    bot.say(response)\n\n\nif __name__ == \"__main__\":\n    from sopel.test_tools import run_example_tests\n    run_example_tests(__file__)\n", "path": "sopel/modules/ip.py"}], "after_files": [{"content": "# coding=utf-8\n\"\"\"\nip.py - Sopel GeoIP Lookup Module\nCopyright 2011, Dimitri Molenaars, TyRope.nl,\nCopyright \u00a9 2013, Elad Alfassa <elad@fedoraproject.org>\nLicensed under the Eiffel Forum License 2.\n\nhttps://sopel.chat\n\"\"\"\n\nfrom __future__ import unicode_literals, absolute_import, print_function, division\n\nimport logging\nimport os\nimport socket\nimport tarfile\n\nimport geoip2.database\n\nfrom sopel.config.types import FilenameAttribute, StaticSection\nfrom sopel.module import commands, example\nfrom sopel.tools import web\n\nurlretrieve = None\ntry:\n    from urllib import urlretrieve\nexcept ImportError:\n    try:\n        # urlretrieve has been put under urllib.request in Python 3.\n        # It's also deprecated so this should probably be replaced with\n        # urllib2.\n        from urllib.request import urlretrieve\n    except ImportError:\n        pass\n\n\nLOGGER = logging.getLogger(__name__)\n\n\nclass GeoipSection(StaticSection):\n    GeoIP_db_path = FilenameAttribute('GeoIP_db_path', directory=True)\n    \"\"\"Path of the directory containing the GeoIP database files.\"\"\"\n\n\ndef configure(config):\n    \"\"\"\n    | name | example | purpose |\n    | ---- | ------- | ------- |\n    | GeoIP\\\\_db\\\\_path | /home/sopel/GeoIP/ | Path to the GeoIP database files |\n    \"\"\"\n    config.define_section('ip', GeoipSection)\n    config.ip.configure_setting('GeoIP_db_path',\n                                'Path of the GeoIP db files')\n\n\ndef setup(bot):\n    bot.config.define_section('ip', GeoipSection)\n\n\ndef _decompress(source, target, delete_after_decompression=True):\n    \"\"\"Decompress just the database from the archive\"\"\"\n    # https://stackoverflow.com/a/16452962\n    tar = tarfile.open(source)\n    for member in tar.getmembers():\n        if \".mmdb\" in member.name:\n            member.name = os.path.basename(member.name)\n            tar.extract(member, target)\n    if delete_after_decompression:\n        os.remove(source)\n\n\ndef _find_geoip_db(bot):\n    \"\"\"Find the GeoIP database\"\"\"\n    config = bot.config\n    if config.ip.GeoIP_db_path:\n        cities_db = os.path.join(config.ip.GeoIP_db_path, 'GeoLite2-City.mmdb')\n        ipasnum_db = os.path.join(config.ip.GeoIP_db_path, 'GeoLite2-ASN.mmdb')\n        if (os.path.isfile(cities_db) and os.path.isfile(ipasnum_db)):\n            return config.ip.GeoIP_db_path\n        else:\n            LOGGER.warning(\n                'GeoIP path configured but DB not found in configured path')\n\n    if (os.path.isfile(os.path.join(config.core.homedir, 'GeoLite2-City.mmdb')) and\n            os.path.isfile(os.path.join(config.core.homedir, 'GeoLite2-ASN.mmdb'))):\n        return config.core.homedir\n    elif (os.path.isfile(os.path.join('/usr/share/GeoIP', 'GeoLite2-City.mmdb')) and\n            os.path.isfile(os.path.join('/usr/share/GeoIP', 'GeoLite2-ASN.mmdb'))):\n        return '/usr/share/GeoIP'\n    elif urlretrieve:\n        LOGGER.info('Downloading GeoIP database')\n        bot.say('Downloading GeoIP database, please wait...')\n\n        common_params = {'license_key': 'JXBEmLjOzislFnh4', 'suffix': 'tar.gz'}\n        base_url = 'https://download.maxmind.com/app/geoip_download'\n        geolite_urls = []\n\n        for edition in ['ASN', 'City']:\n            geolite_urls.append(\n                '{base}?{params}'.format(\n                    base=base_url,\n                    params=web.urlencode(dict(common_params, **{'edition_id': 'GeoLite2-%s' % edition})),\n                )\n            )\n\n        for url in geolite_urls:\n            LOGGER.debug('GeoIP Source URL: %s', url)\n            full_path = os.path.join(config.core.homedir, url.split(\"/\")[-1])\n            urlretrieve(url, full_path)\n            _decompress(full_path, config.core.homedir)\n        return bot.config.core.homedir\n    else:\n        return False\n\n\n@commands('iplookup', 'ip')\n@example('.ip 8.8.8.8',\n         r'\\[IP\\/Host Lookup\\] Hostname: \\S*dns\\S*\\.google\\S* \\| Location: United States \\| ISP: AS15169 Google LLC',\n         re=True,\n         ignore='Downloading GeoIP database, please wait...',\n         online=True)\ndef ip(bot, trigger):\n    \"\"\"IP Lookup tool\"\"\"\n    # Check if there is input at all\n    if not trigger.group(2):\n        return bot.reply(\"No search term.\")\n    # Check whether the input is an IP or hostmask or a nickname\n    decide = ['.', ':']\n    if any(x in trigger.group(2) for x in decide):\n        # It's an IP/hostname!\n        query = trigger.group(2).strip()\n    else:\n        # Need to get the host for the username\n        username = trigger.group(2).strip()\n        user_in_botdb = bot.users.get(username)\n        if user_in_botdb is not None:\n            query = user_in_botdb.host\n\n            # Sanity check - sometimes user information isn't populated yet\n            if query is None:\n                return bot.say(\"I don't know that user's host.\")\n        else:\n            return bot.say(\"I\\'m not aware of this user.\")\n\n    db_path = _find_geoip_db(bot)\n    if db_path is False:\n        LOGGER.error('Can\\'t find (or download) usable GeoIP database.')\n        bot.say('Sorry, I don\\'t have a GeoIP database to use for this lookup.')\n        return False\n\n    if ':' in query:\n        try:\n            socket.inet_pton(socket.AF_INET6, query)\n        except (OSError, socket.error):  # Python 2/3 compatibility\n            return bot.say(\"[IP/Host Lookup] Unable to resolve IP/Hostname\")\n    elif '.' in query:\n        try:\n            socket.inet_pton(socket.AF_INET, query)\n        except (socket.error, socket.herror):\n            try:\n                query = socket.getaddrinfo(query, None)[0][4][0]\n            except socket.gaierror:\n                return bot.say(\"[IP/Host Lookup] Unable to resolve IP/Hostname\")\n    else:\n        return bot.say(\"[IP/Host Lookup] Unable to resolve IP/Hostname\")\n\n    city = geoip2.database.Reader(os.path.join(db_path, 'GeoLite2-City.mmdb'))\n    asn = geoip2.database.Reader(os.path.join(db_path, 'GeoLite2-ASN.mmdb'))\n    host = socket.getfqdn(query)\n    try:\n        city_response = city.city(query)\n        asn_response = asn.asn(query)\n    except geoip2.errors.AddressNotFoundError:\n        return bot.say(\"[IP/Host Lookup] The address is not in the database.\")\n\n    response = \"[IP/Host Lookup] Hostname: %s\" % host\n    try:\n        response += \" | Location: %s\" % city_response.country.name\n    except AttributeError:\n        response += ' | Location: Unknown'\n\n    region = city_response.subdivisions.most_specific.name\n    response += \" | Region: %s\" % region if region else \"\"\n    city = city_response.city.name\n    response += \" | City: %s\" % city if city else \"\"\n    isp = \"AS\" + str(asn_response.autonomous_system_number) + \\\n          \" \" + asn_response.autonomous_system_organization\n    response += \" | ISP: %s\" % isp if isp else \"\"\n    bot.say(response)\n\n\nif __name__ == \"__main__\":\n    from sopel.test_tools import run_example_tests\n    run_example_tests(__file__)\n", "path": "sopel/modules/ip.py"}]}