Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Libtorrent - Given a magnet link, how do you generate a torrent file?

Tags:

I have read through the manual and I cannot find the answer. Given a magnet link I would like to generate a torrent file so that it can be loaded on the next startup to avoid redownloading the metadata. I have tried the fast resume feature, but I still have to fetch meta data when I do it and that can take quite a bit of time. Examples that I have seen are for creating torrent files for a new torrent, where as I would like to create one matching a magnet uri.

like image 566
ciferkey Avatar asked Dec 31 '11 18:12

ciferkey


People also ask

How do you torrent with a magnet link?

Using a magnet link is as simple as clicking the link on a web page. If you have a magnet link capable BitTorrent client installed, your web browser should prompt you to open the magnet link in your torrent client. You can also copy and paste the link into BitTorrent clients that have an address bar for that purpose.

How do I extract a magnet link?

Step 1: Open the uTorrent application on your device and click the “Add Torrent +” button. Step 2: Copy and paste the magnet link to the pop-up window to add magnet link to uTorrent. Then click “Add torrent”. Step 3: Select the exact files which you want to download from the magnet link.


2 Answers

Solution found here:

http://code.google.com/p/libtorrent/issues/detail?id=165#c5

See creating torrent:

http://www.rasterbar.com/products/libtorrent/make_torrent.html

Modify first lines:

file_storage fs;

// recursively adds files in directories
add_files(fs, "./my_torrent");

create_torrent t(fs);

To this:

torrent_info ti = handle.get_torrent_info()

create_torrent t(ti)

"handle" is from here:

torrent_handle add_magnet_uri(session& ses, std::string const& uri add_torrent_params p);

Also before creating torrent you have to make sure that metadata has been downloaded, do this by calling handle.has_metadata().

UPDATE

Seems like libtorrent python api is missing some of important c++ api that is required to create torrent from magnets, the example above won't work in python cause create_torrent python class does not accept torrent_info as parameter (c++ has it available).

So I tried it another way, but also encountered a brick wall that makes it impossible, here is the code:

if handle.has_metadata():

    torinfo = handle.get_torrent_info()

    fs = libtorrent.file_storage()
    for file in torinfo.files():
        fs.add_file(file)

    torfile = libtorrent.create_torrent(fs)
    torfile.set_comment(torinfo.comment())
    torfile.set_creator(torinfo.creator())

    for i in xrange(0, torinfo.num_pieces()):
        hash = torinfo.hash_for_piece(i)
        torfile.set_hash(i, hash)

    for url_seed in torinfo.url_seeds():
        torfile.add_url_seed(url_seed)

    for http_seed in torinfo.http_seeds():
        torfile.add_http_seed(http_seed)

    for node in torinfo.nodes():
        torfile.add_node(node)

    for tracker in torinfo.trackers():
        torfile.add_tracker(tracker)

    torfile.set_priv(torinfo.priv())

    f = open(magnet_torrent, "wb")
    f.write(libtorrent.bencode(torfile.generate()))
    f.close()

There is an error thrown on this line:

torfile.set_hash(i, hash)

It expects hash to be const char* but torrent_info.hash_for_piece(int) returns class big_number which has no api to convert it back to const char*.

When I find some time I will report this missing api bug to libtorrent developers, as currently it is impossible to create a .torrent file from a magnet uri when using python bindings.

torrent_info.orig_files() is also missing in python bindings, I'm not sure whether torrent_info.files() is sufficient.

UPDATE 2

I've created an issue on this, see it here: http://code.google.com/p/libtorrent/issues/detail?id=294

Star it so they fix it fast.

UPDATE 3

It is fixed now, there is a 0.16.0 release. Binaries for windows are also available.

like image 95
Czarek Tomczak Avatar answered Oct 26 '22 20:10

Czarek Tomczak


Just wanted to provide a quick update using the modern libtorrent Python package: libtorrent now has the parse_magnet_uri method which you can use to generate a torrent handle:

import libtorrent, os, time

def magnet_to_torrent(magnet_uri, dst):
    """
    Args:
        magnet_uri (str): magnet link to convert to torrent file
        dst (str): path to the destination folder where the torrent will be saved
    """
    # Parse magnet URI parameters
    params = libtorrent.parse_magnet_uri(magnet_uri)

    # Download torrent info
    session = libtorrent.session()
    handle = session.add_torrent(params)
    print "Downloading metadata..."
    while not handle.has_metadata():
        time.sleep(0.1)

    # Create torrent and save to file
    torrent_info = handle.get_torrent_info()
    torrent_file = libtorrent.create_torrent(torrent_info)
    torrent_path = os.path.join(dst, torrent_info.name() + ".torrent")
    with open(torrent_path, "wb") as f:
        f.write(libtorrent.bencode(torrent_file.generate()))
    print "Torrent saved to %s" % torrent_path
like image 25
Régis B. Avatar answered Oct 26 '22 18:10

Régis B.