种子批量转磁链-javascript实现

Torrent

历史

该技术由美国的程序员布莱姆·科亨于2001年4月时发布,并于2001年7月2日时首次正式应用。

原理

普通的HTTP/FTP下载使用TCP/IP协议,BitTorrent协议是架构于TCP/IP协议之上的一个P2P文件传输通信协议,处于TCP/IP结构的应用层。
根据BitTorrent协议,文件发布者会根据要发布的文件生成提供一个.torrent文件,即种子文件,也简称为“种子”。

组成

种子文件本质是文本文件,包括Tracker和文件信息两个部分:
Tracker服务器保存所有正在下载文件的客户端的地址,有人新建连接时,会将地址反馈给新的连接。
文件信息是用Bencode进行编码,是要下载的文件的索引。

Tracker信息
  • Tracker服务器地址
  • Tracker服务器设置
文件信息
  • announce - tracker的URL
  • info - 该条映射到一个字典,该字典的键将取决于共享的一个或多个文件
    • name - 建议保存到的文件和目录名称
    • piece length - 每个文件块的字节数。通常为256KB = 262144B
    • pieces - 每个文件块的SHA-1的集成Hash。因为SHA-1会返回160-bit的Hash,所以pieces将会得到1个160-bit的整数倍的字符串。和一个length(相当于只有一个文件正在共享)或files(相当于当多个文件被共享):
    • length - 文件的大小(以字节为单位)
    • files - 一个字典的列表(每个字典对应一个文件)与以下的键
      • path - 一个对应子目录名的字符串列表,最后一项是实际的文件名称
      • length - 文件的大小(以字节为单位)

info-hash:每一个种子唯一的编码,由info字段的数据计算而成。

DHT网络

DHT全称为分布式哈希表(Distributed Hash Table),是一种分布式存储方法。在不需要服务器的情况下,每个客户端负责一个小范围的路由,并负责存储一小部分数据,从而实现整个DHT网络的寻址和存储。

磁链

历史

这个标准的草稿出现于2002年,是为了对eDonkey2000的“ed2k:”和Freenet的“freenet:”两个URI格式进行“厂商与项目中立化”(vendor- and project-neutral generalization)而制定的。同时这个标准也尝试紧密地跟进IETF官方的URI标准。

原理

特点:

  • 分布式。
  • 不依赖于ip地址
  • 没有中心服务器
  • 开源

组成

磁力链接由一组参数组成,参数间的顺序没有讲究,其格式与在HTTP链接末尾的查询字符串相同。最常见的参数是"xt",是"exact topic"的缩写,通常是一个特定文件的内容散列函数值形成的URN。

magnet:?xt=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C

其值是Base32编码的文件的SHA-1散列。

基本描述

magnet:? xl = [字节大小]& dn = [文件名(已编码URL)]& xt = urn: tree: tiger: [ TTH hash(Base32)]

由参数来指定相关的内容:

  • dn(显示名称)- 文件名
  • xl(绝对长度)- 文件字节数
  • xt(eXact Topic)- 包含文件散列函数值的URN。磁力链接的这部分最重要。用于寻找和验证包含着磁力链接中的文件。
  • as(可接受来源) - 在线文件的网络链接
  • xs(绝对资源)- P2P链接
  • kt(关键字)- 用于搜索的关键字
  • mt(文件列表)- 链接到一个包含磁力链接的元文件 (MAGMA - MAGnet MAnifest)
  • tr(Tracker地址)- BT下载的Tracker URL
  • btih(BitTorrent Info Hash):种子的info_hash,转换磁链时就是计算它

开发工具和平台

计算提取info_hash

关键:info字段的值,必须先解码,再对info字段的值编码,然后才计算hash。直接从文件中删除其他部分行不通。

js

bencode库

npm install bencode

如果装了nvm,则-g全局安装会装在.nvm文件夹下。否则,就装在用户目录的node_module下。

sha-1库

npm install js-sha1

实现代码

输出

提取的磁力链接存放在种子目录下名为magnets.txt的文件中

使用
node t2m.js <种子文件夹路径>
js代码
var fs = require("fs");
var bencode = require('bencode');
var sha1 = require('js-sha1');
var arguments = process.argv.splice(2); //获取命令行参数,第三个元素是带的参数

outMagnets(getMagnets(arguments), arguments);

// 获取磁链链接,arguments为文件夹路径
function getMagnets(arguments) {
    var fileslist = fs.readdirSync(arguments.toString());
    var magnetlist = new Array();

    for (var f in fileslist) {
        var torrentfile = null;
        var filename = fileslist[f].toString();
        if (filename.includes(".torrent")) {
            var filepath = arguments.toString() + '/' + filename;
            var magnet = getInfoHash(filepath);
            if (magnet) {
                magnetlist.push(magnet);
            }
            //console.log(magnet);
        }
    }
    return magnetlist;
}

// 将结果输出为txt
function outMagnets(magnets, path) {
    if (magnets.length > 0) {
        var writebuffer = Buffer.from(arrayToString(magnets, '\n'));
        var savepath = path.toString() + '/' + "magnets.txt";
        var writesteam = fs.createWriteStream(savepath);
        writesteam.write(writebuffer, 'utf-8');
        writesteam.end();
        writesteam.on('finish', function () {
            console.log("写入完成");
        });
        writesteam.on('error', function (err) {
            console.log(err);
        });
    }
}

// buffer只能输出字符,所以必须将字符数组转换为字符形式,seq为分隔符
function arrayToString(arr, seq) {
    var str_value = null;
    for (a of arr) {
        var astr = a.toString();
        if (str_value) {
            str_value = str_value + seq + astr;
        } else {
            str_value = astr;
        }
    }
    return str_value;
}
// 获取种子文件的info_hash值,有一个解密,再加密的过程
function getInfoHash(torrentfile) {
    var result = bencode.decode(fs.readFileSync(torrentfile));
    if (result) {
        var info = result['info']; //info 字典
        var info_hash = sha1(bencode.encode(info));
        var magnet = "magnet:?xt=urn:btih:" + info_hash.toString();
        return magnet;
    } else {
        return null;
    }
}

python

bencode库

gittub
安装:

pip3 install py3-bencode

实现代码

from bencode import bencode, bdecode
from io import BytesIO
import hashlib

objTorrentFile = open("test.torrent", "rb")
decodedDict = bdecode(objTorrentFile.read())

info_hash = hashlib.sha1(bencode(decodedDict["info"])).hexdigest()
print(info_hash)

在解码提取出info后,似乎还需要编码后,再求hash值

参考网址

磁力链接wiki
磁力链接转换为种子文件
官方种子格式说明
种子格式详解
bencode详解
python bencode可用
bencode-gitthub
bencode源码
js-bencode 实现
wiki-bencode

你可能感兴趣的:(种子批量转磁链-javascript实现)