Exemple #1
0
 def _verify_download(self, file_name):
     try:
         bencodepy.decode_from_file(file_name)
     except bencodepy.DecodingError as e:
         logger.debug('Failed to validate torrent file: {0}'.format(str(e)))
         logger.debug('Result is not a valid torrent file')
         return False
     return True
Exemple #2
0
 def __init__(self, torrent_file, file_extract = None):
     '''
     Initialise various variables for a torrent.
     torrent_file must be path to .torrent file
     Currently this handles only single file case.
     '''
     if file_extract == None:
         self.file_extract = decode_from_file(torrent_file)
     else:
         self.file_extract = file_extract
     self.tracker = []
     if b'announce-list' in self.file_extract:
         for i in self.file_extract[b'announce-list']:
             self.tracker.append(i[0].decode())
     else:
         self.tracker = [self.file_extract[b'announce'].decode()]
     if b'encoding' in self.file_extract:
         self.encoding = self.file_extract[b'encoding'].decode()
     else:
         self.encoding = 'UTF-8'
     self.piece_len = self.file_extract[b'info'][b'piece length']
     self.piece = self.file_extract[b'info'][b'pieces']
     self.name = self.file_extract[b'info'][b'name'].decode()
     self.length = self.file_extract[b'info'][b'length']
     self.print_file_info()
Exemple #3
0
def make_magnet_from_file(file):
    metadata = bencodepy.decode_from_file(file)
    subj = metadata[b'info']
    hashcontents = bencodepy.encode(subj)
    digest = hashlib.sha1(hashcontents).digest()
    b32hash = base64.b32encode(digest).decode()
    return 'magnet:?' + 'xt=urn:btih:' + b32hash
Exemple #4
0
def magnetCheck(stringPassed):
    if "magnet:?xt=" in stringPassed[:11]:
        addTorrent(stringPassed)
    elif os.path.isfile(stringPassed) and stringPassed.endswith('.torrent'):
        metadata = bencodepy.decode_from_file(stringPassed)
        subj = metadata[b'info']
        hashcontents = bencodepy.encode(subj)
        digest = hashlib.sha1(hashcontents).digest()
        b32hash = base64.b32encode(digest).decode()
        convertedMagnet = 'magnet:?'\
            + 'xt=urn:btih:' + b32hash\
            + '&dn=' + metadata[b'info'][b'name'].decode()\
            + '&tr=' + metadata[b'announce'].decode()\
            + '&xl=' + str(metadata[b'info'][b'piece length'])
        addTorrent(convertedMagnet)
    elif stringPassed.startswith('http') and stringPassed.endswith('.torrent'):
        addTorrent(stringPassed)
    elif stringPassed.startswith('http') and not stringPassed.endswith('.torrent'):
        fd, path = tempfile.mkstemp(suffix=".torrent")
        try:
            with os.fdopen(fd, 'wb') as tmp:
                tmp.write(s.get(stringPassed, allow_redirects=True).content)
                magnetCheck(path)
        finally:
            os.remove(path)
    else:
        console.print("Invalid input. Exiting...", style="red")
Exemple #5
0
def total_size_files_torrent(file_name):
    try:
        parsed = bencodepy.decode_from_file(file_name)
    except bencodepy.exceptions.DecodingError as e:
        print("Error parsing {}: {}".format(file_name, e))
        return 0
    else:
        file_list = parsed.get(b'info').get(b'files')
        return sum(item[b'length'] for item in file_list)
 def search_by_hash(self, torr_hash, *dst):
     """
     Compare a torrent hash with a list of torrents and returns those who
     match
     """
     if not isinstance(torr_hash, bytes):
         torr_hash = torr_hash.encode()
     for d in dst:
         d_hash = bencodepy.decode_from_file(d)[b"info"][b"pieces"]
         if torr_hash == d_hash:
             yield d
Exemple #7
0
    def from_file(cls, filename: str, **kwargs):
        dictionary = cast(OrderedDict, bencodepy.decode_from_file(filename))
        download_info = DownloadInfo.from_dict(dictionary[b'info'])

        if b'announce-list' in dictionary:
            announce_list = [[url.decode() for url in tier]
                             for tier in dictionary[b'announce-list']]
        else:
            announce_list = [[dictionary[b'announce'].decode()]]

        return cls(download_info, announce_list, **kwargs)
Exemple #8
0
    def from_file(cls, filename: str, **kwargs):
        dictionary = cast(OrderedDict, bencodepy.decode_from_file(filename))
        download_info = DownloadInfo.from_dict(dictionary[b'info'])

        if b'announce-list' in dictionary:
            announce_list = [[url.decode() for url in tier]
                             for tier in dictionary[b'announce-list']]
        else:
            announce_list = [[dictionary[b'announce'].decode()]]

        return cls(download_info, announce_list, **kwargs)
def make_magnet_from_file(file):
    metadata = bencodepy.decode_from_file(file)
    subj = metadata[b'info']
    hashcontents = bencodepy.encode(subj)
    digest = hashlib.sha1(hashcontents).digest()
    b32hash = base64.b32encode(digest).decode()
    return 'magnet:?'\
             + 'xt=urn:btih:' + b32hash\
             + '&dn=' + metadata[b'info'][b'name'].decode()\
             + '&tr=' + metadata[b'announce'].decode()\
             + '&xl=' + str(metadata[b'info'][b'length'])
Exemple #10
0
def parse(path):
    """Parse the given torrent file and return `Torrent` object.
    """
    logger.info('Started parsing .torrent file')
    res = bencodepy.decode_from_file(path)
    return Torrent(announce=res[b'announce'],
                   announce_list=res.get(b'announce-list', []),
                   comment=res.get(b'comment', ''),
                   created_by=res.get(b'created by', ''),
                   created_at=res.get(b'creation date'),
                   url_list=res.get(b'url-list'),
                   info=res.get(b'info'))
Exemple #11
0
def make_magnet_from_torrent_file(file):
    metadata = bencodepy.decode_from_file(file)
    subj = metadata.get(b"info", {})
    hashcontents = bencodepy.encode(subj)
    digest = hashlib.sha1(hashcontents).digest()
    b16hash = base64.b16encode(digest).decode().lower()
    return ("magnet:?" + "xt=urn:btih:" + b16hash + "&dn=" +
            metadata.get(b"info", {}).get(b"name", b"").decode() + "&tr=" +
            metadata.get(b"announce", b"").decode() + "".join([
                "&tr=" + tr.decode()
                for trlist in metadata.get(b"announce-list", [])
                for tr in trlist if tr.decode().strip()
            ]) + "&xl=" + str(metadata.get(b"info", {}).get(b"length")))
Exemple #12
0
def main():
    arg = ArgumentParser.ArgumentParser()
    arg.do_parsing()
    torrent_dict = decode_from_file(os.getcwd() + "\\" + arg.torrent_file_url)
    info_dict = torrent_dict[b"info"]
    piece_length = info_dict[b"piece length"]
    piece_count = int(len(info_dict[b"pieces"])/20)
    file_name = info_dict[b"name"]
    file_name = file_name.decode("utf-8")
    if b"files" in info_dict:
       print(info_dict[b"files"])
    global chunk_number
    chunk_number = int(piece_length/chunk_size)
    if piece_length % chunk_size != 0:
        chunk_number += 1
    global pieces_bitfield
    pieces_bitfield = [None] * piece_count
    global currently_used
    currently_used = [False] * piece_count
    dictionary_sha1 = helper.get_sha1(encode(info_dict))
    bencoded_info_dict = encode(info_dict)
    info_hash = helper.get_sha1(bencoded_info_dict)
    peer_id = os.urandom(20)
    listen_port = 2710
    file_length = info_dict[b"length"]
    payload = {"info_hash": info_hash, "peer_id": peer_id,
               "port": listen_port, "uploaded": 0, "downloaded": 0, "left": file_length}
    r = requests.get(torrent_dict[b"announce"], params=payload)
    response = decode(r.content)
    if b"failure reason" in response:
        return
    interval = response[b"interval"]
    peers = response[b"peers"]
    peers_list = []
    peer_num = len(peers)/6
    for elem in range(int(peer_num)):
        start_ind = 6 * elem
        peer_ip = socket.inet_ntoa(peers[start_ind:start_ind+4])
        peer_port = struct.unpack("!H", peers[start_ind+4:start_ind+6])[0]
        peers_list.append((peer_ip, peer_port))
    print(peers_list)
    for elem in peers_list:
        test_ip = elem[0]
        test_port = elem[1]
        cur_thread = Thread(target=do_for_each_peer,
                            args=(dictionary_sha1, test_ip, test_port, piece_length, info_dict, peer_id, file_length,
                                  file_name))
        # do_for_each_peer(dictionary_sha1, test_ip, test_port, piece_length, info_dict,peer_id)
        # print(cur_thread.name)
        cur_thread.start()
Exemple #13
0
def generate_magnet_from_file(file) :
    meta_data     = bencodepy.decode_from_file(file)
    meta_info     = meta_data[b'info']
    meta_announce = meta_data[b'announce']

    hash_contents = bencodepy.encode(meta_info)
    digest        = hashlib.sha1(hash_contents).digest()
    b32hash       = base64.b32encode(digest).decode()

    return "magnet:?xt=urn:btih:{0}&dn={1}&tr={2}".format(
        b32hash,
        meta_info[b'name'].decode(),
        meta_announce.decode()
    )
Exemple #14
0
def make_magnet_from_file(file):  # Создание magnet ссылок из torrent файла
    try:
        metadata = bencodepy.decode_from_file(file)
    except:
        # print('Вы использовали доступное Вам количество торрент-файлов в сутки')
        return 'Вы использовали доступное Вам количество торрент-файлов в сутки'
    subj = metadata[b'info']
    hashcontents = bencodepy.encode(subj)
    digest = hashlib.sha1(hashcontents).digest()
    b32hash = base64.b32encode(digest).decode()
    return 'magnet:?'\
             + 'xt=urn:btih:' + b32hash\
             + '&dn=' + metadata[b'info'][b'name'].decode()\
             + '&tr=' + metadata[b'announce'].decode()\
    def have(self, *src_lst):
        """
        Check if the torrent is already in a watch directory.

        param src_lst: torrents to scan
        """
        hash_lst = {
            src: bencodepy.decode_from_file(src)[b"info"][b"pieces"]
            for src in src_lst if len(src)
        }
        if not hash_lst:
            return
        logger.debug("Searching if having the list %s…" % hash_lst.keys())
        for src, t in self._search_multiple_hash(hash_lst, self.targets):
            yield (src, t)
Exemple #16
0
def add_new_torrent_by_file(message):
    file_info = bot.get_file(message.document.file_id)
    downloaded_file = bot.download_file(file_info.file_path)
    torrent_file_name = "{}.torrent".format(time.strftime("%d%m%Y%H%M%S"))
    with open(torrent_file_name, "wb") as new_file:
        new_file.write(downloaded_file)
        metadata = bencodepy.decode_from_file(torrent_file_name)
        subj = metadata[b"info"]
        hashcontents = bencodepy.encode(subj)
        digest = hashlib.sha1(hashcontents).digest()
        b32hash = base64.b32encode(digest).decode()
        transmission = Transmission()
        add_result = transmission.add_torrent("magnet:?xt=urn:btih:" + b32hash)
        os.remove(torrent_file_name)
        return "Torrent was successfully added with ID #{0}".format(add_result)
Exemple #17
0
def bt2magnet(f):
    metadata = bencodepy.decode_from_file(f)
    # print(metadata)
    subj = metadata[b'info']
    hashcontents = bencodepy.encode(subj)
    digest = hashlib.sha1(hashcontents).digest()
    b32hash = base64.b32encode(digest).decode()
    print('magnet:?' + 'xt=urn:btih:' + b32hash + '&dn=' +
          metadata[b'info'][b'name'].decode() + '&tr=' +
          metadata[b'announce'].decode() + '&xl=' +
          str(metadata[b'info'][b'piece length']))
    return 'magnet:?'\
        + 'xt=urn:btih:' + b32hash\
        + '&dn=' + metadata[b'info'][b'name'].decode()\
        + '&tr=' + metadata[b'announce'].decode()\
        + '&xl=' + str(metadata[b'info'][b'piece length'])
 def __init__(self, parameters):
     self.parameter_parser = ParameterParser(parameters)
     # self.torrent_file_dict = getcwd() + "/" + self.parameter_parser.get_torrent_file_path()
     self.torrent_file_dict = decode_from_file(self.parameter_parser.get_torrent_file_path())
     self.tracker = ""
     self.backup_trackers = []
     if b'announce-list' in self.torrent_file_dict:
         self.backup_trackers = self.torrent_file_dict[b'announce-list']
     self.tracker = self.torrent_file_dict[b'announce']
     # print(self.torrent_file_dict[b'info'])
     self.info_parser = InfoDictParser(self.torrent_file_dict[b'info'])
     if self.info_parser.is_single_file_info():
         self.total_size = self.info_parser.get_file_size()
         print(self.info_parser.get_single_file_info()[b'name'])
         print(self.tracker.decode())
     self.register_with_tracker()
