def __init__(self, torrent_file): with open(torrent_file, 'rb') as f: self.torrent_file = f.read() self.meta_info_dict = bdecode(self.torrent_file) self.announce = self.meta_info_dict[b'announce'].decode('utf-8') self.info_dict = self.meta_info_dict[b'info'] self.bencoded_info_dict = self.info_dict['ben_string'] self.filename = self.info_dict[b'name'].decode('utf-8') self.path = 'torrents_in_progress' self.info_hash = sha1(self.bencoded_info_dict).digest() self.peer_id = '-'.join(['','TZ', '0000', str(randrange(10000000000,99999999999))]) self.ip = self.get_IP_address() self.port = '6881' #TODO: Try ports in range (6881,6889) self.length = int(self.info_dict[b'length']) if b'length' in self.info_dict \ else sum([int((f[b'length'])) for f in self.info_dict[b'files']]) self.piece_length = int(self.info_dict[b'piece length']) self.pieces = self.info_dict[b'pieces'] self.piece_hashes = [self.pieces[i:i+20] for i in range(0, len(self.pieces), 20)] self.number_of_pieces = ceil(self.length/self.piece_length) self.downloaded = 0 self.uploaded = 0 self.have = [False] * self.number_of_pieces #TODO: pass torrent class a bitfield and handle restarting torrents self.complete = False #TODO: Update when self.pieces_needed is empty self.io_loop = get_event_loop() self.pieces_needed = []
def __init__(self, torrent_file): with open(torrent_file, 'rb') as f: self.torrent_file = f.read() self.meta_info_dict = bdecode(self.torrent_file) self.announce = self.meta_info_dict[b'announce'].decode('utf-8') self.info_dict = self.meta_info_dict[b'info'] self.bencoded_info_dict = self.info_dict['ben_string'] self.filename = self.info_dict[b'name'].decode('utf-8') self.path = 'torrents_in_progress' self.info_hash = sha1(self.bencoded_info_dict).digest() self.peer_id = '-'.join( ['', 'TZ', '0000', str(randrange(10000000000, 99999999999))]) self.ip = self.get_IP_address() self.port = '6881' #TODO: Try ports in range (6881,6889) self.length = int(self.info_dict[b'length']) if b'length' in self.info_dict \ else sum([int((f[b'length'])) for f in self.info_dict[b'files']]) self.piece_length = int(self.info_dict[b'piece length']) self.pieces = self.info_dict[b'pieces'] self.piece_hashes = [ self.pieces[i:i + 20] for i in range(0, len(self.pieces), 20) ] self.number_of_pieces = ceil(self.length / self.piece_length) self.downloaded = 0 self.uploaded = 0 self.have = [ False ] * self.number_of_pieces #TODO: pass torrent class a bitfield and handle restarting torrents self.complete = False #TODO: Update when self.pieces_needed is empty self.io_loop = get_event_loop() self.pieces_needed = []
def hash(filename): for file_fuck in filename: torrent_file = f'{torrent_folder}{file_fuck}' objTorrentFile = open(torrent_file, 'rb') decodedDict = bencoding.bdecode(objTorrentFile.read()) objTorrentFile.close() info_hash = hashlib.sha1(bencoding.bencode( decodedDict[b"info"])).hexdigest() list2.append(f'{info_hash}==>{torrent_file}')
def read_metainfo(filepath): with open(filepath, 'rb') as f: metainfo = bencoding.bdecode(f.read()) if metainfo is None: raise Exception("Metainfo read failed.") encoding = metainfo[b"encoding"] if b"encoding" in metainfo else b"utf-8" announce = meta_decode(metainfo[b"announce"], encoding) creation_date = meta_decode(metainfo[b"creation date"], encoding) \ if b"creation data" in metainfo else None creator = meta_decode(metainfo[b"created by"], encoding) \ if b"created by" in metainfo else None comment = meta_decode(metainfo[b"comment"], encoding) \ if b"comment" in metainfo else None announce_list = meta_decode(metainfo[b"announce-list"], encoding) \ if b"announce-list" in metainfo else None piece_length = meta_decode(metainfo[b"info"][b"piece length"], encoding) pieces = metainfo[b"info"][b"pieces"] private = meta_decode(metainfo[b"info"][b"private"], encoding) \ if b"private" in metainfo[b"info"] else 0 single_file_mode = b"files" not in metainfo[b"info"] name = meta_decode(metainfo[b"info"][b"name"], encoding) files = [] if single_file_mode: tfile = {"length": meta_decode(metainfo[b"info"][b"length"], encoding), "md5sum": meta_decode(metainfo[b"info"][b"md5sum"], encoding) \ if b"md5sum" in metainfo[b"info"] else None, "path": None} files.append(tfile) else: for tf in metainfo[b"info"][b"files"]: tfile = {"length": meta_decode(tf[b"length"], encoding), "md5sum": meta_decode(tf[b"md5sum"], encoding) \ if b"md5sum" in tf else None, "path": meta_decode(tf[b"path"], encoding)} files.append(tfile) return { "announce": announce, "cdate": creation_date, "creator": creator, "comment": comment, "announce_list": announce_list, "single_file": single_file_mode, "piece_length": piece_length, "pieces": pieces, "private": private, "name": name, "files": files }
def is_torrent_file(cls, torrent_file_path): if not torrent_file_path.is_file(): return False with open(torrent_file_path, 'rb') as f: try: data = bdecode(f.read()) if data.get(b'info'): return True except DecoderError: return False return False
async def get_peers(self, numwant=100): """ # TODO Separate out metadata parsing and HTTP client implementation HTTP(S) Tracker client implementation :param numwant: required number of peers """ peer_id = 'SA' + ''.join( random.choice(string.ascii_lowercase + string.digits) for _ in range(18)) params = { 'info_hash': self.info_hash, 'peer_id': peer_id, 'port': 6881, 'uploaded': 0, 'downloaded': 0, 'left': self._total_length, 'compact': 1, 'no_peer_id': 1, 'event': 'started', 'numwant': numwant } for url in self._trackers: if b'udp' not in url: try: print(url) r = requests.get(url, params=params, timeout=10) except Exception as e: print("Exception occurred for {}\n{}".format(url, e)) continue resp = bencoding.bdecode(r.content) print(r.status_code, r.reason) peers = resp[b'peers'] start = 0 if isinstance(peers, list): self.peers = peers elif len(peers) % 6 == 0: while start < len(peers): ip = peers[start:start + 4] ip = socket.inet_ntoa(ip) port = peers[start + 4:start + 6] port, = struct.unpack('!H', port) self.peers.append((ip, port)) start += 6 else: try: print(url) udp_peers = await self.udp_tracker_client(url.decode()) self.peers.extend(udp_peers) except Exception as e: print("Exception occurred for {}\n{}".format(url, e)) continue
def sendAnnounce(event = ""): global announce_delay, announce_count announce_count += 1 announce_params["event"] = event if (announce_params["event"] == ""): del announce_params["event"] r = requests.get(announce_url, params=announce_params, headers=announce_headers) body_decode = bencoding.bdecode(r.content) if (b'interval' in body_decode): announce_delay = int(body_decode[b'interval']) print("%s announce %02i" % (timestamp(), announce_count), end="") if ("event" in announce_params): print(" " + announce_params["event"], end="") print(" uploaded: %i/%iMB, downloaded: %i/%iMB" % (announce_params["uploaded"]/1024/1024, max_upload/1024/1024, announce_params["downloaded"]/1024/1024, max_down/1024/1024), end="") print(", delay %im%is" % (announce_delay//60, announce_delay%60))
def add_torrent(self, torrent): with open(torrent, "rb") as file: data = bdecode(file.read()) info = data[b"info"] hash = sha1(bencode(info)).hexdigest() if hash in self.torrent_hashes or []: raise TorrentAlreadyPresentException(hash) with open(torrent, "rb") as file: filedump = encodestring(file.read()) filename = basename(torrent) result = self.client.call("core.add_torrent_file", filename, filedump, {}) logger.debug("Returning {}", result.decode("utf-8")) if result.decode("utf-8") != hash: raise Exception(result.decode("utf-8")) self._torrent_hashes = None return True
def add_torrent(self, torrent): with open(torrent, "rb") as file: data = bdecode(file.read()) info = data[b"info"] hash = sha1(bencode(info)).hexdigest() if hash in self.torrent_hashes: raise TorrentAlreadyPresentInCollectionException(hash) host = min(self.hosts, key=lambda host: host.torrent_count) if host.torrent_count >= self.max_torrents: raise AllDelugeHostsInCollectionFullException() if host.add_torrent(torrent): logger.success("Added {} to {}", torrent, host.display) self._torrent_hashes = None return True return False
def add_from_file(update: Update, context: CallbackContext): logger.info('application/x-bittorrent document from %s', update.effective_user.first_name) document = update.message.document if document.mime_type != "application/x-bittorrent" and not document.file_name.lower( ).endswith(".torrent"): logger.info('invalid document from %s (mime type: %s; file name: %s)', update.effective_user.full_name, document.mime_type, document.file_name) update.message.reply_markdown( 'Please send me a valid torrent file (`.torrent` extension or `application/x-bittorrent` mime type)', quote=True) return file_id = document.file_id torrent_file = context.bot.get_file(file_id) file_path = './downloads/{}'.format(document.file_name) torrent_file.download(file_path) kwargs = get_qbt_request_kwargs() with open(file_path, 'rb') as f: # https://stackoverflow.com/a/46270711 decoded_dict = bencoding.bdecode(f.read()) torrent_hash = hashlib.sha1(bencoding.bencode( decoded_dict[b"info"])).hexdigest() f.seek(0) # this method always returns an empty json: # https://python-qbittorrent.readthedocs.io/en/latest/modules/api.html#qbittorrent.client.Client.download_from_file qb.download_from_file(f, **kwargs) update.message.reply_text('Torrent added', quote=True, reply_markup=kb.short_markup(torrent_hash)) os.remove(file_path) notify_addition(update.effective_chat.id, context.bot, update.effective_user, document.file_name or "[unknown file name]")
def __init__(self, torrent_file): self.torrent_data = bencoding.bdecode(open(torrent_file, 'rb').read()) self.announce = self.torrent_data['announce'] self.info = self.torrent_data['info'] self.info_hash = hashlib.sha1(bencoding.bencode(self.torrent_data['info'])).digest() self.peer_id = 'liutorrent1234567890' self.uploaded = 0 self.downloaded = 0 self.port = 6881 # how do I choose a port? randomly within the unreserved range? self.filename = os.path.join(os.getcwd(), self.info['name'].decode('utf-8')) # for now, single file only # handshake: <pstrlen><pstr><reserved><info_hash><peer_id> self.handshake = ''.join([chr(19), 'BitTorrent protocol', chr(0) * 8, self.info_hash, self.peer_id]) self.length = self.info['length'] if 'length' in self.info.keys() \ else sum([f['length'] for f in self.info['files']]) self.piece_len = self.info['piece length'] self.block_len = BLOCK_LEN self.last_piece_len = self.length % self.piece_len self.num_pieces = self.length / self.piece_len + 1 * (self.last_piece_len != 0) self.last_piece = self.num_pieces - 1 # TODO: do I need that? self.last_block_len = self.piece_len % self.block_len self.blocks_per_piece = self.piece_len / self.block_len + 1 * (self.last_block_len != 0) #Pieces/need_blocks data: need_pieces BitArray represents the pieces that I need and have not requested; #need_blocks is a list of BitArray, each of which keeps track of blocks not yet requested self.need_pieces = BitArray(bin='1' * self.num_pieces) self.need_blocks = [BitArray(bin='1' * self.blocks_per_piece) for i in range(self.num_pieces)] self.have_pieces = BitArray(bin='0' * self.num_pieces) self.have_blocks = [BitArray(bin='0' * self.blocks_per_piece) for i in range(self.num_pieces)] self.pieces = defaultdict(self.blocklist) # index : array of blocks self.piece_hashes = self.get_piece_hashes() self.initialize_file(self.filename) self.info_from_tracker = self.update_info_from_tracker() self.peers = self.get_peers() self.active_peers = [] self.num_connected = 0 self.max_connections = MAX_CONNECTIONS
def get_info_hash(self): torrent_bytes = self.session.get( f"{self.DOWNLOAD_URL}{self.topic['id']}") if not torrent_bytes.ok: raise TVShowsSkipTopicError( 'Couldn\t get torrent file', self.topic['title']) return torrent_bytes = torrent_bytes.content _decoded = bdecode(torrent_bytes)[b'info'] info_hash = hashlib.sha1(bencode(_decoded)).hexdigest().upper() if not info_hash: raise TVShowsSkipTopicError( 'Couldn\t calculate torrent hash', self.topic['title']) return if info_hash == self.topic['info_hash']: raise TVShowsSkipTopicError( 'Hashes are equal', self.topic['title']) return manager.update_file(self.topic, torrent_bytes) return info_hash
def infohash(fname): objTorrentFile = open(fname, "rb") decodedDict = bencoding.bdecode(objTorrentFile.read()) info_hash = hashlib.sha1(bencoding.bencode( decodedDict[b"info"])).hexdigest() return info_hash
def get_torr_info_hash(data): import hashlib, bencoding bencode_dict = bencoding.bdecode(data) return hashlib.sha1(bencoding.bencode( bencode_dict[b"info"])).hexdigest()
# 'numwant': '', #Optional. Number of peers that the client would like to receive from the tracker. This value is permitted to be zero. If omitted, typically defaults to 50 peers. # 'key': '', #Optional. An additional client identification mechanism that is not shared with any peers. It is intended to allow a client to prove their identity should their IP address change. # 'trackerid': '' # Optional. If a previous announce contained a tracker id, it should be set here. } encoded_params = parse.urlencode(params) url = tracker_url + "?" + encoded_params print(url) with request.urlopen(url) as req: reponse = req.read().decode('ISO-8859-1') print(reponse) l = [x.encode() for x in reponse] l.reverse() dict_reponse = bencoding.bdecode(l, 'UTF-8') # print(repr(dict_reponse)) if ("failure reason" in dict_reponse): print('Erreur tracker:', dict_reponse['failure reason']) else: if ("warning message" in dict_reponse): print('Avertissement tracker:', dict_reponse['warning message']) interval = dict_reponse['interval'] min_interval = dict_reponse['min interval'] tracker_id = dict_reponse['tracker id'] if 'tracker id' in dict_reponse else '' complete = dict_reponse['complete'] incomplete = dict_reponse['incomplete'] peers = dict_reponse['peers'] if (type(peers) is collections.OrderedDict):# dict model pass else:# binary model
def update_info_from_tracker(self): tracker_response = requests.get(self.announce, params=self.get_params()) return bencoding.bdecode(tracker_response.text)
def __init__(self, file_path): if os.path.isfile(file_path) and file_path.split('.')[-1] == 'torrent': with open(file_path, 'rb') as f: self.metaData = bencoding.bdecode(f.read()) else: raise ValueError('Invalid torrent file') self._announce = self.metaData[b'announce'] if b'private' in self.metaData[b'info']: self._isPrivate = True if int( self.metaData[b'info'][b'private']) == 1 else False else: self._isPrivate = False self._pieces = self.metaData[b'info'][b'pieces'] self._piece_length = self.metaData[b'info'][b'piece length'] if b'announce-list' not in self.metaData: self._trackers = [self._announce] else: self._trackers = self.metaData[b'announce-list'] self._trackers = [ tracker for sublist in self._trackers for tracker in sublist if b'ipv6' not in tracker ] if b'creation date' in self.metaData: self._creationDate = self.metaData[b'creation date'] if b'comment' in self.metaData: self._comment = self.metaData[b'comment'] if b'created by' in self.metaData: self._createdBy = self.metaData[b'created by'] if b'encoding' in self.metaData: self._encoding = self.metaData[b'encoding'] if b'files' not in self.metaData[b'info']: self.mode = 'single' self._total_length = self.metaData[b'info'][b'length'] if b'md5sum' in self.metaData: self._md5sum = self.metaData[b'info'][b'md5sum'] else: self.mode = 'multiple' self.files = self.metaData[b'info'][b'files'] # Man Made stuff here onwards # self.Fractures stores File finish indexes self.files, self._total_length, self.fractures = self.__parse_files( ) self.number_of_pieces = math.ceil(self._total_length / self._piece_length) print("MODE:", self.mode) print("TOTAL LENGTH:", self._total_length) print("PIECE_LEN:", self._piece_length) print("NO. OF PIECES:", self.number_of_pieces) print("LAST PIECE LEN:", self._total_length % self._piece_length) print("NO. OF PIECE HASHES", len(self._pieces) / 20) self.name = self.metaData[b'info'][b'name'] # Usage depends on mode self.info_hash = sha1(bencoding.bencode( self.metaData[b'info'])).digest() self.peers = []
def _get_hash_file(path): with open(path, "rb") as f: decodedDict = bdecode(f.read()) hash_ = sha1(bencode(decodedDict[b'info'])).hexdigest() return str(hash_)
announce_delay = 180 arguments = sys.argv if (len(arguments) > 1): if ("--help" in arguments): print("-t <torrent file> -mu <max_upload in MB> -md <max_down in MB> -su <min_speed in KB/s> <max_speed in KB/s> -sd <min_speed in KB/s> <max_speed in KB/s>") sys.exit() else: max_down = 0 max_upload = 0 speed_up = (800, 3000) speed_down = (800, 2000) if ("-f" in arguments): torrent_file = open(arguments[arguments.index("-f") + 1], "rb") torrent_decoded = bencoding.bdecode(torrent_file.read()) announce_params["info_hash"] = codecs.decode(hashlib.sha1(bencoding.bencode(torrent_decoded[b"info"])).hexdigest(), "hex") torrent_length = (len(torrent_decoded[b"info"][b"pieces"]) / 20) * torrent_decoded[b"info"][b"piece length"] announce_url = torrent_decoded[b"announce"] print("torrent size: %iMB" % (torrent_length // 1024 // 1024)) max_upload = random.randrange(40, 80) * torrent_length // 100 max_down = random.randrange(1, 8) * torrent_length // 100 if ("-mu" in arguments): max_upload = int(arguments[arguments.index("-mu") + 1]) * 1024 * 1024 if ("-md" in arguments): max_down = int(arguments[arguments.index("-md") + 1]) * 1024 * 1024 if ("-su" in arguments): speed_up = (int(arguments[arguments.index("-su") + 1]), int(arguments[arguments.index("-su") + 2])) if ("-sd" in arguments): speed_down = (int(arguments[arguments.index("-sd") + 1]), int(arguments[arguments.index("-sd") + 2]))
import os, bencoding, hashlib for f_name in os.listdir('1'): if f_name.endswith('.torrent'): # print(f_name) objTorrentFile = open("1/%s" % f_name, "rb") decodedDict = bencoding.bdecode(objTorrentFile.read()) info_hash = hashlib.sha1(bencoding.bencode( decodedDict[b"info"])).hexdigest() print('magnet:?xt=urn:btih:%s' % info_hash)