Add magnet uri support to Add Url in Webui

This commit is contained in:
Calum Lind 2012-02-18 00:39:24 +00:00
commit 717db367e8
4 changed files with 103 additions and 40 deletions

View file

@ -1,6 +1,6 @@
/*! /*!
* Deluge.add.AddWindow.js * Deluge.add.AddWindow.js
* *
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -50,7 +50,7 @@ Deluge.add.AddWindow = Ext.extend(Deluge.add.Window, {
this.addButton(_('Cancel'), this.onCancelClick, this); this.addButton(_('Cancel'), this.onCancelClick, this);
this.addButton(_('Add'), this.onAddClick, this); this.addButton(_('Add'), this.onAddClick, this);
function torrentRenderer(value, p, r) { function torrentRenderer(value, p, r) {
if (r.data['info_hash']) { if (r.data['info_hash']) {
return String.format('<div class="x-deluge-add-torrent-name">{0}</div>', value); return String.format('<div class="x-deluge-add-torrent-name">{0}</div>', value);
@ -73,7 +73,7 @@ Deluge.add.AddWindow = Ext.extend(Deluge.add.Window, {
sortable: true, sortable: true,
renderer: torrentRenderer, renderer: torrentRenderer,
dataIndex: 'text' dataIndex: 'text'
}], }],
stripeRows: true, stripeRows: true,
singleSelect: true, singleSelect: true,
listeners: { listeners: {
@ -114,7 +114,7 @@ Deluge.add.AddWindow = Ext.extend(Deluge.add.Window, {
}] }]
}) })
}); });
this.optionsPanel = this.add(new Deluge.add.OptionsPanel()); this.optionsPanel = this.add(new Deluge.add.OptionsPanel());
this.on('hide', this.onHide, this); this.on('hide', this.onHide, this);
this.on('show', this.onShow, this); this.on('show', this.onShow, this);
@ -165,16 +165,14 @@ Deluge.add.AddWindow = Ext.extend(Deluge.add.Window, {
var torrent = this.list.getSelectedRecords()[0]; var torrent = this.list.getSelectedRecords()[0];
this.list.getStore().remove(torrent); this.list.getStore().remove(torrent);
this.optionsPanel.clear(); this.optionsPanel.clear();
if (this.torrents && this.torrents[torrent.id]) delete this.torrents[torrent.id]; if (this.torrents && this.torrents[torrent.id]) delete this.torrents[torrent.id];
}, },
onSelect: function(list, selections) { onSelect: function(list, selections) {
if (selections.length) { if (selections.length) {
var record = this.list.getRecord(selections[0]); var record = this.list.getRecord(selections[0]);
this.optionsPanel.setTorrent(record.get('info_hash')); this.optionsPanel.setTorrent(record.get('info_hash'));
this.optionsPanel.files.setDisabled(false);
this.optionsPanel.form.setDisabled(false);
} else { } else {
this.optionsPanel.files.setDisabled(true); this.optionsPanel.files.setDisabled(true);
this.optionsPanel.form.setDisabled(true); this.optionsPanel.form.setDisabled(true);
@ -193,7 +191,7 @@ Deluge.add.AddWindow = Ext.extend(Deluge.add.Window, {
this.file.on('beforeadd', this.onTorrentBeforeAdd, this); this.file.on('beforeadd', this.onTorrentBeforeAdd, this);
this.file.on('add', this.onTorrentAdd, this); this.file.on('add', this.onTorrentAdd, this);
} }
this.optionsPanel.form.getDefaults(); this.optionsPanel.form.getDefaults();
}, },
@ -219,6 +217,7 @@ Deluge.add.AddWindow = Ext.extend(Deluge.add.Window, {
r.set('text', info['name']); r.set('text', info['name']);
this.list.getStore().commitChanges(); this.list.getStore().commitChanges();
this.optionsPanel.addTorrent(info); this.optionsPanel.addTorrent(info);
this.list.select(r);
} }
}, },

View file

@ -1,6 +1,6 @@
/*! /*!
* Deluge.add.OptionsPanel.js * Deluge.add.OptionsPanel.js
* *
* Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com> * Copyright (c) Damien Churchill 2009-2010 <damoxc@gmail.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -61,7 +61,7 @@ Deluge.add.OptionsPanel = Ext.extend(Ext.TabPanel, {
Ext.each(Ext.keys(fileIndexes), function(index) { Ext.each(Ext.keys(fileIndexes), function(index) {
priorities[index] = fileIndexes[index]; priorities[index] = fileIndexes[index];
}); });
var oldId = this.form.optionsManager.changeId(torrent['info_hash'], true); var oldId = this.form.optionsManager.changeId(torrent['info_hash'], true);
this.form.optionsManager.setDefault('file_priorities', priorities); this.form.optionsManager.setDefault('file_priorities', priorities);
this.form.optionsManager.changeId(oldId, true); this.form.optionsManager.changeId(oldId, true);
@ -91,23 +91,34 @@ Deluge.add.OptionsPanel = Ext.extend(Ext.TabPanel, {
this.torrentId = torrentId; this.torrentId = torrentId;
this.form.optionsManager.changeId(torrentId); this.form.optionsManager.changeId(torrentId);
this.files.clearFiles(); this.files.clearFiles();
var root = this.files.getRootNode(); var root = this.files.getRootNode();
var priorities = this.form.optionsManager.get('file_priorities'); var priorities = this.form.optionsManager.get('file_priorities');
this.walkFileTree(this.torrents[torrentId]['files_tree'], function(filename, type, entry, parentNode) { this.form.setDisabled(false);
var node = new Ext.tree.TreeNode({
download: (entry.index) ? priorities[entry.index] : true, if (this.torrents[torrentId]['files_tree']) {
filename: filename, this.walkFileTree(this.torrents[torrentId]['files_tree'], function(filename, type, entry, parentNode) {
fileindex: entry.index, var node = new Ext.tree.TreeNode({
leaf: type != 'dir', download: (entry.index) ? priorities[entry.index] : true,
size: entry.length filename: filename,
}); fileindex: entry.index,
parentNode.appendChild(node); leaf: type != 'dir',
if (type == 'dir') return node; size: entry.length
}, this, root); });
root.firstChild.expand(); parentNode.appendChild(node);
if (type == 'dir') return node;
}, this, root);
root.firstChild.expand();
this.files.setDisabled(false);
this.files.show();
} else {
// Files tab is empty so show options tab
this.form.show();
this.files.setDisabled(true);
}
}, },
walkFileTree: function(files, callback, scope, parentNode) { walkFileTree: function(files, callback, scope, parentNode) {
@ -120,7 +131,7 @@ Deluge.add.OptionsPanel = Ext.extend(Ext.TabPanel, {
} else { } else {
var ret = callback(filename, type, entry, parentNode); var ret = callback(filename, type, entry, parentNode);
} }
if (type == 'dir') this.walkFileTree(entry, callback, scope, ret); if (type == 'dir') this.walkFileTree(entry, callback, scope, ret);
} }
}, },
@ -142,7 +153,7 @@ Deluge.add.OptionsPanel = Ext.extend(Ext.TabPanel, {
}, this); }, this);
} else { } else {
this.files.setDownload(nodes[0], oldValue, true); this.files.setDownload(nodes[0], oldValue, true);
} }
}, },
scope: this, scope: this,
icon: Ext.MessageBox.QUESTION icon: Ext.MessageBox.QUESTION

View file

@ -81,17 +81,27 @@ Deluge.add.UrlWindow = Ext.extend(Deluge.add.Window, {
var cookies = this.cookieField.getValue(); var cookies = this.cookieField.getValue();
var torrentId = this.createTorrentId(); var torrentId = this.createTorrentId();
deluge.client.web.download_torrent_from_url(url, cookies, { if (url.substring(0,20) == 'magnet:?xt=urn:btih:') {
success: this.onDownload, deluge.client.web.get_magnet_info(url, {
scope: this, success: this.onGotInfo,
torrentId: torrentId scope: this,
}); filename: url,
torrentId: torrentId
});
} else {
deluge.client.web.download_torrent_from_url(url, cookies, {
success: this.onDownload,
scope: this,
torrentId: torrentId
});
}
this.hide(); this.hide();
this.urlField.setValue('');
this.fireEvent('beforeadd', torrentId, url); this.fireEvent('beforeadd', torrentId, url);
}, },
onDownload: function(filename, obj, resp, req) { onDownload: function(filename, obj, resp, req) {
this.urlField.setValue('');
deluge.client.web.get_torrent_info(filename, { deluge.client.web.get_torrent_info(filename, {
success: this.onGotInfo, success: this.onGotInfo,
scope: this, scope: this,

View file

@ -41,6 +41,7 @@ import logging
import hashlib import hashlib
import tempfile import tempfile
from urlparse import urljoin from urlparse import urljoin
from urllib import unquote_plus
from types import FunctionType from types import FunctionType
from twisted.internet import reactor from twisted.internet import reactor
@ -683,10 +684,8 @@ class WebApi(JSONComponent):
:: ::
{ {
"filename": the torrent file,
"name": the torrent name, "name": the torrent name,
"size": the total size of the torrent, "files_tree": the files the torrent contains,
"files": the files the torrent contains,
"info_hash" the torrents info_hash "info_hash" the torrents info_hash
} }
@ -699,6 +698,45 @@ class WebApi(JSONComponent):
log.exception(e) log.exception(e)
return False return False
@export
def get_magnet_info(self, uri):
"""
Return information about a magnet link.
:param uri: the magnet link
:type uri: string
:returns: information about the magnet link:
::
{
"name": the torrent name,
"info_hash": the torrents info_hash,
"files_tree": empty value for magnet links
}
:rtype: dictionary
"""
try:
s = uri.split("&")[0][20:]
if len(s) == 32:
info_hash = base64.b32decode(s).encode("hex")
elif len(s) == 40:
info_hash = s
else:
return False
name = None
for i in uri.split("&")[1:]:
if i[:3] == "dn=":
name = unquote_plus(i.split("=")[1])
if not name:
name = info_hash
return {"name":name, "info_hash":info_hash, "files_tree":''}
except Exception, e:
log.exception(e)
return False
@export @export
def add_torrents(self, torrents): def add_torrents(self, torrents):
""" """
@ -717,11 +755,16 @@ class WebApi(JSONComponent):
""" """
for torrent in torrents: for torrent in torrents:
filename = os.path.basename(torrent["path"]) if common.is_magnet(torrent["path"]):
fdump = base64.encodestring(open(torrent["path"], "rb").read()) log.info("Adding torrent from magnet uri `%s` with options `%r`",
log.info("Adding torrent from file `%s` with options `%r`", torrent["path"], torrent["options"])
filename, torrent["options"]) client.core.add_torrent_magnet(torrent["path"], torrent["options"])
client.core.add_torrent_file(filename, fdump, torrent["options"]) else:
filename = os.path.basename(torrent["path"])
fdump = base64.encodestring(open(torrent["path"], "rb").read())
log.info("Adding torrent from file `%s` with options `%r`",
filename, torrent["options"])
client.core.add_torrent_file(filename, fdump, torrent["options"])
return True return True
@export @export