123 lines
4.6 KiB
Python
Executable File
123 lines
4.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import sys
|
|
import os
|
|
import os.path
|
|
import glob
|
|
from hashlib import sha1
|
|
from io import BytesIO
|
|
from torrentool.api import Torrent
|
|
|
|
"""
|
|
'announce_urls', 'comment', 'create_from', 'created_by', 'creation_date', 'files', 'from_file', 'from_string',
|
|
'get_magnet', 'httpseeds', 'info_hash', 'magnet_link', 'name', 'private', 'to_file', 'to_string', 'total_size',
|
|
'webseeds']
|
|
|
|
"""
|
|
|
|
ARG_OPTIONS = {'short': False, 'files': False, 'existing': False, 'non-existing': False, 'validate': False}
|
|
|
|
|
|
def make_blob(buffer, fileinfo):
|
|
if os.path.exists(fileinfo[0]):
|
|
with open(fileinfo[0], 'rb') as datafd:
|
|
num_written = buffer.write(datafd.read())
|
|
else:
|
|
num_written = buffer.write(b'\x00' * fileinfo[1])
|
|
return num_written
|
|
|
|
|
|
def parse_torrent_file(torrentfile):
|
|
buffer = BytesIO()
|
|
|
|
torrent = Torrent.from_file(torrentfile)
|
|
print('+- Torrent : {}'.format(os.path.basename(torrentfile)))
|
|
print('| Title : {}'.format(torrent.name))
|
|
info_struct = torrent._struct.get('info')
|
|
print('| Piece Len: {:,} Bytes'.format(info_struct['piece length']))
|
|
try:
|
|
print('| Size : {:,} Bytes'.format(torrent.total_size))
|
|
except:
|
|
print('| Size : {}'.format('n/a'))
|
|
if not ARG_OPTIONS['short']:
|
|
print('| Comment : {}'.format(torrent.comment or 'n/a'))
|
|
print('| Created : {}'.format(torrent.creation_date or 'n/a'))
|
|
print('| Hash : {}'.format(torrent.info_hash))
|
|
if torrent.comment:
|
|
print('| Comment : {}'.format(torrent.comment))
|
|
if len(torrent.httpseeds) > 0:
|
|
print('| httpseeds: {}'.format(torrent.httpseeds))
|
|
if len(torrent.webseeds) > 0:
|
|
print('| webseeds : {}'.format(torrent.webseeds))
|
|
if ARG_OPTIONS['files']:
|
|
# TODO: move to separate print file detail method
|
|
num_written = 0
|
|
for index, fileinfo in enumerate(torrent.files):
|
|
if ARG_OPTIONS['validate']:
|
|
num_written += make_blob(buffer, fileinfo)
|
|
if ARG_OPTIONS['existing']:
|
|
if os.path.exists(fileinfo[0]):
|
|
print('| FOUND [{:4}] name = {} (size = {:,} Bytes)'.format(index, fileinfo[0], fileinfo[1]))
|
|
elif ARG_OPTIONS['non-existing']:
|
|
print('| MISSING [{:4}] name = {} (size = {:,} Bytes)'.format(index, fileinfo[0], fileinfo[1]))
|
|
|
|
if ARG_OPTIONS['validate']:
|
|
pieceshash = info_struct['pieces']
|
|
buffer.seek(0)
|
|
print('| Validation:')
|
|
chunk_size = info_struct['piece length']
|
|
chunk = buffer.read(chunk_size)
|
|
chunk_hashes = []
|
|
while len(chunk) > 0:
|
|
hashcalc = sha1()
|
|
hashcalc.update(chunk)
|
|
chunk_hashes.append(hashcalc.digest())
|
|
chunk = buffer.read(chunk_size)
|
|
|
|
out_wrap = 0
|
|
completed = True
|
|
sys.stdout.write('| ')
|
|
for digest in chunk_hashes:
|
|
out_wrap += 1
|
|
if digest in pieceshash:
|
|
sys.stdout.write('▒')
|
|
else:
|
|
completed = False
|
|
sys.stdout.write('░')
|
|
if not(out_wrap % 64):
|
|
sys.stdout.write('\n| ')
|
|
sys.stdout.write('\n')
|
|
print('| Completed: {}'.format(completed))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
try:
|
|
for option in ARG_OPTIONS.keys():
|
|
if '--' + option in sys.argv:
|
|
ARG_OPTIONS[option] = not ARG_OPTIONS[option]
|
|
sys.argv.remove('--' + option)
|
|
if len(sys.argv) <= 1 or len(sys.argv) > 2:
|
|
raise IndexError
|
|
scan_path = sys.argv[-1]
|
|
if os.name == 'nt':
|
|
if not scan_path[-1] == '\\' and os.path.isdir(scan_path):
|
|
scan_path += '\\'
|
|
scan_path = scan_path.replace('\\', '\\')
|
|
else:
|
|
if not scan_path[-1] == '/' and os.path.isdir(scan_path):
|
|
scan_path += '/'
|
|
except IndexError:
|
|
print('Not enough parameters.\n Usage: {} [--short|--files] <directory|filename>'.format(sys.argv[0]))
|
|
sys.exit(1)
|
|
|
|
if os.path.isdir(scan_path):
|
|
for index, torrentfile in enumerate(glob.glob(scan_path + '*.torrent')):
|
|
parse_torrent_file(torrentfile)
|
|
try:
|
|
print('Found {} .torrent files.'.format(index+1))
|
|
except NameError:
|
|
print('No valid files found.')
|
|
sys.exit(1)
|
|
else:
|
|
parse_torrent_file(scan_path)
|