API Docs for:
Show:

File: make_torrent.js

/**
 * Make a torrent file that contains a thing.
 * 
 * This program follows up on the 
 * <a href="http://my.brainshark.com/Distributed-Thing-Tracker-767853647">Distributed Thing Tracker</a>
 * proposal to use BitTorrent as a means to distribute things.
 * 
 * The process is quick and dirty, i.e. easy for me to code so you need to do all the work.
 * In brief:
 * <ul>
 * <li>Create a thing.</li>
 * <li>Create a torrent file with the thing files.</li>
 * <li>Merge them with this program.</li>
 * <li>Seed your torrent.</li>
 * <li>Publish the magnet link generated by this program.</li>
 * </ul>
 * 
 * More slowly now.
 * 
 * You need to create a design and put its metadata in a JSON format.
 * Making the actual design is beyond the scope of these instructions,
 * but it would be something like creating an <a href="http://www.openscad.org/">OpenSCAD</a>
 * or <a href="http://openjscad.org/">OpenJSCAD</a> file.
 * Once you have your design, you can create a JSON file with the
 * metadata that describes it. You can start from this template, but the
 * definitive source is the <a href="http://thingtracker.net/specification.html">Thing Tracker Network</a>.
 * 
      {
        "title": "Mechanical Movement #27",
        "url": "http://garyhodgson.github.com/githubiverse-tst",
        "author": "Gary Hodgson",
        "license": "GPL3",
        "tags": ["mechanical movement", "fun"],
        "thumbnailURL": "https://github.com/garyhodgson/githubiverse-tst/raw/master/img/test-jig.jpg",
        "description": "An implementation of movement #27 from &quot;501 Mechanical Movements&quot; by Henry T. Brown.\\n\\nThis is still a work in progress."
      }
 * 
 * Once you have a JSON file that has contents like the above and your design files
 * you have a "thing" and can proceed to make a "distributed thing" out of it.
 * 
 * You will need a way to create a .torrent file, which means a capable torrent client.
 * I suggest <a href="http://www.utorrent.com/">µTorrent</a>.
 * Do whatever is necessary with that tool to generate a .torrent file.
 * I'll describe what I did.
 * Push the nice friendly <a href="http://www.utorrent.com/">Get µTorrent</a> button.
 * Click the <a href="http://www.utorrent.com/downloads/complete/os/win">Free Download</a>
 * fine print link above the comparison chart.
 * Save the uTorrent.exe file.
 * Run the uTorrent.exe file by double clicking on it. This installs the µTorrent client
 * (for me it was Version 3.3 Build 29342). I installed it in directory
 * C:\Program Files (x86)\uTorrent and unchecked every option it offered except
 * "Add an exception for µTorrent in Windows Firewall" but you can choose other options.
 * The program starts up, or start it up by clicking on the <em>installed</em> 
 * uTorrent.exe (this one: C:\Program Files (x86)\uTorrent\uTorrent.exe).
 * Create a new torrent. From the File menu, choose Create New Torrent..., or hot-key CTRL-N.
 * Click the Add File button and select the design file (you could also add a directory of
 * files if there were more than one).
 * Remove all the tracker info from the Trackers text box.
 * Add a comment in the Comment field if you want.
 * Click the Create and save as... button and save the new .torrent file.
 * Click Yes to the dialog box that is displayed with the text:
 * "Please enter a valid tracker URL. Do you want to continue without having any trackers?"
 * 
 * You can check the contents of the .torrent file by uploading it to
 * <a href="http://www.tools4noobs.com/online_tools/torrent_decode/">Tools4noobs Torrent decode</a>.
 * 
 * The two pieces - the .json and the .torrent can now be merged by running this program.
 * This program requires <a href="http://nodejs.org/">node.js</a>, so you need to install it first.
 * After that, you should have commands "node" and "npm" (the node package manager) available.
 *
 * The program relies on two packages, namely
 * <a href="https://github.com/themasch/node-bencode">bencode</a>
 * and
 * <a href="https://github.com/pvorb/node-sha1">sha1</a>.
 * You can install these locally (i.e. in the directory you're working in -
 * the same one this file is in) with these commands:
 * 
       npm install bencode
       npm install sha1
 *
 * Now you can make a "thing". The command line is:
 * 
       node make_torrent.js thing.json thing.torrent output.torrent
 *
 * where:
 * <ul>
 * <li>thing.json is the metadata file you created from the template</li>
 * <li>thing.torrent is the original torrent file created by your BitTorrent client</li>
 * <li>output.torrent is the file you want to create</li>
 * </ul>
 * 
 * Besides creating the output file, which is a modified torrent file containing
 * the thing metadata, the program will also display a magnet link.
 * 
 * To seed your torrent, you need to put the file(s) that it comprises and
 * the generated torrent file in the directory configured for torrent seeding
 * (usually the same as the one for downloads), and then add the torrent
 * as an initial seed in your client. For the µTorrent client this found
 * of the File menu, Add Torrent... or CTRL-O. where you can select the generated
 * torrent file. This is somewhat confusing because it requires the directory
 * to save it - but apparently doesn't mind if this is the same directory.
 * 
 * Then you can send the magnet link to your geeky friends who can paste it into their
 * BitTorrent client and torrent your thing. For the µTorrent client, that latter
 * step is found on the File menu, Add Torrent from URL... or CTRL-U, where you can paste
 * the magnet link and begin the torrent process.
 * 
 * @module make_torrent
 **/

var bencode = require ('bencode');
var fs = require ('fs');
var sha1 = require ('sha1');

// need a byte array from a buffer
// why isn't this already defined?
Buffer.prototype.toByteArray = function ()
{
    return (Array.prototype.slice.call (this, 0));
}

// get the name of the JSON "thing" file
var thing = "thing.json";
if (null != process.argv[2])
    thing = process.argv[2];
else
    console.log ("Usage: node make_torrent.js thing.json thing.torrent output.torrent");

//get the name of the existing torrent file
var filename = "thing.torrent";
if (null != process.argv[3])
    filename = process.argv[3];

//get the name of the output torrent file
var output = "output.torrent";
if (null != process.argv[4])
    output = process.argv[4];

console.log ("Processing \"" + thing + "\" and \"" + filename + "\" to make \"" + output + "\"");
if (!fs.existsSync (thing))
    console.log (thing + " doesn't exist");
else if (!fs.existsSync (filename))
    console.log (filename + " doesn't exist");
else
{
    var data = JSON.parse (fs.readFileSync (thing));
    //console.log (JSON.stringify (data, null, 4));
    var title = data['title'];
    if (null == title)
    {
	var n = thing.lastIndexOf (".");
	if (-1 == n)
	    title = thing;
	else
	    title = thing.substring (0, n);
    }
    title = title.replace (/\&/g,"and");
    title = title.replace (/ /g, "%20");

    var file = fs.readFileSync (filename);
    var torrent = bencode.decode (file);
    //console.log (JSON.stringify (torrent, null, 4).substr (0, 1000));

    // add our thing data
    torrent['info']['thing'] = data;
    fs.writeFile (output, bencode.encode (torrent));
    
    // generate the 160 bit (40 hex characters) info primary key
    var info = torrent['info'];
    var primary_key = sha1 (bencode.encode (info).toByteArray ());

    // spew it out as a magnet link URI
    console.log ("magnet:?xt=urn:btih:" + primary_key + "&dn=" + title);
}