diff --git a/deluge/core/core.py b/deluge/core/core.py
index 9f51e1773..c03fca0e9 100644
--- a/deluge/core/core.py
+++ b/deluge/core/core.py
@@ -92,6 +92,10 @@ class Core(component.Component):
# New release check information
self.new_release = None
+ # External IP Address from libtorrent
+ self.external_ip = None
+ self.eventmanager.register_event_handler("ExternalIPEvent", self._on_external_ip_event)
+
# Get the core config
self.config = ConfigManager("core.conf")
self.config.save()
@@ -920,6 +924,16 @@ class Core(component.Component):
except InvalidPathError:
return -1
+ def _on_external_ip_event(self, external_ip):
+ self.external_ip = external_ip
+
+ @export
+ def get_external_ip(self):
+ """
+ Returns the external ip address recieved from libtorrent.
+ """
+ return self.external_ip
+
@export
def get_libtorrent_version(self):
"""
diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py
index e158e891f..ec0b8f8aa 100644
--- a/deluge/core/torrentmanager.py
+++ b/deluge/core/torrentmanager.py
@@ -28,8 +28,9 @@ from deluge.configmanager import ConfigManager, get_config_dir
from deluge.core.authmanager import AUTH_LEVEL_ADMIN
from deluge.core.torrent import Torrent, TorrentOptions, sanitize_filepath
from deluge.error import AddTorrentError, InvalidTorrentError
-from deluge.event import (PreTorrentRemovedEvent, SessionStartedEvent, TorrentAddedEvent, TorrentFileCompletedEvent,
- TorrentFileRenamedEvent, TorrentFinishedEvent, TorrentRemovedEvent, TorrentResumedEvent)
+from deluge.event import (ExternalIPEvent, PreTorrentRemovedEvent, SessionStartedEvent, TorrentAddedEvent,
+ TorrentFileCompletedEvent, TorrentFileRenamedEvent, TorrentFinishedEvent, TorrentRemovedEvent,
+ TorrentResumedEvent)
log = logging.getLogger(__name__)
@@ -1256,8 +1257,14 @@ class TorrentManager(component.Component):
self.handle_torrents_status_callback(self.torrents_status_requests.pop())
def on_alert_external_ip(self, alert):
- """Alert handler for libtorrent external_ip_alert"""
- log.info("on_alert_external_ip: %s", decode_string(alert.message()))
+ """Alert handler for libtorrent external_ip_alert
+
+ Note:
+ alert.message format is: "external IP received: 0.0.0.0"
+ """
+ external_ip = decode_string(alert.message()).split(':')[1].strip()
+ log.info("on_alert_external_ip: %s", external_ip)
+ component.get("EventManager").emit(ExternalIPEvent(external_ip))
def on_alert_performance(self, alert):
"""Alert handler for libtorrent performance_alert"""
diff --git a/deluge/event.py b/deluge/event.py
index f91d6d2ea..4a143266b 100644
--- a/deluge/event.py
+++ b/deluge/event.py
@@ -285,3 +285,15 @@ class ClientDisconnectedEvent(DelugeEvent):
"""
def __init__(self, session_id):
self._args = [session_id]
+
+
+class ExternalIPEvent(DelugeEvent):
+ """
+ Emitted when the external ip address is received from libtorrent.
+ """
+ def __init__(self, external_ip):
+ """
+ Args:
+ external_ip (str): The IP address.
+ """
+ self._args = [external_ip]
diff --git a/deluge/ui/console/statusbars.py b/deluge/ui/console/statusbars.py
index ae31470d0..5a002823d 100644
--- a/deluge/ui/console/statusbars.py
+++ b/deluge/ui/console/statusbars.py
@@ -23,6 +23,7 @@ class StatusBars(component.Component):
self.download = ""
self.upload = ""
self.dht = 0
+ self.external_ip = ""
# Default values
self.topbar = "{!status!}Deluge %s Console - " % deluge.common.get_version()
@@ -41,12 +42,16 @@ class StatusBars(component.Component):
self.update_statusbars()
+ def on_get_external_ip(external_ip):
+ self.external_ip = external_ip
+
keys = ["num_peers", "payload_upload_rate", "payload_download_rate"]
if self.config["dht"]:
keys.append("dht_nodes")
client.core.get_session_status(keys).addCallback(on_get_session_status)
+ client.core.get_external_ip().addCallback(on_get_external_ip)
def update_statusbars(self):
# Update the topbar string
@@ -105,3 +110,6 @@ class StatusBars(component.Component):
if self.config["dht"]:
self.bottombar += " " + _("DHT") + ": {!white,blue!}%s{!status!}" % self.dht
+
+ self.bottombar += " " + _("IP {!white,blue!}%s{!status!}") % (
+ self.external_ip if self.external_ip else _("n/a"))
diff --git a/deluge/ui/gtkui/addtorrentdialog.py b/deluge/ui/gtkui/addtorrentdialog.py
index fa2b99e5b..5dc1fbf89 100644
--- a/deluge/ui/gtkui/addtorrentdialog.py
+++ b/deluge/ui/gtkui/addtorrentdialog.py
@@ -210,7 +210,7 @@ class AddTorrentDialog(component.Component):
if not row and new_row:
self.listview_torrents.get_selection().select_iter(new_row)
- self.dialog.set_title("Add Torrents (%d)" % len(self.torrent_liststore))
+ self.dialog.set_title(_("Add Torrents (%d)") % len(self.torrent_liststore))
if already_added:
log.debug("Tried to add %d duplicate torrents!", already_added)
diff --git a/deluge/ui/gtkui/statusbar.py b/deluge/ui/gtkui/statusbar.py
index 7d52d0224..c18f27236 100644
--- a/deluge/ui/gtkui/statusbar.py
+++ b/deluge/ui/gtkui/statusbar.py
@@ -179,6 +179,9 @@ class StatusBar(component.Component):
text=_("No Incoming Connections!"),
callback=self._on_health_icon_clicked, pack_start=True)
+ self.external_ip_item = self.add_item(
+ tooltip=_("External IP Address"), pack_start=True)
+
self.health = False
def update_config_values(configs):
@@ -201,6 +204,7 @@ class StatusBar(component.Component):
self.remove_item(self.health_item)
self.remove_item(self.traffic_item)
self.remove_item(self.diskspace_item)
+ self.remove_item(self.external_ip_item)
except Exception as ex:
log.debug("Unable to remove StatusBar item: %s", ex)
self.show_not_connected()
@@ -270,6 +274,7 @@ class StatusBar(component.Component):
client.core.get_session_status(keys).addCallback(self._on_get_session_status)
client.core.get_free_space().addCallback(self._on_get_free_space)
+ client.core.get_external_ip().addCallback(self._on_get_external_ip)
def on_configvaluechanged_event(self, key, value):
"""
@@ -326,6 +331,10 @@ class StatusBar(component.Component):
self.max_upload_speed = max_upload_speed
self.update_upload_label()
+ def _on_get_external_ip(self, external_ip):
+ ip = external_ip if external_ip else _("n/a")
+ self.external_ip_item.set_markup(_("IP %s") % ip)
+
def update_connections_label(self):
# Set the max connections label
if self.max_connections_global < 0:
diff --git a/deluge/ui/web/js/deluge-all/Statusbar.js b/deluge/ui/web/js/deluge-all/Statusbar.js
index 74266723e..90d220f93 100644
--- a/deluge/ui/web/js/deluge-all/Statusbar.js
+++ b/deluge/ui/web/js/deluge-all/Statusbar.js
@@ -180,6 +180,11 @@ Deluge.Statusbar = Ext.extend(Ext.ux.StatusBar, {
deluge.preferences.show();
deluge.preferences.selectPage('Network');
}
+ }, '-', {
+ id: 'statusbar-externalip',
+ text: ' ',
+ cls: 'x-btn-text',
+ tooltip: _('External IP Address')
}, '-', {
id: 'statusbar-dht',
text: ' ',
@@ -289,5 +294,7 @@ Deluge.Statusbar = Ext.extend(Ext.ux.StatusBar, {
this.items.get('statusbar-dht').setText(stats.dht_nodes);
this.items.get('statusbar-freespace').setText(stats.free_space >= 0 ? fsize(stats.free_space): _('Error'));
+ this.items.get('statusbar-externalip').setText(
+ String.format(_('IP {0}'), stats.external_ip ? stats.external_ip: _("n/a")));
}
});
diff --git a/deluge/ui/web/json_api.py b/deluge/ui/web/json_api.py
index 21c5d59a8..e846234b8 100644
--- a/deluge/ui/web/json_api.py
+++ b/deluge/ui/web/json_api.py
@@ -525,6 +525,9 @@ class WebApi(JSONComponent):
def got_free_space(free_space):
ui_info["stats"]["free_space"] = free_space
+ def got_external_ip(external_ip):
+ ui_info["stats"]["external_ip"] = external_ip
+
def got_torrents(torrents):
ui_info["torrents"] = torrents
@@ -551,7 +554,10 @@ class WebApi(JSONComponent):
d4 = client.core.get_free_space(self.core_config.get("download_location"))
d4.addCallback(got_free_space)
- dl = DeferredList([d1, d2, d3, d4], consumeErrors=True)
+ d5 = client.core.get_external_ip()
+ d5.addCallback(got_external_ip)
+
+ dl = DeferredList([d1, d2, d3, d4, d5], consumeErrors=True)
dl.addCallback(on_complete)
return d