diff --git a/addon.xml b/addon.xml
index 578547d..6f8017f 100644
--- a/addon.xml
+++ b/addon.xml
@@ -3,6 +3,7 @@
+
diff --git a/lib/pyrrent.py b/lib/pyrrent.py
index eb8866b..bfc3aa2 100644
--- a/lib/pyrrent.py
+++ b/lib/pyrrent.py
@@ -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