diff --git a/deluge/component.py b/deluge/component.py index a2bbba9ae..6fe62920f 100644 --- a/deluge/component.py +++ b/deluge/component.py @@ -32,7 +32,7 @@ COMPONENT_STATE = [ ] class Component(object): - def __init__(self, name, interval=1000, depend=None): + def __init__(self, name, interval=1, depend=None): # Register with the ComponentRegistry register(name, self, depend) self._interval = interval @@ -48,7 +48,8 @@ class Component(object): def _start(self): self._state = COMPONENT_STATE.index("Started") if self._update(): - self._timer = LoopingCall(self._interval, self._update) + self._timer = LoopingCall(self._update) + self._timer.start(self._interval) def stop(self): pass diff --git a/deluge/core/core.py b/deluge/core/core.py index 4cccd771a..07e474b2a 100644 --- a/deluge/core/core.py +++ b/deluge/core/core.py @@ -28,9 +28,11 @@ import os import os.path import threading import pkg_resources +import base64 from twisted.internet import reactor from twisted.internet.task import LoopingCall +import twisted.web.client try: import deluge.libtorrent as lt @@ -215,51 +217,81 @@ class Core(component.Component): return False # Exported Methods - @export() - def ping(self): - """A method to see if the core is running""" - return True - - @export() - def register_client(self, port): - """Registers a client with the signal manager so that signals are - sent to it.""" - self.signalmanager.register_client(component.get("RPCServer").client_address, port) - if self.config["new_release_check"]: - self.check_new_release() - - @export() - def deregister_client(self): - """De-registers a client with the signal manager.""" - self.signalmanager.deregister_client(component.get("RPCServer").client_address) - @export() def add_torrent_file(self, filename, filedump, options): - """Adds a torrent file to the libtorrent session - This requires the torrents filename and a dump of it's content """ - reactor.callLater(0, self._add_torrent_file, filename, filedump, options) + Adds a torrent file to the session. - def _add_torrent_file(self, filename, filedump, options): - # Turn the filedump into a torrent_info - if not isinstance(filedump, str): - filedump = filedump.data + :param filename: str, the filename of the torrent + :param filedump: str, a base64 encoded string of the torrent file contents + :param options: dict, the options to apply to the torrent on add - if len(filedump) == 0: - log.warning("Torrent file is corrupt!") - return + :returns: the torrent_id as a str or None + + """ + try: + filedump = base64.decodestring(filedump) + except Exception, e: + log.error("There was an error decoding the filedump string!") + log.exception(e) try: - torrent_info = lt.torrent_info(lt.bdecode(filedump)) - except RuntimeError, e: - log.warning("Unable to decode torrent file: %s", e) - return None - - torrent_id = self.torrentmanager.add(filedump=filedump, options=options, filename=filename) + torrent_id = self.torrentmanager.add(filedump=filedump, options=options, filename=filename) + except Exception, e: + log.error("There was an error adding the torrent file %s", filename) + log.exception(e) # Run the plugin hooks for 'post_torrent_add' self.pluginmanager.run_post_torrent_add(torrent_id) + @export() + def add_torrent_url(self, url, options): + """ + Adds a torrent from a url. Deluge will attempt to fetch the torrent + from url prior to adding it to the session. + + :param url: str, the url pointing to the torrent file + :param options: dict, the options to apply to the torrent on add + + :returns: the torrent_id as a str or None + + """ + log.info("Attempting to add url %s", url) + def on_get_page(page): + # We got the data, so attempt adding it to the session + self.add_torrent_file(url.split("/")[-1], base64.encodestring(page), options) + + def on_get_page_error(reason): + log.error("Error occured downloading torrent from %s", url) + log.error("Reason: %s", reason) + # XXX: Probably should raise an exception to the client here + return + + twisted.web.client.getPage(url).addCallback(on_get_page).addErrback(on_get_page_error) + + @export() + def add_torrent_magnets(self, uris, options): + for uri in uris: + log.debug("Attempting to add by magnet uri: %s", uri) + try: + option = options[uris.index(uri)] + except IndexError: + option = None + + torrent_id = self.torrentmanager.add(magnet=uri, options=option) + + # Run the plugin hooks for 'post_torrent_add' + self.pluginmanager.run_post_torrent_add(torrent_id) + + + @export() + def remove_torrent(self, torrent_ids, remove_data): + log.debug("Removing torrent %s from the core.", torrent_ids) + for torrent_id in torrent_ids: + if self.torrentmanager.remove(torrent_id, remove_data): + # Run the plugin hooks for 'post_torrent_remove' + self.pluginmanager.run_post_torrent_remove(torrent_id) + @export() def get_stats(self): """ @@ -297,53 +329,6 @@ class Core(component.Component): return status - @export() - def add_torrent_url(self, url, options): - log.info("Attempting to add url %s", url) - - threading.Thread(target=self.fetch_torrent_url_thread, args=(self.add_torrent_file, url, options)).start() - - def fetch_torrent_url_thread(self, callback, url, options): - # Get the actual filename of the torrent from the url provided. - filename = url.split("/")[-1] - - # Get the .torrent file from the url - torrent_file = deluge.common.fetch_url(url) - if torrent_file is None: - return False - - # Dump the torrents file contents to a string - try: - filedump = open(torrent_file, "rb").read() - except IOError: - log.warning("Unable to open %s for reading.", torrent_file) - return False - - # Add the torrent to session - return callback(filename, filedump, options) - - @export() - def add_torrent_magnets(self, uris, options): - for uri in uris: - log.debug("Attempting to add by magnet uri: %s", uri) - try: - option = options[uris.index(uri)] - except IndexError: - option = None - - torrent_id = self.torrentmanager.add(magnet=uri, options=option) - - # Run the plugin hooks for 'post_torrent_add' - self.pluginmanager.run_post_torrent_add(torrent_id) - - @export() - def remove_torrent(self, torrent_ids, remove_data): - log.debug("Removing torrent %s from the core.", torrent_ids) - for torrent_id in torrent_ids: - if self.torrentmanager.remove(torrent_id, remove_data): - # Run the plugin hooks for 'post_torrent_remove' - self.pluginmanager.run_post_torrent_remove(torrent_id) - @export() def force_reannounce(self, torrent_ids): log.debug("Forcing reannouncment to: %s", torrent_ids) diff --git a/deluge/ui/gtkui/addtorrentdialog.py b/deluge/ui/gtkui/addtorrentdialog.py index aebe7f35d..f7084d3f3 100644 --- a/deluge/ui/gtkui/addtorrentdialog.py +++ b/deluge/ui/gtkui/addtorrentdialog.py @@ -28,6 +28,8 @@ pygtk.require('2.0') import gtk, gtk.glade import gettext import gobject +import base64 +import os import pkg_resources @@ -671,7 +673,11 @@ class AddTorrentDialog(component.Component): row = self.torrent_liststore.iter_next(row) if torrent_filenames: - client.core.add_torrent_file(torrent_filenames, torrent_options) + for i, f in enumerate(torrent_filenames): + client.core.add_torrent_file( + os.path.split(f)[-1], + base64.encodestring(open(f).read()), + torrent_options[i]) if torrent_magnets: client.core.add_torrent_magnets(torrent_magnets, torrent_magnet_options) diff --git a/deluge/ui/gtkui/createtorrentdialog.py b/deluge/ui/gtkui/createtorrentdialog.py index e078a3de0..a4de42caf 100644 --- a/deluge/ui/gtkui/createtorrentdialog.py +++ b/deluge/ui/gtkui/createtorrentdialog.py @@ -321,7 +321,10 @@ class CreateTorrentDialog: httpseeds=httpseeds) self.glade.get_widget("progress_dialog").hide_all() if add_to_session: - client.core.add_torrent_file([target]) + client.core.add_torrent_file( + os.path.split(target)[-1], + base64.encodestring(open(target).read()), + None) def _on_create_torrent_progress(self, value, num_pieces): percent = float(value)/float(num_pieces) diff --git a/deluge/ui/gtkui/filtertreeview.py b/deluge/ui/gtkui/filtertreeview.py index dabcbf16a..b51ae352d 100644 --- a/deluge/ui/gtkui/filtertreeview.py +++ b/deluge/ui/gtkui/filtertreeview.py @@ -64,7 +64,7 @@ def _t(text): #sidebar-treeview class FilterTreeView(component.Component): def __init__(self): - component.Component.__init__(self, "FilterTreeView", interval=2000) + component.Component.__init__(self, "FilterTreeView", interval=2) self.window = component.get("MainWindow") glade = self.window.main_glade self.hpaned = glade.get_widget("hpaned") diff --git a/deluge/ui/gtkui/ipcinterface.py b/deluge/ui/gtkui/ipcinterface.py index 429370a6d..e91688af8 100644 --- a/deluge/ui/gtkui/ipcinterface.py +++ b/deluge/ui/gtkui/ipcinterface.py @@ -25,6 +25,7 @@ import sys import os.path +import base64 import deluge.component as component from deluge.ui.client import client @@ -106,4 +107,5 @@ def process_args(args): component.get("AddTorrentDialog").add_from_files([os.path.abspath(arg)]) component.get("AddTorrentDialog").show(config["focus_add_dialog"]) else: - client.core.add_torrent_file([os.path.abspath(arg)]) + path = os.path.abspath(arg) + client.core.add_torrent_file(os.path.split(path)[-1], base64.encodestring(open(path).read()), None) diff --git a/deluge/ui/gtkui/queuedtorrents.py b/deluge/ui/gtkui/queuedtorrents.py index f4c42d0df..4b1b386a7 100644 --- a/deluge/ui/gtkui/queuedtorrents.py +++ b/deluge/ui/gtkui/queuedtorrents.py @@ -178,7 +178,10 @@ class QueuedTorrents(component.Component): component.get("AddTorrentDialog").add_from_files([torrent_path]) component.get("AddTorrentDialog").show(self.config["focus_add_dialog"]) else: - client.core.add_torrent_file([torrent_path]) + client.core.add_torrent_file( + os.path.split(torrent_path)[-1], + base64.encodestring(open(torrent_path).read()), + None) self.liststore.foreach(add_torrent, None) del self.queue[:] diff --git a/deluge/ui/gtkui/statusbar.py b/deluge/ui/gtkui/statusbar.py index 5bcf2dea0..c0d4e77f7 100644 --- a/deluge/ui/gtkui/statusbar.py +++ b/deluge/ui/gtkui/statusbar.py @@ -91,7 +91,7 @@ class StatusBarItem: class StatusBar(component.Component): def __init__(self): - component.Component.__init__(self, "StatusBar", interval=3000) + component.Component.__init__(self, "StatusBar", interval=3) self.window = component.get("MainWindow") self.statusbar = self.window.main_glade.get_widget("statusbar") self.tooltips = gtk.Tooltips() diff --git a/deluge/ui/gtkui/systemtray.py b/deluge/ui/gtkui/systemtray.py index 714734dd3..aeabca889 100644 --- a/deluge/ui/gtkui/systemtray.py +++ b/deluge/ui/gtkui/systemtray.py @@ -35,7 +35,7 @@ import deluge.ui.gtkui.common as common class SystemTray(component.Component): def __init__(self): - component.Component.__init__(self, "SystemTray", interval=4000) + component.Component.__init__(self, "SystemTray", interval=4) self.window = component.get("MainWindow") self.config = ConfigManager("gtkui.conf") # List of widgets that need to be hidden when not connected to a host @@ -290,8 +290,7 @@ class SystemTray(component.Component): def on_menuitem_add_torrent_activate(self, menuitem): log.debug("on_menuitem_add_torrent_activate") - from addtorrentdialog import AddTorrentDialog - client.core.add_torrent_file(AddTorrentDialog().show()) + component.get("AddTorrentDialog").show() def on_menuitem_pause_all_activate(self, menuitem): log.debug("on_menuitem_pause_all_activate") diff --git a/deluge/ui/gtkui/torrentdetails.py b/deluge/ui/gtkui/torrentdetails.py index a4cac9f57..ee5e2ceb1 100644 --- a/deluge/ui/gtkui/torrentdetails.py +++ b/deluge/ui/gtkui/torrentdetails.py @@ -63,7 +63,7 @@ class Tab: class TorrentDetails(component.Component): def __init__(self): - component.Component.__init__(self, "TorrentDetails", interval=2000) + component.Component.__init__(self, "TorrentDetails", interval=2) self.window = component.get("MainWindow") glade = self.window.main_glade diff --git a/deluge/ui/gtkui/torrentview.py b/deluge/ui/gtkui/torrentview.py index 86e0ee841..4ff571f21 100644 --- a/deluge/ui/gtkui/torrentview.py +++ b/deluge/ui/gtkui/torrentview.py @@ -109,7 +109,7 @@ def queue_column_sort(model, iter1, iter2, data): class TorrentView(listview.ListView, component.Component): """TorrentView handles the listing of torrents.""" def __init__(self): - component.Component.__init__(self, "TorrentView", interval=2000) + component.Component.__init__(self, "TorrentView", interval=2) self.window = component.get("MainWindow") # Call the ListView constructor listview.ListView.__init__(self,