From c5156df280cd78c2b1e822de4bafba141f635769 Mon Sep 17 00:00:00 2001 From: Andrew Resch Date: Mon, 17 Sep 2007 11:07:58 +0000 Subject: [PATCH] Add torrent from URL implemented. This is Marcos patch plus some more error checking and some modifications to make it work properly with TorrentManager. --- deluge/common.py | 20 +++++++ deluge/config.py | 1 + deluge/core/core.py | 23 ++++++++ deluge/core/torrentmanager.py | 5 +- deluge/ui/functions.py | 8 +++ deluge/ui/gtkui/addtorrenturl.py | 70 +++++++++++++++++++++++++ deluge/ui/gtkui/glade/main_window.glade | 1 + deluge/ui/gtkui/menubar.py | 2 + 8 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 deluge/ui/gtkui/addtorrenturl.py diff --git a/deluge/common.py b/deluge/common.py index b29f352af..54ccf5975 100644 --- a/deluge/common.py +++ b/deluge/common.py @@ -139,4 +139,24 @@ def ftime(seconds): return '%dw %dd' % (weeks, days) return 'unknown' +def is_url(url): + """A simple regex test to check if the URL is valid.""" + import re + return bool(re.search('^(https?|ftp)://', url)) +def fetch_url(url): + """Downloads a torrent file from a given + URL and checks the file's validity.""" + import urllib + from deluge.log import LOG as log + try: + filename, headers = urllib.urlretrieve(url) + except IOError: + log.debug("Network error while trying to fetch torrent from %s", url) + else: + if filename.endswith(".torrent") or headers["content-type"] ==\ + "application/x-bittorrent": + return filename + else: + log.debug("URL doesn't appear to be a valid torrent file: %s", url) + return None diff --git a/deluge/config.py b/deluge/config.py index 8ec226f5c..7cb0e6487 100644 --- a/deluge/config.py +++ b/deluge/config.py @@ -123,3 +123,4 @@ class Config: def __setitem__(self, key, value): self.set(key, value) + diff --git a/deluge/core/core.py b/deluge/core/core.py index 38de95e49..4f89cceb2 100644 --- a/deluge/core/core.py +++ b/deluge/core/core.py @@ -163,6 +163,29 @@ class Core(dbus.service.Object): # Return False because the torrent was not added successfully return False + @dbus.service.method(dbus_interface="org.deluge_torrent.Deluge", + in_signature="s", out_signature="b") + def add_torrent_url(self, url): + log.info("Attempting to add url %s", url) + + # 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 self.add_torrent_file(filename, filedump) + @dbus.service.method(dbus_interface="org.deluge_torrent.Deluge", in_signature="s", out_signature="") def remove_torrent(self, torrent_id): diff --git a/deluge/core/torrentmanager.py b/deluge/core/torrentmanager.py index af635ff16..017959589 100644 --- a/deluge/core/torrentmanager.py +++ b/deluge/core/torrentmanager.py @@ -92,7 +92,10 @@ class TorrentManager: # Convert the filedump data array into a string of bytes if filedump is not None: - filedump = "".join(chr(b) for b in filedump) + # If the filedump is already of type str, then it's already been + # joined. + if type(filedump) is not str: + filedump = "".join(chr(b) for b in filedump) else: # Get the data from the file try: diff --git a/deluge/ui/functions.py b/deluge/ui/functions.py index 6bcf4ac54..531f1423e 100644 --- a/deluge/ui/functions.py +++ b/deluge/ui/functions.py @@ -91,6 +91,14 @@ def add_torrent_file(torrent_files): # The torrent was not added successfully. log.warning("Torrent %s was not added successfully.", filename) +def add_torrent_url(torrent_url): + """Adds torrents to the core via url""" + core = get_core() + result = core.add_torrent_url(torrent_url) + if result is False: + # The torrent url was not added successfully. + log.warning("Torrent %s url was not added successfully.", torrent_url) + def remove_torrent(torrent_ids): """Removes torrent_ids from the core.. Expects a list of torrent_ids""" log.debug("Attempting to removing torrents: %s", torrent_ids) diff --git a/deluge/ui/gtkui/addtorrenturl.py b/deluge/ui/gtkui/addtorrenturl.py new file mode 100644 index 000000000..9a0e69012 --- /dev/null +++ b/deluge/ui/gtkui/addtorrenturl.py @@ -0,0 +1,70 @@ +# +# addtorrenturl.py +# +# Copyright (C) 2007 Marcos Pinto ('markybob') +# +# Deluge is free software. +# +# You may redistribute it and/or modify it under the terms of the +# GNU General Public License, as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) +# any later version. +# +# deluge is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with deluge. If not, write to: +# The Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor +# Boston, MA 02110-1301, USA. +# +# In addition, as a special exception, the copyright holders give +# permission to link the code of portions of this program with the OpenSSL +# library. +# You must obey the GNU General Public License in all respects for all of +# the code used other than OpenSSL. If you modify file(s) with this +# exception, you may extend this exception to your version of the file(s), +# but you are not obligated to do so. If you do not wish to do so, delete +# this exception statement from your version. If you delete this exception +# statement from all source files in the program, then also delete it here. + +import pygtk +pygtk.require('2.0') +import gtk, gtk.glade +import gettext + +from deluge.config import Config +import deluge.common +import pkg_resources + +class AddTorrentUrl: + def __init__(self, parent=None): + """Set up url dialog""" + self.dlg = gtk.Dialog(title=_("Add torrent from URL"), parent=None, + buttons=(gtk.STOCK_CANCEL, 0, gtk.STOCK_OK, 1)) + self.dlg.set_icon(deluge.common.get_logo(32)) + self.dlg.set_default_response(1) + label = gtk.Label(_("Enter the URL of the .torrent to download")) + self.entry = gtk.Entry() + self.dlg.vbox.pack_start(label) + self.dlg.vbox.pack_start(self.entry) + clip = gtk.clipboard_get(selection='PRIMARY') + text = clip.wait_for_text() + if text: + text = text.strip() + if deluge.common.is_url(text): + self.entry.set_text(text) + + def run(self): + """Show url dialog and add torrent""" + self.dlg.show_all() + self.response = self.dlg.run() + url = self.entry.get_text() + self.dlg.destroy() + if self.response == 1: + return url + else: + return None diff --git a/deluge/ui/gtkui/glade/main_window.glade b/deluge/ui/gtkui/glade/main_window.glade index c0461fe09..dd79347db 100644 --- a/deluge/ui/gtkui/glade/main_window.glade +++ b/deluge/ui/gtkui/glade/main_window.glade @@ -41,6 +41,7 @@ True Add _URL True + diff --git a/deluge/ui/gtkui/menubar.py b/deluge/ui/gtkui/menubar.py index 01c725c10..98def96fd 100644 --- a/deluge/ui/gtkui/menubar.py +++ b/deluge/ui/gtkui/menubar.py @@ -101,6 +101,8 @@ class MenuBar: def on_menuitem_addurl_activate(self, data=None): log.debug("on_menuitem_addurl_activate") + from addtorrenturl import AddTorrentUrl + functions.add_torrent_url(AddTorrentUrl().run()) def on_menuitem_clear_activate(self, data=None): log.debug("on_menuitem_clear_activate")