Всё в объекты. Добавлена зависимость от tinybt
parent
d7f41a2f07
commit
1fcefa2195
|
@ -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">
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue