Beispiel #1
0
    def setmagnetlink(self, wantmodified):
        """
        Set magnet link (note could easily be modified to return torrentdata or torrentfile if wanted)
        - assume that metadata already fetched but that _metadata.files not converted to _list yet (as that process  will use this data.
        :return:
        """
        if not self._metadata:
            raise CodingException(
                message="Must have fetched metadata before read torrentdata")
        ff = [
            f for f in self._metadata["files"]
            if f.get("format") == "Archive BitTorrent"
        ]
        if not len(ff) == 1:
            raise CodingException(
                message='Should be exactly one "Archive BitTorrent" file')
        torrentfilemeta = ff[0]
        torrentfileurl = "{}{}/{}".format(config["archive"]["url_download"],
                                          self.itemid, torrentfilemeta["name"])
        torrentcontents = httpget(torrentfileurl, wantmime=False)
        self.torrentdata = bencode.bdecode(
            torrentcontents)  # Convert to a object
        assert (bencode.bencode(self.torrentdata) == torrentcontents)
        hash_contents = bencode.bencode(self.torrentdata['info'])
        digest = hashlib.sha1(hash_contents).digest()
        b32hash = base64.b32encode(digest)  # Get the hash of the torrent file
        # Now revise the data since IA torrents as of Dec2017 have issues

        if wantmodified:
            # The trackers at bt1 and bt2 are http, but they dont support webtorrent anyway so that doesnt matter.
            webtorrenttrackerlist = [
                'wss://tracker.btorrent.xyz',
                'wss://tracker.openwebtorrent.com', 'wss://tracker.fastcast.nz'
            ]
            self.torrentdata["announce-list"] += [
                [wtt] for wtt in webtorrenttrackerlist
            ]
            # Note announce-list is never empty after this, so can ignore announce field
            #  Replace http with https (as cant call http from https) BUT still has cors issues
            # self.torrentdata["url-list"] = [ u.replace("http://","https://") for u in self.torrentdata["url-list"] ]
            self.torrentdata["url-list"] = [config["gateway"]["url_download"]
                                            ]  # Has trailing slash
            externaltorrenturl = "{}{}".format(
                config["gateway"]["url_torrent"],
                self.itemid)  # Intentionally no file name, we are modifying it
        else:
            externaltorrenturl = "{}{}/{}".format(
                config["archive"]["url_download"], self.itemid,
                torrentfilemeta["name"])
        magnetlink = ''.join([
            'magnet:?xt=urn:btih:', b32hash.decode('ASCII'),
            ''.join(['&tr=' + urllib.parse.quote_plus(t[0]) for t in self.torrentdata['announce-list']]),
            ''.join(['&ws=' + urllib.parse.quote_plus(t) \
                     for t in self.torrentdata['url-list']]),
            '&xs=', urllib.parse.quote_plus(externaltorrenturl),
        ])
        self._metadata["metadata"]["magnetlink"] = magnetlink
        return
Beispiel #2
0
    def modifiedtorrent(cls, itemid, wantmodified=True, verbose=False):
        # Assume its named <itemid>_archive.torrent
        torrentfilename = itemid + "_archive.torrent"
        torrentfileurl = "{}{}/{}".format(config["archive"]["url_download"], itemid, torrentfilename)
        try:
            torrentcontents = httpget(torrentfileurl, wantmime=False)
        except (requests.exceptions.HTTPError, TransportURLNotFound) as e:
            logging.warning("Inaccessible torrent at {}, {}".format(torrentfileurl, e))
            return  # Its ok if cant get a torrent
        try:
            # noinspection PyAttributeOutsideInit
            torrentdata = bencode.bdecode(torrentcontents)  # Convert to a object  XXX-do we use this except here
        except bencode.DecodingException as e:
            # Probably a magneturi.bencode.DecodingException - there are lots of bad torrents, mostly skipped cos files too big (according to Aaron Ximm)
            logging.warning("Bad Torrent file at: {}".format(torrentfileurl))
            return  # Dont need to throw an error - we'll just skip it
        assert (bencode.bencode(torrentdata) == torrentcontents)
        hash_contents = bencode.bencode(torrentdata['info'])
        digest = hashlib.sha1(hash_contents).digest()
        b32hash = base64.b32encode(digest)  # Get the hash of the torrent file
        b32hashascii = b32hash.decode('ASCII')
        # Now possible revise the data since IA torrents as of Dec2017 have issues, this doesnt change the hash.

        if wantmodified:  # Normally we want the torrent file modified to support WebTorrent and not use HTTP URLs
            # The trackers at bt1 and bt2 are http, but they dont support webtorrent anyway so that doesnt matter.
            webtorrenttrackerlist = ['wss://tracker.btorrent.xyz', 'wss://tracker.openwebtorrent.com',
                                     'wss://tracker.fastcast.nz']
            torrentdata["announce-list"] += [[wtt] for wtt in webtorrenttrackerlist]
            # Note announce-list is never empty after this, so can ignore announce field
            #  Replace http with https (as cant call http from https) BUT still has cors issues
            # torrentdata["url-list"] = [ u.replace("http://","https://") for u in torrentdata["url-list"] ]
            torrentdata["url-list"] = [config["gateway"]["url_download"]]  # Has trailing slash
            externaltorrenturl = "{}{}".format(config["gateway"]["url_torrent"],
                                               itemid)  # Intentionally no file name, we are modifying it
        else:
            externaltorrenturl = "{}{}/{}".format(config["archive"]["url_download"], itemid, torrentfilename)
        magnetlink = ''.join([
            'magnet:?xt=urn:btih:', b32hashascii,
            ''.join(['&tr=' + urllib.parse.quote_plus(t[0]) for t in torrentdata['announce-list']]),
            ''.join(['&ws=' + urllib.parse.quote_plus(t)
                     for t in torrentdata['url-list']]),
            '&xs=', urllib.parse.quote_plus(externaltorrenturl),
        ])
        MagnetLinkService.archiveidset(itemid, magnetlink, verbose)  # Cache it
        if verbose: logging.info("New magnetlink for item: {}, {}".format(itemid, magnetlink))
        # We should probably extract the b32hashascii from the magnetlink if we already have one
        MagnetLinkService.btihset(b32hashascii, magnetlink, verbose)  # Cache mapping from torrenthash to magnetlink
        return torrentdata
Beispiel #3
0
 def torrent(self, headers=True, verbose=False):
     """
     Output the torrent
     :return:
     """
     mimetype = "application/x-bittorrent"
     data = bencode.bencode(self.torrentdata)
     return {"Content-type": mimetype, "data": data} if headers else data
Beispiel #4
0
 def torrent(self, headers=True, verbose=False, **kwargs):
     """
     Output the torrent
     :return:
     """
     mimetype = "application/x-bittorrent"
     data = bencode.bencode(self.torrentdata)   # Set in ArchiveItem.new > setmagnetlink
     return {"Content-type": mimetype, "data": data} if headers else data
Beispiel #5
0
def from_torrent_data(torrent_contents):
    """
    return a magnet URI given Bittorrent torrent file content
    """
    metadata = bencode.bdecode(torrent_contents)
    hash_contents = bencode.bencode(metadata['info'])
    digest = hashlib.sha1(hash_contents).digest()
    b32hash = base64.b32encode(digest)
    return 'magnet:?xt=urn:btih:%s' % b32hash.decode('ASCII')
Beispiel #6
0
    def get_hash_from_torrent(self):
        from magneturi import bencode
        import hashlib

        self.download_torrent()

        decodedDict = bencode.bdecode(self.content)
        info_hash = hashlib.sha1(bencode.bencode(
            decodedDict["info"])).hexdigest()
        return info_hash
Beispiel #7
0
 def torrent(self, verbose=False, headers=False, **kwargs):
     torrenturl = self.torrenturl(
         verbose=verbose
     )  # NoContentException if not found # TODO-PERMS unused can delete this line?
     data = bencode.bencode(
         ArchiveItem.modifiedtorrent(self.itemid(),
                                     wantmodified=True,
                                     verbose=verbose))
     mimetype = "application/x-bittorrent"
     return {"Content-type": mimetype, "data": data} if headers else data
Beispiel #8
0
def from_torrent_data(torrent_contents):
    """
    return a magnet URI given Bittorrent torrent file content
    """
    metadata = bencode.bdecode(torrent_contents)
    hash_contents = bencode.bencode(metadata['info'])
    digest = hashlib.sha1(hash_contents).digest()
    b32hash = base64.b32encode(digest)

    if 'announce-list' in metadata:
        tracker_list = ''.join(['&tr='+urllib.parse.quote_plus(t[0]) \
                                for t in metadata['announce-list']])
    elif 'announce' in metadata:
        tracker_list = '&tr='+urllib.parse.quote_plus(metadata['announce'])
    else:
        tracker_list = ''

    result = ''.join([b32hash.decode('ASCII'), tracker_list])
    return 'magnet:?xt=urn:btih:%s' % result