mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-16 02:02:58 -07:00
IP address lookup using MaxMind GeoLite2 database
This commit is contained in:
parent
f5bfa67c69
commit
c96b1eb09d
22 changed files with 2886 additions and 32 deletions
|
@ -154,6 +154,7 @@ _CONFIG_DEFINITIONS = {
|
|||
'FACEBOOK_ON_PMSUPDATE': (int, 'Facebook', 0),
|
||||
'FIRST_RUN_COMPLETE': (int, 'General', 0),
|
||||
'FREEZE_DB': (int, 'General', 0),
|
||||
'GEOIP_DB': (str, 'General', ''),
|
||||
'GET_FILE_SIZES': (int, 'General', 0),
|
||||
'GET_FILE_SIZES_HOLD': (dict, 'General', {'section_ids': [], 'rating_keys': []}),
|
||||
'GIT_BRANCH': (str, 'General', 'master'),
|
||||
|
|
|
@ -16,11 +16,14 @@
|
|||
import base64
|
||||
import datetime
|
||||
from functools import wraps
|
||||
import geoip2.database, geoip2.errors
|
||||
import gzip
|
||||
import hashlib
|
||||
import imghdr
|
||||
from IPy import IP
|
||||
import json
|
||||
import math
|
||||
import maxminddb
|
||||
from operator import itemgetter
|
||||
import os
|
||||
import re
|
||||
|
@ -514,6 +517,98 @@ def get_ip(host):
|
|||
|
||||
return ip_address
|
||||
|
||||
def install_geoip_db():
|
||||
maxmind_url = 'http://geolite.maxmind.com/download/geoip/database/'
|
||||
geolite2_gz = 'GeoLite2-City.mmdb.gz'
|
||||
geolite2_md5 = 'GeoLite2-City.md5'
|
||||
geolite2_db = geolite2_gz[:-3]
|
||||
md5_checksum = ''
|
||||
|
||||
temp_gz = os.path.join(plexpy.CONFIG.CACHE_DIR, geolite2_gz)
|
||||
geolite2_db = os.path.join(plexpy.DATA_DIR, geolite2_db)
|
||||
|
||||
# Retrieve the GeoLite2 gzip file
|
||||
logger.debug(u"PlexPy Helpers :: Downloading GeoLite2 gzip file from MaxMind...")
|
||||
try:
|
||||
maxmind = urllib.URLopener()
|
||||
maxmind.retrieve(maxmind_url + geolite2_gz, temp_gz)
|
||||
md5_checksum = urllib2.urlopen(maxmind_url + geolite2_md5).read()
|
||||
except Exception as e:
|
||||
logger.error(u"PlexPy Helpers :: Failed to download GeoLite2 gzip file from MaxMind: %s" % e)
|
||||
return False
|
||||
|
||||
# Extract the GeoLite2 database file
|
||||
logger.debug(u"PlexPy Helpers :: Extracting GeoLite2 database...")
|
||||
try:
|
||||
with gzip.open(temp_gz, 'rb') as gz:
|
||||
with open(geolite2_db, 'wb') as db:
|
||||
db.write(gz.read())
|
||||
except Exception as e:
|
||||
logger.error(u"PlexPy Helpers :: Failed to extract the GeoLite2 database: %s" % e)
|
||||
return False
|
||||
|
||||
# Check MD5 hash for GeoLite2 database file
|
||||
logger.debug(u"PlexPy Helpers :: Checking MD5 checksum for GeoLite2 database...")
|
||||
try:
|
||||
hash_md5 = hashlib.md5()
|
||||
with open(geolite2_db, 'rb') as f:
|
||||
for chunk in iter(lambda: f.read(4096), b""):
|
||||
hash_md5.update(chunk)
|
||||
md5_hash = hash_md5.hexdigest()
|
||||
|
||||
if md5_hash != md5_checksum:
|
||||
logger.error(u"PlexPy Helpers :: MD5 checksum doesn't match for GeoLite2 database. "
|
||||
"Checksum: %s, file hash: %s" % (md5_checksum, md5_hash))
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error(u"PlexPy Helpers :: Failed to generate MD5 checksum for GeoLite2 database: %s" % e)
|
||||
return False
|
||||
|
||||
# Delete temportary GeoLite2 gzip file
|
||||
logger.debug(u"PlexPy Helpers :: Deleting temporary GeoLite2 gzip file...")
|
||||
try:
|
||||
os.remove(temp_gz)
|
||||
except Exception as e:
|
||||
logger.warn(u"PlexPy Helpers :: Failed to remove temporary GeoLite2 gzip file: %s" % e)
|
||||
|
||||
logger.debug(u"PlexPy Helpers :: GeoLite2 database installed successfully.")
|
||||
plexpy.CONFIG.__setattr__('GEOIP_DB', geolite2_db)
|
||||
plexpy.CONFIG.write()
|
||||
|
||||
return True
|
||||
|
||||
def geoip_lookup(ip_address):
|
||||
if not plexpy.CONFIG.GEOIP_DB:
|
||||
return 'GeoLite2 database not installed. Please install from the Settings page.'
|
||||
|
||||
if not ip_address:
|
||||
return 'No IP address provided.'
|
||||
|
||||
try:
|
||||
reader = geoip2.database.Reader(plexpy.CONFIG.GEOIP_DB)
|
||||
geo = reader.city(ip_address)
|
||||
reader.close()
|
||||
except IOError as e:
|
||||
return 'Missing GeoLite2 database. Please reinstall from the Settings page.'
|
||||
except ValueError as e:
|
||||
return 'Unable to read GeoLite2 database: %s' % e
|
||||
except maxminddb.InvalidDatabaseError as e:
|
||||
return 'Invalid GeoLite2 database.'
|
||||
except geoip2.errors.AddressNotFoundError as e:
|
||||
return '%s' % e
|
||||
except Exception as e:
|
||||
return 'Error: %s' % e
|
||||
|
||||
geo_info = {'country': geo.country.name,
|
||||
'region': geo.subdivisions.most_specific.name,
|
||||
'city': geo.city.name,
|
||||
'timezone': geo.location.time_zone,
|
||||
'latitude': geo.location.latitude,
|
||||
'longitude': geo.location.longitude
|
||||
}
|
||||
|
||||
return geo_info
|
||||
|
||||
# Taken from SickRage
|
||||
def anon_url(*url):
|
||||
"""
|
||||
|
|
|
@ -2608,6 +2608,7 @@ class WebInterface(object):
|
|||
"imgur_client_id": plexpy.CONFIG.IMGUR_CLIENT_ID,
|
||||
"cache_images": checked(plexpy.CONFIG.CACHE_IMAGES),
|
||||
"pms_version": plexpy.CONFIG.PMS_VERSION,
|
||||
"geoip_db": plexpy.CONFIG.GEOIP_DB
|
||||
}
|
||||
|
||||
return serve_template(templatename="settings.html", title="Settings", config=config)
|
||||
|
@ -2795,6 +2796,19 @@ class WebInterface(object):
|
|||
else:
|
||||
return {'result': 'error', 'message': 'Database backup failed.'}
|
||||
|
||||
@cherrypy.expose
|
||||
@cherrypy.tools.json_out()
|
||||
@requireAuth(member_of("admin"))
|
||||
def install_geoip_db(self):
|
||||
""" Downloads and installs the GeoIP database """
|
||||
|
||||
result = helpers.install_geoip_db()
|
||||
|
||||
if result:
|
||||
return {'result': 'success', 'message': 'GeoIP database installed successful.'}
|
||||
else:
|
||||
return {'result': 'error', 'message': 'GeoIP database install failed.'}
|
||||
|
||||
@cherrypy.expose
|
||||
@requireAuth(member_of("admin"))
|
||||
def get_notification_agent_config(self, agent_id, **kwargs):
|
||||
|
@ -4244,3 +4258,12 @@ class WebInterface(object):
|
|||
pms_connect = pmsconnect.PmsConnect()
|
||||
result = pms_connect.get_update_staus()
|
||||
return result
|
||||
|
||||
@cherrypy.expose
|
||||
@cherrypy.tools.json_out()
|
||||
@requireAuth()
|
||||
def get_geoip_lookup(self, ip_address='', **kwargs):
|
||||
geo_info = helpers.geoip_lookup(ip_address)
|
||||
if isinstance(geo_info, basestring):
|
||||
return {'error': geo_info}
|
||||
return geo_info
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue