Skip to content

Instantly share code, notes, and snippets.

@Burgestrand
Created February 3, 2012 23:20
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save Burgestrand/1733611 to your computer and use it in GitHub Desktop.
Save Burgestrand/1733611 to your computer and use it in GitHub Desktop.
A ruby script to construct magnet links out of .torrent files

Magneto

It reads your torrents. Spit out magnet URIs.

Example Usage

$ ./magneto.rb magneto.rb.torrent

Results in:

[WARN] There are no trackers on the torrent. It’s recommended you add at least one.
       Here are a few public free trackers that don’t require registration:

         udp://tracker.publicbt.com:80/announce
         udp://tracker.openbittorrent.com:80/announce

Magnet URI for magneto.rb:
  magnet:?xt=urn:btih:W7TTABVNI4AADW3MWLMKWF32WVY7XE7P&dn=magneto.rb
#!/usr/bin/env ruby
# coding: utf-8
require 'rubygems'
require 'cgi'
require 'openssl'
def require_gem(name)
require(name)
rescue LoadError
abort "[ERROR] Missing the '#{name}' gem, install it with 'gem install #{name}'"
end
require_gem 'bencode'
require_gem 'base32'
require_gem 'rack/utils'
# We cannot trust .torrent file data
ARGF.set_encoding 'BINARY'
# Read torrent from STDIN / ARGV filepath
torrent_data = ARGF.read
# Parse the torrent data
torrent = BEncode.load(torrent_data)
# Calculate the info_hash (actually, info_sha1 *is* the info_hash)
info_hash = torrent["info"].bencode
info_sha1 = OpenSSL::Digest::SHA1.digest(info_hash)
# Build the magnet link
params = {}
params[:xt] = "urn:btih:" << Base32.encode(info_sha1)
params[:dn] = CGI.escape(torrent["info"]["name"])
Array(torrent["announce-list"]).each do |(tracker, _)|
params[:tr] ||= []
params[:tr] << tracker
end
unless params[:tr]
puts "[WARN] There are no trackers on the torrent. It’s recommended you add at least one."
puts " Here are a few public free trackers that don’t require registration:"
puts
puts " udp://tracker.publicbt.com:80/announce"
puts " udp://tracker.openbittorrent.com:80/announce"
puts
end
# params[:tr] = [] << to complement DHT we can add trackers too
magnet_uri = "magnet:?xt=#{params.delete(:xt)}"
magnet_uri << "&" << Rack::Utils.build_query(params)
puts "Magnet URI for #{params[:dn]}:"
puts " #{magnet_uri}"
@jcldavid
Copy link

How do you do it the other way around?

@Burgestrand
Copy link
Author

@Apathetic012 You mean create torrents from magnet URIs? You can’t, not with the information you have in the magnet link alone. The magnet link allows bit torrent clients to find other peers that have the .torrent, which is then downloaded from them.

@jikkujose
Copy link

I understand that the information isn't get back the torrent file, but isn't there a way to download torrent using command line using the magnet link?

@colindean
Copy link

@jikkujose It's been a long time since you asked but since I came across this gist today, I thought I'd share for others:

aria2c can download magnet links. See the docs here.

@jikkujose
Copy link

Thanks! That will help others too!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment