Advertisement
nanogyth

CLI torrent

Jan 3rd, 2013
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.65 KB | None | 0 0
  1. '''
  2. Usage:
  3.  torrent.py [options] <file> [--url_list <url>...]
  4.  torrent.py -h | --help
  5.  
  6.  -t, --tracker <url>     Tracker address
  7.  [default: udp://tracker.openbittorrent.com:80/announce]
  8.  -u, --url_list <url>    GetRight webseeds
  9.  -p, --min_pieces <min>  [default: 1]
  10.  -P, --max_pieces <max>  [default: 0]
  11.  -l, --min_length <min>  [default: 16]
  12.  -L, --max_length <max>  [default: 0]
  13.  -h, --help              Help file
  14.  
  15.  The lengths need to be a multiple of 16 since that is the smallest
  16.  unit torrent transports.
  17.  
  18.  This is my hack at Robert Nitsch's code to get a command line
  19.  torrenter that I can use. I've added webseed support, docopt,
  20.  progress, and some piece/length control.
  21.  
  22. http://www.robertnitsch.de/projects:py3createtorrent
  23. '''
  24. from py3bencode import bencode
  25. from docopt import docopt
  26. import os, hashlib, sys, requests
  27.  
  28. def auto_length(length, min_p, max_p, min_l, max_l):
  29.     assert length > 0
  30.     piece_length = 2**((length.bit_length()+8)//2)
  31.     pieces = length / piece_length
  32.     assert min_p >= 1
  33.     while pieces < min_p:
  34.         piece_length /= 2
  35.         pieces *= 2
  36.     if max_p > 0:
  37.         while pieces > max_p:
  38.             piece_length *= 2
  39.             pieces /= 2
  40.     assert min_l >= 16384
  41.     assert min_l % 16384 == 0
  42.     assert max_l % 16384 == 0
  43.     if piece_length < min_l:
  44.         piece_length = min_l
  45.     if max_l > 0 and piece_length > max_l:
  46.         piece_length = max_l
  47.     return piece_length
  48.    
  49. def torrent_dict(announce, file, url_list, min_p, max_p, min_l, max_l):
  50.     name = os.path.basename(file)
  51.     length = os.path.getsize(file)
  52.     piece_length = auto_length(length, min_p, max_p, min_l, max_l)
  53.     pieces = bytearray()
  54.     num = length // piece_length + 1
  55.     with open(file, 'rb') as f:
  56.         i = 0
  57.         print('Hashing ... ')
  58.         for piece in iter((lambda:f.read(piece_length)),b''):
  59.             pieces += hashlib.sha1(piece).digest()
  60.             i += 1
  61.             sys.stdout.write('\r{}/{}'.format(i,num))
  62.     d = {
  63.         'announce': announce,
  64.         'info':
  65.         {
  66.             'name': name,
  67.             'length': length,
  68.             'piece length': piece_length,
  69.             'pieces': pieces
  70.         }
  71.     }
  72.     if url_list:
  73.         if len(url_list) is 1:
  74.             d['url-list'] = url_list[0]
  75.         else:
  76.             d['url-list'] = url_list
  77.     return d
  78.  
  79. def torrent_bencode(a, f, u, p, P, l, L):
  80.     return bencode(torrent_dict(a, f, u, p, P, l, L))
  81.    
  82. def write_torrent(a, f, u, p=1, P=0, l=16384, L=0):
  83.     with open(f + '.torrent', 'wb') as file:
  84.         file.write(bencode(torrent_dict(a, f, u, p, P, l, L)))
  85.  
  86. def try_int(s, default):
  87.     try:
  88.         i = int(s)
  89.     except ValueError:
  90.         print('[warning] pieces and length must be integers, using default values')
  91.         i = default
  92.     return i
  93.    
  94. def try_file(f):
  95.     if os.path.isfile(f):
  96.         return os.path.abspath(f)
  97.     else:
  98.         sys.exit("[error] '{}' isn't a file".format(f))
  99.                
  100. def try_url(u):
  101.     try:
  102.         r = requests.head(u.strip())
  103.         r.raise_for_status()
  104.     except Exception as e:
  105.         print("[warning] url '{}' had an error: {}".format(u, e))
  106.        
  107. if __name__ == '__main__':
  108.     arguments = docopt(__doc__)
  109.     announce = arguments['--tracker']
  110.     file = try_file(arguments['<file>'])
  111.     url_list = arguments['--url_list']
  112.     min_p = try_int(arguments['--min_pieces'], 1)
  113.     max_p = try_int(arguments['--max_pieces'], 0)
  114.     min_l = try_int(arguments['--min_length'], 16) * 1024
  115.     max_l = try_int(arguments['--max_length'], 0) * 1024
  116.     write_torrent(announce, file, url_list, min_p, max_p, min_l, max_l)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement