Всё в объекты. Добавлена зависимость от tinybt

master
Бородин Роман 2019-05-07 19:58:24 +03:00
parent d7f41a2f07
commit 1fcefa2195
2 changed files with 69 additions and 27 deletions

View File

@ -3,6 +3,7 @@
<requires>
<import addon="xbmc.python" version="2.25.0"/>
<import addon="script.module.torrent_parser" version="0.3.0"/>
<import addon="script.module.tinybt" version="0.9.0"/>
</requires>
<extension point="xbmc.python.module" library="lib"/>
<extension point="xbmc.addon.metadata">

View File

@ -1,6 +1,8 @@
import torrent_parser as tp
import threading
from math import ceil
from hashlib import sha1
from datetime import datetime
BUFFER_SIZE = 10 * 1024 * 1024
@ -55,35 +57,74 @@ class Buffer(object):
return []
class Piece(object):
def __init__(self, p_index, p_hash, payload):
self.index = p_index
def __init__(self, p_hash, payload=b''):
self.hash = p_hash
self.payload = payload
self.exist = False
class PieceRange(object):
def __init__(self, first_piece, first_piece_offset, last_piece, last_piece_size):
self.first = first_piece
self.first_offset = first_piece_offset
self.last = last_piece
self.last_size = last_piece_size
class TFile(object):
def __init__(self, path, length, piece_range):
self.path = path
self.name = path[-1]
self.length = length
self.pieace_range = piece_range
class Tracker(object):
def __init__(self, url):
self.url = url
self.next_announce = datetime.now()
self.reachable = True
@property
def can_announce(self):
return self.next_announce <= datetime.now() and self.reachable
class Info(object):
def __init__(self, info, trackers):
trackers = list(set(trackers))
self.hash = sha1(tp.BEncoder(info).encode()).hexdigest()
self.files = []
self.trackers = list(map(Tracker, trackers))
self.pieces = list(map(Piece, info['pieces']))
self.piece_length = info['piece length']
def piece_range_gen(start, next_at):
first_piece = start // self.piece_length
first_piece_offset = start % self.piece_length
tail = next_at % self.piece_length
last_piece = next_at // self.piece_length - int(not bool(tail))
last_piece_size = self.piece_length if not tail else tail
return PieceRange(first_piece, first_piece_offset, last_piece, last_piece_size)
if 'files' in info:
addr_ptr = 0
for i in range(len(info['files'])):
f = info['files'][i]
next_at = addr_ptr + f['length']
pr = piece_range_gen(addr_ptr, next_at)
self.files.append(TFile(info['name'] + f['path'], f['length'], pr))
addr_ptr += f['length']
else:
pr = piece_range_gen(0, info['length'])
self.files.append(TFile([info['name']], info['length'], pr))
class Pyrrent(object):
multifile = False
shuttingdown = False
downloaded = 0
uploaded = 0
tracker_responce = {}
tracker_responce_ver = 0
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)]
data = tp.parse_torrent_file(filepath)
self.info = Info(data['info'], [data['announce']] + data['announce-list'] if 'announce-list' in data else [])
def tracker_anouncer(self):
self.tracker_responce_ver += 1
for i in range(len(self.info.trackers)):
tracker = self.info.trackers[i]
if tracker.can_announce:
thr = threading.Thread(target=self.announce, args=(tracker, i))
thr.start()
def announce(self, tracker, index):
pass