Exemple #19
0
def make_magnet_from_torrent_file(file):
    metadata = bencodepy.decode_from_file(file)
    subj = metadata.get(b'info', {})
    hashcontents = bencodepy.encode(subj)
    digest = hashlib.sha1(hashcontents).digest()
    b32hash = base64.b32encode(digest).decode()
    return 'magnet:?'\
             + 'xt=urn:btih:' + b32hash\
             + '&dn=' + metadata.get(b'info', {}).get(b'name', b'').decode()\
             + '&tr=' + metadata.get(b'announce', b'').decode()\
             + "".join([
                "&tr=" + tr.decode()
                for trlist in metadata.get(b'announce-list', [])
                for tr in trlist
                if tr.decode().strip()
             ])\
             + '&xl=' + str(metadata.get(b'info', {}).get(b'length'))
Exemple #20
0
 def __init__(self, path_to_torrent: str = "debian.torrent", path_to_save_dir: str = os.getcwd()):
     self.log_update_time = 6
     self.path_to_torrent = path_to_torrent
     self.torrent_dict = bencodepy.decode_from_file(self.path_to_torrent)
     self.info_hash = calculate_hash(bencodepy.encode(self.torrent_dict[b'info']))
     temp = self.torrent_dict[b'info'][b'pieces']
     self.pieces_hashes = [temp[i:i + 20] for i in range(0, len(temp), 20)]
     self.pieces_cnt = len(self.pieces_hashes)
     self.piece_length = self.torrent_dict[b'info'][b'piece length']
     self.peer_id = calculate_peer_id()
     self.file_name = self.torrent_dict[b'info'][b'name'].decode()
     self.full_result_filepath = path_to_save_dir + "/" + self.file_name
     self.received_pieces_mask = [0] * self.pieces_cnt
     self.full_length = self.calculate_full_length()
     self.downloaded_bytes = None
     self.connected_peers = []
     self.log_lock = threading.Lock()
     self.pieces_lock = threading.Lock()
Exemple #21
0
def magnetCheck(stringPassed):
    if "magnet:?xt=" in stringPassed[:11]:
        #print("YAY its a magnet link")
        addTorrent(stringPassed)
    else:
        if os.path.isfile(stringPassed) and stringPassed.endswith('.torrent'):
            metadata = bencodepy.decode_from_file(stringPassed)
            subj = metadata[b'info']
            hashcontents = bencodepy.encode(subj)
            digest = hashlib.sha1(hashcontents).digest()
            b32hash = base64.b32encode(digest).decode()
            convertedMagnet = 'magnet:?'\
                + 'xt=urn:btih:' + b32hash\
                + '&dn=' + metadata[b'info'][b'name'].decode()\
                + '&tr=' + metadata[b'announce'].decode()\
                + '&xl=' + str(metadata[b'info'][b'piece length'])
            # print(convertedMagnet)
            addTorrent(convertedMagnet)
Exemple #22
0
def parse_torrent_file(filename):
    """
    Decode Torrent file and sig out data that matters: trackers, and infohash
    """
    try:
        logger.info('Parsing torrent file {0}'.format(filename))
        data = b.decode_from_file(filename)
    except (b.DecodingError, IOError) as e:
        logger.critical('Unable to parse torrent file {0}: {1}'.format(
            filename, e))
        raise

    trackers = [data[b'announce'].decode()] + flatten(data[b'announce-list'])
    trackers = set(trackers)

    infohash = sha1(b.encode(data[b'info'])).hexdigest()

    return trackers, infohash
Exemple #23
0
def magnetCheck(stringPassed):
    if "magnet:?xt=" in stringPassed[:11]:
        addTorrent(stringPassed)
    elif os.path.isfile(stringPassed) and stringPassed.endswith('.torrent'):
        metadata = bencodepy.decode_from_file(stringPassed)
        subj = metadata[b'info']
        hashcontents = bencodepy.encode(subj)
        digest = hashlib.sha1(hashcontents).digest()
        b32hash = base64.b32encode(digest).decode()
        convertedMagnet = 'magnet:?'\
            + 'xt=urn:btih:' + b32hash\
            + '&dn=' + metadata[b'info'][b'name'].decode()\
            + '&tr=' + metadata[b'announce'].decode()\
            + '&xl=' + str(metadata[b'info'][b'piece length'])
        addTorrent(convertedMagnet)
    elif stringPassed.startswith('http') and stringPassed.endswith('.torrent'):
        addTorrent(stringPassed)
    else:
        print(f"{Fore.RED}Invalid input. Exiting...")
Exemple #24
0
	def __init__(self, filename):

		self.metainfo_file_path = (filename + ".torrent").encode('utf-8')
		self.decoded_metainfo = decode_from_file(self.metainfo_file_path)
	
		self.info_dict = self.decoded_metainfo[b'info']
	
		self.info_hash = hashlib.sha1()
		for key in self.info_dict.keys():
			self.info_hash.update(key)

		for value in self.info_dict.values():
			self.info_hash.update(bytearray(value))

		self.announce = self.decoded_metainfo[b'announce'].decode('utf-8')
		self.filename = filename
		self.piece_length = self.info_dict[b'piece length']
		self.file_length = self.info_dict[b'length']
		self.pieces = self.info_dict[b'pieces']
		self.num_pieces = math.ceil(self.info_dict[b'length']/self.info_dict[b"piece length"])
Exemple #25
0
def collect_torrents(torrent_dirs):
    print("Getting file/folder names from torrents...")
    torrent_files = set()
    target_names = set()
    for d in torrent_dirs:
        for x in os.scandir(d):
            if not x.is_file() or not x.name.endswith(".torrent"):
                continue

            try:
                path = os.path.abspath(os.path.join(os.getcwd(), x.path))
                data = decode_from_file(path)
                name = data[b"info"][b"name"].decode("utf-8", errors="replace")
            except (OSError, DecodingError, KeyError) as e:
                print("Couldn't check '{}': {}".format(path, e))
            else:
                torrent_files.add(path)
                target_names.add(name)

    return torrent_files, target_names
    def filter(self, torrent):
        """
        Apply filter and return the match as a boolean

        :param torrent: path of torrent file to apply the filters on
        """
        def tracker_matches(f_tracker, tracker):
            regex = r"^.*://%s(:\d*|)(/.*|)$"
            exclude = f_tracker.startswith("!")
            if exclude:
                f_tracker = f_tracker[1:]
                return not re.match(regex % f_tracker, tracker)
            else:
                return re.match(regex % f_tracker, tracker)

        match = True
        if (self.filters.get("trackers", False)
                and len(self.filters["trackers"])):
            try:
                decoded_torrent = bencodepy.decode_from_file(torrent)
                tracker = decoded_torrent[b"announce"].decode()
                logger.debug("Tracker of %s: %s" % (torrent, tracker))
                if isinstance(self.filters["trackers"], str):
                    f_tracker = self.filters["trackers"]

                    match = match and tracker_matches(f_tracker, tracker)
                else:
                    matches = []
                    for f_tracker in self.filters["trackers"]:
                        matches.append(tracker_matches(f_tracker, tracker))
                    match = match and any(matches)
            except Exception as e:
                logger.info("%s doesn't contain a announce field, pass" %
                            torrent)
                logger.debug(e)
                pass
        logger.debug("%s matches %s" % (torrent, match or "no filter"))
        return match
Exemple #27
0
    async def get_magnet(self, location: str) -> str:
        """
        Will take a file location or an internet location for a torrent file.
        The magnet URL for that torrent is then resolved and returned.

        If the location parameter is already detected to be a magnet URL,
        it will instantly return it.

        Parameters
        ----------
        location: str
            A file location or web address.

        Returns
        -------
        str
            The magnet URL for the torrent at the given location.
        """
        if location.startswith("magnet:?"):
            return location
        elif location.endswith(".torrent"):
            async with self.session.get(location) as resp:
                torrent_bytes = await resp.read()
                metadata = bencodepy.decode(torrent_bytes)
        else:
            metadata = bencodepy.decode_from_file(location)

        subject = metadata[b'info']

        hash_data = bencodepy.encode(subject)
        digest = hashlib.sha1(hash_data).digest()
        base32_hash = base64.b32encode(digest).decode()

        return "magnet:?"\
            + f"xt=urn:btih:{base32_hash}"\
            + f"&dn={metadata[b'info'][b'name'].decode()}"\
            + f"&tr={metadata[b'announce'].decode()}"
 def _search_multiple_hash(self, torrent_lst, dst_lst):
     """
     Search in a list of hash which ones match with the destination list
     """
     if len(torrent_lst) == 0:
         return
     for dst in dst_lst:
         dst = os.path.expanduser(dst)
         if os.path.isdir(dst):
             logger.debug("Scanning all torrents into %s" % dst)
             for t, h in self._search_multiple_hash(
                     torrent_lst, glob.glob(os.path.join(dst,
                                                         "*.torrent"))):
                 yield t, h
             continue
         try:
             dst_hash = bencodepy.decode_from_file(dst)[b"info"][b"pieces"]
             for t, h in torrent_lst.items():
                 if dst_hash == h:
                     logger.debug("Hash matches for %s", dst)
                     yield t, dst
         except Exception as e:
             logger.error("Error when opening the torrent %s" % dst)
             logger.error(e)
