mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-10 07:22:37 -07:00
Async ISP lookup
This commit is contained in:
parent
9b067a437c
commit
ba8e4ff33c
5 changed files with 149 additions and 69 deletions
41
API.md
41
API.md
|
@ -342,18 +342,7 @@ Returns:
|
||||||
"timezone": "America/Los_Angeles",
|
"timezone": "America/Los_Angeles",
|
||||||
"latitude": 37.386,
|
"latitude": 37.386,
|
||||||
"longitude": -122.0838,
|
"longitude": -122.0838,
|
||||||
"accuracy": 1000,
|
"accuracy": 1000
|
||||||
"net": [{"description": "Google Inc.",
|
|
||||||
"address": "1600 Amphitheatre Parkway",
|
|
||||||
"city": "Mountain View",
|
|
||||||
"state": "CA",
|
|
||||||
"postal_code": "94043",
|
|
||||||
"country": "United States",
|
|
||||||
...
|
|
||||||
},
|
|
||||||
{...}
|
|
||||||
]
|
|
||||||
|
|
||||||
}
|
}
|
||||||
json:
|
json:
|
||||||
{"error": "The address 127.0.0.1 is not in the database."
|
{"error": "The address 127.0.0.1 is not in the database."
|
||||||
|
@ -1716,6 +1705,34 @@ Returns:
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### get_whois_lookup
|
||||||
|
Get the ISP info for an IP address.
|
||||||
|
|
||||||
|
```
|
||||||
|
Required parameters:
|
||||||
|
ip_address
|
||||||
|
|
||||||
|
Optional parameters:
|
||||||
|
None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
json:
|
||||||
|
[{"description": "Google Inc.",
|
||||||
|
"address": "1600 Amphitheatre Parkway",
|
||||||
|
"city": "Mountain View",
|
||||||
|
"state": "CA",
|
||||||
|
"postal_code": "94043",
|
||||||
|
"country": "United States",
|
||||||
|
...
|
||||||
|
},
|
||||||
|
{...}
|
||||||
|
]
|
||||||
|
json:
|
||||||
|
{"error": "The address 127.0.0.1 is not in the database."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### import_database
|
### import_database
|
||||||
Import a PlexWatch or Plexivity database into PlexPy.
|
Import a PlexWatch or Plexivity database into PlexPy.
|
||||||
|
|
||||||
|
|
|
@ -3009,8 +3009,10 @@ a:hover .overlay-refresh-image {
|
||||||
a:hover .overlay-refresh-image:hover {
|
a:hover .overlay-refresh-image:hover {
|
||||||
opacity: .9;
|
opacity: .9;
|
||||||
}
|
}
|
||||||
#ip_error {
|
#ip_error, #isp_error {
|
||||||
color: #aaa;
|
color: #aaa;
|
||||||
display: none;
|
display: none;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
}
|
}
|
|
@ -13,10 +13,10 @@
|
||||||
</h4>
|
</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body" id="modal-text">
|
<div class="modal-body" id="modal-text">
|
||||||
<div id="ip_error" class="text-muted"></div>
|
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<h4><strong>Location Details</strong></h4>
|
<h4><strong>Location Details</strong><span id="ip_loading" style="padding-left: 5px;"><i class="fa fa-refresh fa-spin"></i></span></h4>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="ip_error" class="col-sm-12 text-muted"></div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li>Continent: <strong><span id="continent"></span></strong></li>
|
<li>Continent: <strong><span id="continent"></span></strong></li>
|
||||||
|
@ -35,8 +35,9 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<h4><strong>Connection Details</strong></h4>
|
<h4><strong>Connection Details</strong><span id="isp_loading" style="padding-left: 5px;"><i class="fa fa-refresh fa-spin"></i></span></h4>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="isp_error" class="col-sm-12 text-muted"></div>
|
||||||
<div class="col-sm-6" id="isp_instance">
|
<div class="col-sm-6" id="isp_instance">
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<li>ISP: <strong><span id="isp"></span></strong></li>
|
<li>ISP: <strong><span id="isp"></span></strong></li>
|
||||||
|
@ -59,13 +60,16 @@
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
data: { ip_address: ip_address },
|
data: { ip_address: ip_address },
|
||||||
cache: true,
|
cache: true,
|
||||||
async: true,
|
async: true,
|
||||||
|
complete: function () {
|
||||||
|
$('#ip_loading').remove();
|
||||||
|
},
|
||||||
error: function () {
|
error: function () {
|
||||||
$('#ip_error').html('<i class="fa fa-exclamation-circle"></i> Request failed.<br /><br />').show();
|
$('#ip_error').html('<i class="fa fa-exclamation-circle"></i> Internal request failed.').show();
|
||||||
},
|
},
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if ('error' in data) {
|
if ('error' in data) {
|
||||||
$('#ip_error').html('<i class="fa fa-exclamation-circle"></i> ' + data.error + '<br /><br />').show();
|
$('#ip_error').html('<i class="fa fa-exclamation-circle"></i> ' + data.error).show();
|
||||||
} else {
|
} else {
|
||||||
$('#continent').html(data.continent);
|
$('#continent').html(data.continent);
|
||||||
$('#country').html(data.country);
|
$('#country').html(data.country);
|
||||||
|
@ -76,30 +80,54 @@
|
||||||
$('#latitude').html(data.latitude);
|
$('#latitude').html(data.latitude);
|
||||||
$('#longitude').html(data.longitude);
|
$('#longitude').html(data.longitude);
|
||||||
$('#accuracy').html(data.accuracy + ' km');
|
$('#accuracy').html(data.accuracy + ' km');
|
||||||
|
|
||||||
var nets = data.nets;
|
|
||||||
if (!(nets.length)) {
|
|
||||||
$('#isp').html('Not Found')
|
|
||||||
$('#isp_address').html('Not Found')
|
|
||||||
} else {
|
|
||||||
$('#isp_instance').remove();
|
|
||||||
$.each(nets, function (index, net) {
|
|
||||||
$('#modal-text').append('<div class="col-sm-6"> \
|
|
||||||
<ul class="list-unstyled"> \
|
|
||||||
<li>ISP: <strong>' + net.description + '</strong></li> \
|
|
||||||
<li><span style="float: left;">Address: </span> \
|
|
||||||
<span style="float: left;"><strong>' + net.address + '</strong><br /> \
|
|
||||||
<strong>' + net.city + ", " + net.state + " " + net.postal_code + '</strong><br /> \
|
|
||||||
<strong>' + net.country + '</strong></span> \
|
|
||||||
</li> \
|
|
||||||
</ul> \
|
|
||||||
</div>')
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getUserConnection(ip_address) {
|
||||||
|
$.ajax({
|
||||||
|
url: 'get_whois_lookup',
|
||||||
|
type: 'GET',
|
||||||
|
data: { ip_address: ip_address },
|
||||||
|
cache: true,
|
||||||
|
async: true,
|
||||||
|
complete: function () {
|
||||||
|
$('#isp_loading').remove();
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
$('#isp_error').html('<i class="fa fa-exclamation-circle"></i> Internal request failed.').show();
|
||||||
|
},
|
||||||
|
success: function (data) {
|
||||||
|
if ('error' in data) {
|
||||||
|
$('#isp_error').html('<i class="fa fa-exclamation-circle"></i> ' + data.error).show();
|
||||||
|
} else if (!(data.length)) {
|
||||||
|
$('#isp_error').html('<i class="fa fa-exclamation-circle"></i> Connection details not found.').show();
|
||||||
|
} else {
|
||||||
|
$('#isp_instance').remove();
|
||||||
|
$.each(data, function (index, net) {
|
||||||
|
var s = '';
|
||||||
|
if (net.city || net.state || net.postal_code) {
|
||||||
|
s = (net.city && net.state) ? net.city + ', ' + net.state : net.city || net.state || '';
|
||||||
|
s = (s && net.postal_code) ? s + ' ' + net.postal_code : s || net.postal_code || '';
|
||||||
|
}
|
||||||
|
s = (s) ? '<strong>' + s + '</strong><br />' : s;
|
||||||
|
$('#modal-text').append('<div class="col-sm-6"> \
|
||||||
|
<ul class="list-unstyled"> \
|
||||||
|
<li>ISP: <strong>' + net.description + '</strong></li> \
|
||||||
|
<li><span style="float: left;">Address: </span> \
|
||||||
|
<span style="float: left;"><strong>' + net.address + '</strong><br />' + s +
|
||||||
|
'<strong>' + net.country + '</strong></span> \
|
||||||
|
</li> \
|
||||||
|
</ul> \
|
||||||
|
</div>')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getUserLocation('${data}');
|
getUserLocation('${data}');
|
||||||
|
getUserConnection('${data}');
|
||||||
</script>
|
</script>
|
||||||
% endif
|
% endif
|
|
@ -20,8 +20,7 @@ import geoip2.database, geoip2.errors
|
||||||
import gzip
|
import gzip
|
||||||
import hashlib
|
import hashlib
|
||||||
import imghdr
|
import imghdr
|
||||||
from ipwhois import IPWhois
|
import ipwhois, ipwhois.exceptions, ipwhois.utils
|
||||||
from ipwhois.utils import get_countries
|
|
||||||
from IPy import IP
|
from IPy import IP
|
||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
|
@ -604,12 +603,11 @@ def geoip_lookup(ip_address):
|
||||||
reader = geoip2.database.Reader(plexpy.CONFIG.GEOIP_DB)
|
reader = geoip2.database.Reader(plexpy.CONFIG.GEOIP_DB)
|
||||||
geo = reader.city(ip_address)
|
geo = reader.city(ip_address)
|
||||||
reader.close()
|
reader.close()
|
||||||
|
except ValueError as e:
|
||||||
|
return 'Invalid IP address provided: %s.' % ip_address
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
return 'Missing GeoLite2 database. Please reinstall from the ' \
|
return 'Missing GeoLite2 database. Please reinstall from the ' \
|
||||||
'<a href="settings?install_geoip=true">Settings</a> page.'
|
'<a href="settings?install_geoip=true">Settings</a> page.'
|
||||||
except ValueError as e:
|
|
||||||
return 'Unable to read GeoLite2 database. Please reinstall from the ' \
|
|
||||||
'<a href="settings?reinstall_geoip=true">Settings</a> page.'
|
|
||||||
except maxminddb.InvalidDatabaseError as e:
|
except maxminddb.InvalidDatabaseError as e:
|
||||||
return 'Invalid GeoLite2 database. Please reinstall from the ' \
|
return 'Invalid GeoLite2 database. Please reinstall from the ' \
|
||||||
'<a href="settings?reinstall_geoip=true">Settings</a> page.'
|
'<a href="settings?reinstall_geoip=true">Settings</a> page.'
|
||||||
|
@ -618,17 +616,6 @@ def geoip_lookup(ip_address):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return 'Error: %s' % e
|
return 'Error: %s' % e
|
||||||
|
|
||||||
nets = []
|
|
||||||
try:
|
|
||||||
whois = IPWhois(ip_address).lookup_whois()
|
|
||||||
countries = get_countries()
|
|
||||||
nets = whois['nets']
|
|
||||||
for net in nets:
|
|
||||||
net['country'] = countries[net['country']]
|
|
||||||
net['postal_code'] = net['postal_code'].replace('-', ' ')
|
|
||||||
except Exception as e:
|
|
||||||
logger.warn(u"PlexPy Helpers :: %s." % e)
|
|
||||||
|
|
||||||
geo_info = {'continent': geo.continent.name,
|
geo_info = {'continent': geo.continent.name,
|
||||||
'country': geo.country.name,
|
'country': geo.country.name,
|
||||||
'region': geo.subdivisions.most_specific.name,
|
'region': geo.subdivisions.most_specific.name,
|
||||||
|
@ -637,12 +624,33 @@ def geoip_lookup(ip_address):
|
||||||
'timezone': geo.location.time_zone,
|
'timezone': geo.location.time_zone,
|
||||||
'latitude': geo.location.latitude,
|
'latitude': geo.location.latitude,
|
||||||
'longitude': geo.location.longitude,
|
'longitude': geo.location.longitude,
|
||||||
'accuracy': geo.location.accuracy_radius,
|
'accuracy': geo.location.accuracy_radius
|
||||||
'nets': nets
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return geo_info
|
return geo_info
|
||||||
|
|
||||||
|
def whois_lookup(ip_address):
|
||||||
|
|
||||||
|
nets = []
|
||||||
|
try:
|
||||||
|
whois = ipwhois.IPWhois(ip_address).lookup_whois(retry_count=0)
|
||||||
|
countries = ipwhois.utils.get_countries()
|
||||||
|
nets = whois['nets']
|
||||||
|
for net in nets:
|
||||||
|
net['country'] = countries[net['country']]
|
||||||
|
if net['postal_code']:
|
||||||
|
net['postal_code'] = net['postal_code'].replace('-', ' ')
|
||||||
|
except ValueError as e:
|
||||||
|
return 'Invalid IP address provided: %s.' % ip_address
|
||||||
|
except ipwhois.exceptions.IPDefinedError as e:
|
||||||
|
return '%s' % e
|
||||||
|
except ipwhois.exceptions.ASNRegistryError as e:
|
||||||
|
return '%s' % e
|
||||||
|
except Exception as e:
|
||||||
|
return 'Error: %s' % e
|
||||||
|
|
||||||
|
return nets
|
||||||
|
|
||||||
# Taken from SickRage
|
# Taken from SickRage
|
||||||
def anon_url(*url):
|
def anon_url(*url):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -4310,18 +4310,7 @@ class WebInterface(object):
|
||||||
"timezone": "America/Los_Angeles",
|
"timezone": "America/Los_Angeles",
|
||||||
"latitude": 37.386,
|
"latitude": 37.386,
|
||||||
"longitude": -122.0838,
|
"longitude": -122.0838,
|
||||||
"accuracy": 1000,
|
"accuracy": 1000
|
||||||
"net": [{"description": "Google Inc.",
|
|
||||||
"address": "1600 Amphitheatre Parkway",
|
|
||||||
"city": "Mountain View",
|
|
||||||
"state": "CA",
|
|
||||||
"postal_code": "94043",
|
|
||||||
"country": "United States",
|
|
||||||
...
|
|
||||||
},
|
|
||||||
{...}
|
|
||||||
]
|
|
||||||
|
|
||||||
}
|
}
|
||||||
json:
|
json:
|
||||||
{"error": "The address 127.0.0.1 is not in the database."
|
{"error": "The address 127.0.0.1 is not in the database."
|
||||||
|
@ -4332,3 +4321,39 @@ class WebInterface(object):
|
||||||
if isinstance(geo_info, basestring):
|
if isinstance(geo_info, basestring):
|
||||||
return {'error': geo_info}
|
return {'error': geo_info}
|
||||||
return geo_info
|
return geo_info
|
||||||
|
|
||||||
|
@cherrypy.expose
|
||||||
|
@cherrypy.tools.json_out()
|
||||||
|
@requireAuth()
|
||||||
|
@addtoapi()
|
||||||
|
def get_whois_lookup(self, ip_address='', **kwargs):
|
||||||
|
""" Get the ISP info for an IP address.
|
||||||
|
|
||||||
|
```
|
||||||
|
Required parameters:
|
||||||
|
ip_address
|
||||||
|
|
||||||
|
Optional parameters:
|
||||||
|
None
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
json:
|
||||||
|
[{"description": "Google Inc.",
|
||||||
|
"address": "1600 Amphitheatre Parkway",
|
||||||
|
"city": "Mountain View",
|
||||||
|
"state": "CA",
|
||||||
|
"postal_code": "94043",
|
||||||
|
"country": "United States",
|
||||||
|
...
|
||||||
|
},
|
||||||
|
{...}
|
||||||
|
]
|
||||||
|
json:
|
||||||
|
{"error": "The address 127.0.0.1 is not in the database."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
whois_info = helpers.whois_lookup(ip_address)
|
||||||
|
if isinstance(whois_info, basestring):
|
||||||
|
return {'error': whois_info}
|
||||||
|
return whois_info
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue