script.module.pyrrent/lib/pyrrent.py

90 lines
2.9 KiB
Python

import torrent_parser as tp
import threading
from math import ceil
BUFFER_SIZE = 10 * 1024 * 1024
class Cron(object):
alive = False
def __init__(self, interval, func, *a, **kw):
self.interval = interval
self.func = func
self.a = a
self.kw = kw
self.ticker = threading.Event()
def start(self):
self.t = threading.Thread(target=self.run)
self.alive = True
self.t.start()
def run(self):
while self.alive and not self.ticker.wait(self.interval):
self.func(*self.a, **self.kw)
def stop(self):
self.alive = False
class Buffer(object):
def __init__(self, piece_size):
self.buf_reset_pending = False
self.buf_changed = threading.Event()
self.size = ceil(BUFFER_SIZE / piece_size)
self.buf = []
def buf_changed_event(self):
self.buf_changed.set()
self.buf_changed.clear()
def put(self, piece):
if not self.buf_reset_pending:
self.buf.append(piece)
self.buf_changed_event()
return True
else:
return False
def get(self):
if not self.buf_reset_pending:
if len(self.buf):
return self.buf.pop(0)
return None
def reset(self):
self.buf_reset_pending = True
self.buf = []
self.buf_reset_pending = False
self.buf_changed_event()
def pieces(self):
if not self.buf_reset_pending:
return list(map(lambda x: (x.index, x.hash), self.buf))
else:
return []
class Piece(object):
def __init__(self, p_index, p_hash, payload):
self.index = p_index
self.hash = p_hash
self.payload = payload
class Pyrrent(object):
multifile = False
def __init__(self, filepath):
self.data = tp.parse_torrent_file(filepath)
self.piece_length = self.data['info']['piece length']
self.buffer = Buffer(self.piece_length)
self.pieces = self.data['info']['pieces']
if 'files' in self.data['info'].keys():
self.multifile = True
if not self.multifile:
self.file_addresses = [(0, self.piece_length)]
else:
self.file_addresses = []
addr_ptr = 0
for length in map(lambda x: x['length'], self.data['info']['files']):
next_at = addr_ptr + length
self.file_addresses.append((addr_ptr, next_at))
addr_ptr += length
def piece_range(self, f_index):
start, next_at = self.file_addresses[f_index]
start_piece = start // self.piece_length
start_byte = start % self.piece_length
tail = next_at % self.piece_length
end_piece = next_at // self.piece_length - int(not bool(tail))
end_byte = self.piece_length if not tail else tail
return [(start_piece, start_byte),(end_piece, end_byte)]