def main():

    client = Client('127.0.0.1', 9999, 'UR.mp3')
    #parse metainfo file
    metainfo_file_path = "UR.mp3.torrent".encode('utf-8')
    decoded_metainfo = decode_from_file(metainfo_file_path)

    info_dict = decoded_metainfo[b'info']

    info_hash = hashlib.sha1()
    for key in info_dict.keys():
        info_hash.update(key)
        print("Key: " + str(key) + '\n')

    for value in info_dict.values():
        info_hash.update(bytearray(value))
        print("val: " + str(value) + '\n')

    print(info_hash)

    #Contact tracker and get list of peers

    #initiate handshaking with peers

    #download/upload chunks according to peer wire protocol
    #maintain state information for each connection with remote peer
    #should include bidirectional status
    #use status info to determine whether a chunk should be downloaded or uploaded
    #rarest first with randomization

    #message flow
    #choke, unchoke, interested, not interested

    #have

    #bitfield
    #sent after handshaking before any other messages
    #client should drop connection if bitfield is wrong length

    #request

    #piece

    #cancel (can be ignored)

    #implement commands

    def print_metainfo():
        print("IP/port    :  " + str(client.ip_addr) + "/" + str(client.port))
        print("ID        :  " + "someplaceholderstuff")
        print("metainfo file:  " + "UR.mp3.torrent")
        print("info hash    :  " + str(info_hash.hexdigest()))
        print("filename    :  " + "UR.mp3")
        print("piece length:  " + str(info_dict[b"piece length"]))
        print("file size:  " + str(info_dict[b"length"]))
        print("announce URL:  " + str(decoded_metainfo[b"announce"]))
        print("pieces' hashes:  ")
        num_pieces = math.ceil(info_dict[b"length"] /
                               info_dict[b"piece length"])
        print(num_pieces)
        print("other")

    #	for i in range(0, num_pieces):
    #		print(info_dict[b"pieces"][i:i+20+1].hexdigest())

    while True:
        command = input()
        #metainfo
        if (command == "metainfo"):
            print_metainfo()
Exemple #30
0
path_torrent_file = args.torrent_file
verbose = args.verbose

save_directory = args.directory
logging_time = int(args.t) if args.t else 30

signal.signal(signal.SIGINT, signal_handler)

if not os.path.exists(save_directory) or (not os.path.isdir(save_directory)):
    print("No such directory")
    exit()

if save_directory == "/":
    save_directory = os.getcwd()

my_ordred_dict = bencodepy.decode_from_file(path_torrent_file)
dict_hash = utils.compute_hash(bencodepy.encode(my_ordred_dict[b'info']))
my_peer_id = utils.random_peer_id()

hashes = my_ordred_dict[b'info'][b'pieces']

root_directory = ""
files = []
file = ()

if b'files' in my_ordred_dict[b'info'].keys():
    root_directory = str(my_ordred_dict[b'info'][b'name'], 'utf-8')
    if root_directory.endswith("/"): root_directory = root_directory[:-1]
    # if save_directory.endswith("/"): save_directory = save_directory[:-1]
    if not os.path.exists(save_directory + "/" + root_directory):
        os.mkdir(save_directory + "/" + root_directory)
    def parse_from_file(self,
                        file,
                        base='16',
                        size=0,
                        seed=1,
                        leech=1,
                        surrogated_id=''):
        '''
        This function, will parse the content of a *.torrent file, retrieving the fundamental values
        :param file: this value, represents the path to the *.torrent file
        :param base: this value, represents the base of hash you're gonna use to encode, by default 16
        :return: this function, returns a magnet instace with the fundamental values from the *.torrent file
        :rtype: MagnetInstance
        '''
        _hash = ''
        announce = ''
        display_name = ''
        announce_list = ''

        try:
            metadata0 = self.raw_parse_from_file(file)
            metadata = bencodepy.decode_from_file(file)  # Read from the file
            subj = metadata[b'info']
            # # Calculating hash
            try:
                hashcontents = bencodepy.encode(subj)
                digest = hashlib.sha1(hashcontents).digest(
                )  # Calculating the magnet hash 16, based on the metadata[b'info]
                if base == '16':
                    _hash = base64.b16encode(digest).decode().lower()
                else:
                    _hash = base64.b32encode(digest).decode().lower()
            except Exception as err:
                self.logger.error(err)

            try:
                display_name = self._eval_display_name(
                    metadata0)  # Gather display_name from the file
            except MagnetBuilderTorrentKeyDisplayNameError as err:
                self.logger.warning(err.message)

            try:
                announce = self._eval_announce(
                    metadata0)  # Gather announce from the file
            except MagnetBuilderTorrentAnnounceKeyError as err:
                self.logger.warning(err.message)

            try:
                announce_list = self._eval_announce_list(
                    metadata0)  # Gather announce_list from the file
            except MagnetBuilderTorrentAnnounceListKeyError as err:
                self.logger.warning(err.message)

            try:
                size = self._eval_size(
                    metadata0)  # Gather announce_list from the file
            except MagnetBuilderTorrentSizeKeyError as err:
                self.logger.warning(err.message)

            if announce_list is '':
                announce_list = announce

            ch_filter = chinese_filter()
            display_name = ch_filter.sub('', str(display_name))
            self.logger.debug0(
                '{0} Generated Uri from Torrent File: {1} with Hash [ {2} ]'.
                format(self.name, display_name, _hash))
            self.logger.debug('* Announce List {0}'.format(announce_list))
            print(_hash, str(display_name), announce_list, size, seed, leech,
                  surrogated_id)
            return MagnetInstance(_hash, str(display_name), announce_list,
                                  size, seed, leech, surrogated_id)
        except Exception as err:
            return MagnetInstance
def get_data_from_torrent(arg):
    # https://github.com/eweast/BencodePy
    global torrent_data
    # try to parse and decode the torrent file...
    try:

        # assign file_path based on the command line arg/param
        file_path = arg

        # call the decode_from_file() function that's a member of the bencodepy class`
        btdata = bencodepy.decode_from_file(file_path)

        # store the fresh, bencodepy decoded data in the global scope
        global btdata_backup
        btdata_backup = btdata

        # XXX test print XXX
        # print("\n\n::::::btdata backup  : \n\n", btdata_backup, "\n\n")

        # next, build the decoded dictionary through a series of iterative statements within the btdata OrderedDict object
        # the "builder" variable used for this we'll call decoded_dict
        decoded_dict = {}

        # for each of the key:value pairs in the OrderedDict, try to decode both the key and the value
        # finally, append the results to the builder dictionary : decoded_dict
        for x, y in btdata.items():

            # decode the key
            x = x.decode('UTF-8')
            # try to decode the value associated with the key...
            try:
                y = y.decode('UTF-8')
            except AttributeError:
                # if we can't decode the value, just pass it for now
                pass
            decoded_dict[x] = y

        # decode the array elements that exist as the value for the 'url-list' key in the decoded_dict
        for x, member in enumerate(decoded_dict['url-list']):
            decoded_dict['url-list'][x] = decoded_dict['url-list'][x].decode(
                'UTF-8')

        # decode the array elements that exist as the value for the 'announce-list' key in the decoded_dict
        # this has another layer of complexity compared to decoding the elements in the 'url-list', this is
        # because some of the elements of the decoded_dict['announce-list'] are arrays themselves, need a nested loop :
        for x, member in enumerate(decoded_dict['announce-list']):
            for y, member in enumerate(decoded_dict['announce-list'][x]):
                decoded_dict['announce-list'][x][y] = decoded_dict[
                    'announce-list'][x][y].decode('UTF-8')

        # store freshly bencodepy decoded info-ordered-dictionary
        global btdata_info_backup
        btdata_info_backup = decoded_dict['info']

        # decode the (sub)ordered-dictionary that exists as a value corresponding to the 'info' key inside the decoded_dict dictionary
        # access this (sub)ordered-dictionary with : decoded_dict['info']
        # use the appendage_dict={} in order to temporarily store the sub-ordered-dictionary, this will be appended to the decoded_dict at the correct 'info' key after traversal
        appendage_dict = {}
        for x, y in decoded_dict['info'].items():

            # decode the key
            x = x.decode('UTF-8')
            # try to decode the value associated with the key...
            try:
                # we don't want to decode the value at the pieces key... this is a byte string
                if x != 'pieces':
                    y = y.decode('UTF-8')

            except AttributeError:
                # if we can't decode the value, just pass it for now
                pass

            # append the key:value pair to the dictionary
            appendage_dict[x] = y

        # append the appendage_dict to the 'info' key of the decoded_dict dictionary, the same place where it came encoded from
        decoded_dict['info'] = appendage_dict

        # XXX test print XXX
        # print(decoded_dict)
        # XXX test print XXX

        # Do what you need to do with the torrent data.
        # You'll probably want to set some globals, such as
        # total_length, piece_length, number of pieces (you'll)
        # need to calculate that) etc. You might want to give
        # file_array its initial value here as an array of
        # empty binary sequences (b'') that can later be appended
        # to. There may be other values you want to initialize here.

        # instantiate an object to have the TorrentData class type
        # assign all of the key:value pairs to correspond to the relevant bit_torrent data
        # note : the number of pieces is thus determined by 'ceil( total length / piece size )'
        torrent_data = TorrentData(\
            decoded_dict['info']['name'],\
            decoded_dict['info']['length'],\
            decoded_dict['info']['length']/8,\
            decoded_dict['info']['piece length'],\
            decoded_dict['info']['piece length']/8,\
            math.ceil(decoded_dict['info']['length']/decoded_dict['info']['piece length']),\
            decoded_dict['announce'])

        #  XXX test print XXX
        # print('total length : ', total_length)
        # print('piece length : ', piece_length)
        # print('piece length bytes : ', piece_length_bytes)
        # print('number of pieces :', no_of_pieces)
        # print('announce url :', announce_url)
        # print('output file name : ', output_filename)
        # print(decoded_dict['info']['pieces'])
        # print('type :', type(decoded_dict['info']['pieces'])) # type of
        #  XXX test print XXX

        # reporting torrent :
        report_torrent(torrent_data)

    except:
        print(
            'Failed to parse input. Usage: python btClient.py torrent_file"\ntorrent_file must be a .torrent file'
        )
        sys.exit(2)

    return decoded_dict
Exemple #33
0
def open_torrent_url(url):
  """Mount the specified torrent and open it in the file browser

  Keyword arguments:
  url -- url to download the torrent file, path of torrent in filesystem, or magnet url
  """

  url_parsed = urlparse(url)
  
  
  # Magnet
  if url_parsed.scheme == 'magnet':
    print('MAGNET', url)
    query_params = parse_qs(url_parsed.query)
    
    magnet_params = {}
    if 'tr' in query_params:
      magnet_params['tr'] = query_params['tr']
    
    if magnet_params:
      encoded_params = '&' + urlencode(magnet_params, doseq=True)
    else:
      encoded_params = ''
    
    # For each torrent in the magnet
    for param_name, param_data in query_params.items():
      if param_name[:2] != 'xt':
        continue
      
      xt_data = param_data[0]
      
      btih = re.search(r'^urn:btih:([0-9a-fA-F]{40}|[2-7A-Z]{32})$', xt_data)
      if btih is not None:
        btih = btih.group(1)
        
        # Hex encoded
        if (len(btih) == 40):
          btih = btih.lower()
          
        # Base32 encoded
        else:
          btih = base64.b32decode(btih).hex()
        
        open_torrent_btih(btih, 'magnet:?xt=' + xt_data + encoded_params)
    
    return
    
    
  # Download torrent from URL
  if len(url_parsed.scheme):
    print('URL', url)
    torrent_file = os.path.join(config.torrent_dir, hashlib.md5(url.encode('utf-8')).hexdigest()+'.torrent')
    urllib.request.urlretrieve(url, torrent_file)
    url = torrent_file
  
  
  # Open torrent in file system
  if os.path.isfile(url):
    print('FILE', url)
    
    # Calculate bittorrent info hash
    metadata = bencodepy.decode_from_file(url)
    hashcontents = bencodepy.encode(metadata[b'info'])
    digest = hashlib.sha1(hashcontents).digest()
    btih = digest.hex()
    
    open_torrent_btih(btih, url)
    return
  
  
  print('Torrent URL is not supported')